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: cz@rock-chips.com * 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: cz@rock-chips.com * 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 <utils/misc.h> #include <android_runtime/AndroidRuntime.h> #include <utils/Log.h> #include <cutils/properties.h> 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);