android 添加系统服务
在android系统中, 许许多的系统服务都是在系统启动时加载启动的,
如: PowerManager, WifiManager, InputMethodManager, 等等;
注: 本文参考自RK所提供的一部份补丁, 若涉及侵权, 请及时与我联系.
本文主要用于记录如何添加一个(Pppoe拨号)系统服务:
1. 添加IXManager.aidl(AIDL)文件:
frameworks/base/pppoe/java/android/net/pppoe/IPppoeManager.aidl
package android.net.pppoe;
interface IPppoeManager
{
int getPppoeState();
boolean setupPppoe(String user, String iface, String dns1, String dns2, String password);
boolean startPppoe();
boolean stopPppoe();
String getPppoePhyIface();
}
frameworks/base/Android.mk中添加编译文件:
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \
core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
core/java/android/app/IActivityController.aidl \
core/java/android/app/IActivityPendingResult.aidl \
core/java/android/app/IAlarmManager.aidl \
core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/IProcessObserver.aidl \
core/java/android/app/ISearchManager.aidl \
core/java/android/app/ISearchManagerCallback.aidl \
core/java/android/app/IServiceConnection.aidl \
location/java/android/location/ILocationManager.aidl \
pppoe/java/android/net/pppoe/IPppoeManager.aidl
添加XManager.java
frameworks/base/pppoe/java/android/net/pppoe/PppoeManager.java
/*
* Copyright(C), 2009-2010, Fuzhou Rockchip Co. ,Ltd. All Rights Reserved.
*
* File: PppoeManager.java
* Desc:
* Usage:
* Note:
* Author: [email protected]
* Version:
* v1.0
* Log:
----Thu Sep 8 2011 v1.0
*/
package android.net.pppoe;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.net.DhcpInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.Handler;
import android.os.Message;
import android.os.Looper;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.util.Log;
import java.util.List;
public class PppoeManager {
private static final String TAG = "PppoeManager";
public static final boolean DEBUG = true;
private static void LOG(String msg) {
if ( DEBUG ) {
Log.d(TAG, msg);
}
}
/**
* Broadcast intent action
* indicating that PPPOE has been enabled, disabled, enabling, disabling, or unknown.
* One extra provides current state as an int.
* Another extra provides the previous state, if available.
*
* @see #EXTRA_PPPOE_STATE
* @see #EXTRA_PREVIOUS_PPPOE_STATE
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String PPPOE_STATE_CHANGED_ACTION
= "android.net.pppoe.PPPOE_STATE_CHANGED";
/**
* Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
*
* @see #PPPOE_STATE_DISABLED
* @see #PPPOE_STATE_DISABLING
* @see #PPPOE_STATE_INIT_ENABLED
* @see #PPPOE_STATE_ENABLING
* @see #PPPOE_STATE_UNKNOWN
*/
public static final String EXTRA_PPPOE_STATE = "pppoe_state";
/**
* The previous PPPOE state.
*
* @see #EXTRA_PPPOE_STATE
*/
public static final String EXTRA_PREVIOUS_PPPOE_STATE = "previous_pppoe_state";
public static final int PPPOE_STATE_CONNECTING = 0;
public static final int PPPOE_STATE_CONNECTED = 1;
public static final int PPPOE_STATE_DISCONNECTING = 2;
public static final int PPPOE_STATE_DISCONNECTED = 3;
public static final int PPPOE_STATE_UNKNOWN = 4;
IPppoeManager mService;
Handler mHandler;
private PppoeHandler mPppoeHandler;
/**
另一种做法:
static public IXManager getService()
{
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService(name);
sService = IXManager.Stub.asInterface(b);
return sService;
}
**/
public PppoeManager(IPppoeManager service, Handler handler) {
mService = service;
mHandler = handler;
if ( null == mPppoeHandler ) {
LOG("PppoeManager() : start 'pppoe handle thread'.");
HandlerThread handleThread = new HandlerThread("Pppoe Handler Thread");
handleThread.start();
mPppoeHandler = new PppoeHandler(handleThread.getLooper()/*, this*/);
}
}
private class PppoeHandler extends Handler {
private static final int COMMAND_START_PPPOE = 1;
private static final int COMMAND_STOP_PPPOE = 2;
private Handler mTarget;
public PppoeHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
int event;
LOG("PppoeHandler::handleMessage() : Entered : msg = " + msg);
switch (msg.what) {
case COMMAND_START_PPPOE:
try {
mService.startPppoe();
} catch (RemoteException e) {
Log.e(TAG, "startPppoe failed");
}
break;
case COMMAND_STOP_PPPOE:
try {
mService.stopPppoe();
} catch (RemoteException e) {
Log.e(TAG, "stopPppoe failed");
}
break;
default:
break;
}
}
}
public int getPppoeState() {
try {
return mService.getPppoeState();
} catch (RemoteException e) {
Log.e(TAG, "stopPppoe failed");
return -1;
}
}
public boolean startPppoe() {
return mPppoeHandler.sendEmptyMessage(PppoeHandler.COMMAND_START_PPPOE);
}
public boolean stopPppoe() {
return mPppoeHandler.sendEmptyMessage(PppoeHandler.COMMAND_STOP_PPPOE);
}
public boolean setupPppoe(String user, String iface, String dns1, String dns2, String password) {
try {
return mService.setupPppoe(user, iface, dns1, dns2, password);
} catch (RemoteException e) {
return false;
}
}
public String getPppoePhyIface() {
try {
return mService.getPppoePhyIface();
} catch (RemoteException e) {
return null;
}
}
}
再去看看真正干活的地方:XManagerService.java 也可用XService.java
frameworks/base/services/java/com/android/server/PppoeService.java
/*$_FOR_ROCKCHIP_RBOX_$*/
//$_rbox_$_modify_$_chenzhi_20120309: add for pppoe
/*
* Copyright(C), 2009-2010, Fuzhou Rockchip Co. ,Ltd. All Rights Reserved.
*
* File: PppoeService.java
* Desc:
* Usage:
* Note:
* Author: [email protected]
* Version:
* v1.0
* Log:
----Thu Sep 8 2011 v1.0
*/
package com.android.server;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.pppoe.IPppoeManager;
import android.net.pppoe.PppoeManager;
import android.net.NetworkStateTracker;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UEventObserver;
import android.provider.Settings;
import android.util.Log;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.io.FileDescriptor;
import java.io.PrintWriter;
public class PppoeService extends IPppoeManager.Stub {
private static final String TAG = "PppoeService";
private static final boolean DEBUG = true;
private static void LOG(String msg) {
if ( DEBUG ) {
Log.d(TAG, msg);
}
}
private Context mContext;
private PppoeObserver mObserver;
private NetworkInfo mNetworkInfo;
int mPppoeState = PppoeManager.PPPOE_STATE_DISCONNECTED;
private String mIface;
/*-------------------------------------------------------*/
PppoeService(Context context) {
LOG("PppoeService() : Entered.");
mContext = context;
mObserver = new PppoeObserver(mContext);
}
public int getPppoeState() {
return mPppoeState;
}
private void setPppoeStateAndSendBroadcast(int newState) {
int preState = mPppoeState;
mPppoeState = newState;
final Intent intent = new Intent(PppoeManager.PPPOE_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(PppoeManager.EXTRA_PPPOE_STATE, newState);
intent.putExtra(PppoeManager.EXTRA_PREVIOUS_PPPOE_STATE, preState);
LOG("setPppoeStateAndSendBroadcast() : preState = " + preState +", curState = " + newState);
mContext.sendStickyBroadcast(intent);
}
public boolean startPppoe() {
LOG("startPppoe");
setPppoeStateAndSendBroadcast(PppoeManager.PPPOE_STATE_CONNECTING);
if ( 0 != startPppoeNative() ) {
LOG("startPppoe() : fail to start pppoe!");
setPppoeStateAndSendBroadcast(PppoeManager.PPPOE_STATE_DISCONNECTED);
return false;
} else {
setPppoeStateAndSendBroadcast(PppoeManager.PPPOE_STATE_CONNECTED);
return true;
}
}
public boolean stopPppoe() {
setPppoeStateAndSendBroadcast(PppoeManager.PPPOE_STATE_DISCONNECTING);
if ( 0 != stopPppoeNative() ) {
LOG("stopPppoe() : fail to stop pppoe!");
return false;
} else {
setPppoeStateAndSendBroadcast(PppoeManager.PPPOE_STATE_DISCONNECTED);
return true;
}
}
public boolean setupPppoe(String user, String iface, String dns1, String dns2, String password) {
int ret;
LOG("setupPppoe: ");
LOG("user="+user);
LOG("iface="+iface);
LOG("dns1="+dns1);
LOG("dns2="+dns2);
// LOG("password="+password);
mIface = iface;
if (0 == setupPppoeNative(user, iface, dns1, dns2, password)) {
return true;
} else {
return false;
}
}
public String getPppoePhyIface() {
return mIface;
}
private class PppoeObserver extends UEventObserver {
private static final String PPPOE_UEVENT_MATCH = "SUBSYSTEM=net";
private Context mContext;
public PppoeObserver(Context context) {
mContext = context;
LOG("PppoeObserver() : to start observing, to catch uevent with '" + PPPOE_UEVENT_MATCH + "'.");
startObserving(PPPOE_UEVENT_MATCH);
init();
}
private synchronized final void init() {
}
@Override
public void onUEvent(PppoeObserver.UEvent event) {
LOG("onUEvent() : get uevent : '" + event + "'.");
String netInterface = event.get("INTERFACE");
String action = event.get("ACTION");
if ( null != netInterface && netInterface.equals("ppp0") ) {
if ( action.equals("add") ) {
LOG("onUEvent() : pppoe started");
// setEthernetEnabled(true);
}
else if ( action.equals("remove") ) {
LOG("onUEvent() : pppoe stopped");
// setEthernetEnabled(false);
}
}
}
}
/**
以下为JNI调用,在后面,会将这部分实现的步骤附上.
**/
public native static int setupPppoeNative(String user, String iface,String dns1, String dns2, String password);
public native static int startPppoeNative();
public native static int stopPppoeNative();
public native static int isPppoeUpNative();
}
涉及JNI部分:
frameworks/base/core/jni/Android.mk
同样,先增加源码文件,
LOCAL_SRC_FILES:= \
AndroidRuntime.cpp \
android_animation_PropertyValuesHolder.cpp \
android_net_pppoe_PppoeNative.cpp
添加CPP源文件:
frameworks/base/core/jni/android_net_pppoe_PppoeNative.cpp
//$_rbox_$_modify_$_chenzhi_20120309: add for pppoe
#define LOG_TAG "android_pppoe_PppoeNative.cpp"
#include "jni.h"
#include
#include
#include
#include
namespace android {
static jint setupPppoeNative(JNIEnv* env,
jobject clazz,
jstring user,
jstring iface,
jstring dns1,
jstring dns2,
jstring password)
{
int attempt;
int err = 0;
char* cmd = (char*)malloc(128);
char* prop = (char*)malloc(PROPERTY_VALUE_MAX);
///LOGD("%s", __FUNCTION__);
char *c_user = (char *)env->GetStringUTFChars(user, NULL);
char *c_iface = (char *)env->GetStringUTFChars(iface, NULL);
char *c_dns1 = (char *)env->GetStringUTFChars(dns1, NULL);
char *c_dns2 = (char *)env->GetStringUTFChars(dns2, NULL);
char *c_password = (char *)env->GetStringUTFChars(password, NULL);
if (!strcmp(c_dns1, "")) {
strcpy(c_dns1, "server");
}
sprintf(cmd, "pppoe_setup:%s %s no %s %s %s NONE",
c_user, c_iface, c_dns1, c_dns2, c_password);
//LOGD("setprop ctl.start %s", cmd);
if (property_set("ctl.start", cmd) < 0) {
//LOGE("Failed to start pppoe_setup");
err = -1;
goto end;
}
for (attempt = 50; attempt > 0; attempt--) {
property_get("net.pppoe.status", prop, "");
if (!strcmp(prop, "setuped")) {
break;
}
usleep(100000); // 100 ms retry delay
}
if (attempt == 0) {
//LOGE("%s: Timeout waiting for pppoe-setup", __FUNCTION__);
err = -1;
goto end;
}
err = 0;
end:
free(cmd);
free (prop);
return err;
}
static jint startPppoeNative(JNIEnv* env, jobject clazz)
{
int attempt;
int err = 0;
char* prop = (char *)malloc(PROPERTY_VALUE_MAX);
//LOGD("%s", __FUNCTION__);
if (property_set("ctl.start", "pppoe_start") < 0) {
//LOGE("Failed to start pppoe_start");
err = -1;
goto end;
}
for (attempt = 300; attempt > 0; attempt--) {
property_get("net.pppoe.status", prop, "");
if (!strcmp(prop, "connected")) {
break;
}
usleep(100000); // 100 ms retry delay
}
if (attempt == 0) {
//LOGE("%s: Timeout waiting for pppoe-start", __FUNCTION__);
err = -1;
goto end;
}
err = 0;
end:
free(prop);
return err;
}
static jint stopPppoeNative(JNIEnv* env, jobject clazz)
{
int attempt;
int err = 0;
char* prop = (char *)malloc(PROPERTY_VALUE_MAX);
//LOGD("%s", __FUNCTION__);
if (property_set("ctl.start", "pppoe_stop") < 0) {
//LOGE("Failed to start pppoe_stop");
err = -1;
goto end;
}
for (attempt = 100; attempt > 0; attempt--) {
property_get("net.pppoe.status", prop, "");
if (!strcmp(prop, "disconnected")) {
property_set("ctl.stop", "pppoe_stop");
err = 0;
goto end;
}
usleep(100000); // 100 ms retry delay
}
property_set("ctl.stop", "pppoe_stop");
err = -1;
end:
free(prop);
return err;
}
static jint isPppoeUpNative(JNIEnv* env, jobject clazz)
{
//LOGD("%s", __FUNCTION__);
return 0;
}
/*---------------------------------------------------------------------------*/
/*
* JNI registration.
*/
static JNINativeMethod gPppoeMethods[] = {
/* name, method descriptor, funcPtr */
{ "setupPppoeNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void *)setupPppoeNative },
{ "startPppoeNative", "()I", (void *)startPppoeNative },
{ "stopPppoeNative", "()I", (void *)stopPppoeNative },
{ "isPppoeUpNative", "()I", (void *)isPppoeUpNative },
};
int register_android_pppoe_PppoeNative(JNIEnv* env)
{
return AndroidRuntime::registerNativeMethods(env, "com/android/server/PppoeService", gPppoeMethods, NELEM(gPppoeMethods) );
}
}
同时,需要加载进库中(上面的CPP文件并不是单独编译出一个SO, 一个放在AndroidRuntime库中)
frameworks/base/core/jni/AndroidRuntime.cpp
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
extern int register_android_net_NetworkUtils(JNIEnv* env);
extern int register_android_net_TrafficStats(JNIEnv* env);
extern int register_android_net_wifi_WifiManager(JNIEnv* env);
//$_rbox_$_modify_$_chenzhi_20120309: add register_android_pppoe_PppoeNative
extern int register_android_pppoe_PppoeNative(JNIEnv* env);//引入
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_AndroidBidi(JNIEnv *env);
同时,需要加入到:
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
REG_JNI(register_android_util_FloatMath),
REG_JNI(register_android_text_format_Time),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
REG_JNI(register_android_emoji_EmojiFactory),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_AndroidBidi),
REG_JNI(register_android_view_InputDevice),
REG_JNI(register_android_view_KeyCharacterMap),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_PixelFormat),
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_GLES20DisplayList),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_HardwareRenderer),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_TextureView),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_GLES10),
REG_JNI(register_android_opengl_jni_GLES10Ext),
REG_JNI(register_android_opengl_jni_GLES11),
REG_JNI(register_android_opengl_jni_GLES11Ext),
REG_JNI(register_android_pppoe_PppoeNative),//有时会忘记
...
中
2. 系统启动后,添加服务:
frameworks/base/services/java/com/android/server/SystemServer.java
@Override
public void run() {
...
//添加服务
try {
Slog.i(TAG, "Pppoe Service");
pppoe = new PppoeService(context);
ServiceManager.addService(Context.PPPOE_SERVICE, pppoe);
} catch (Throwable e) {
reportWtf("starting Pppoe Service", e);
}
//$_rbox_$_modify_$_end
try {
Slog.i(TAG, "Throttle Service");
throttle = new ThrottleService(context);
ServiceManager.addService(
Context.THROTTLE_SERVICE, throttle);
} catch (Throwable e) {
reportWtf("starting ThrottleService", e);
}
try {
Slog.i(TAG, "UpdateLock Service");
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
new UpdateLockService(context));
} catch (Throwable e) {
reportWtf("starting UpdateLockService", e);
}
添加Manager
frameworks/base/core/java/android/app/ContextImpl.java
static {
registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
IAccountManager service = IAccountManager.Stub.asInterface(b);
return new AccountManager(ctx, service);
}});
registerService(PPPOE_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(PPPOE_SERVICE);
IPppoeManager service = IPppoeManager.Stub.asInterface(b);
return new PppoeManager(service, ctx.mMainThread.getHandler());
}});
...
3. 如何使用?
XManager mgr = (XManager)context.getSystemService(name);