In normal android application Development, most of them only call the APIs in framwork for application layer coding. in system development, you may add system services by yourself;
If any system service is added, how does the service call the native code, and how the service is called by the manager? Here is a demo of result verification.
1. Compile native code, framwork/base/services/jni/com_android_server_VirtualInputService.cpp;
The following are native functions used and register_android_server_VirtualInputService. The specific implementation is not detailed.
static JNINativeMethod method_table[] = { {"native_open", "()I",(void *)android_server_VirtualInputService_open}, {"native_close", "()Z", (void *)android_server_VirtualInputService_close}, {"native_sendir", "(II)Z", (void *)android_server_VirtualInputService_sendir},}; +int register_android_server_VirtualInputService(JNIEnv *env)+{+ jclass clazz = env->FindClass("com/android/server/VirtualInputService");+ if (clazz == NULL) {+ ALOGE("Can't find com/android/server/VirtualInputService");+ return -1;+ }++ return jniRegisterNativeMethods(env, "com/android/server/VirtualInputService",+ method_table, NELEM(method_table));+}+};
2. Add register_android_server_VirtualInputService to base/services/jni/onload. cpp.
int register_android_server_SerialService(JNIEnv* env);+int register_android_server_VirtualInputService(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); register_android_server_SerialService(env);+register_android_server_VirtualInputService(env); register_android_server_InputApplicationHandle(env);
3. Add com_android_server_VirtualInputService to mk to compile it
+++ base/services/jni/Android.mk(working copy)@@ -16,6 +16,7 @@ com_android_server_VibratorService.cpp \ com_android_server_location_GpsLocationProvider.cpp \ com_android_server_connectivity_Vpn.cpp \+ com_android_server_VirtualInputService.cpp \ onload.cpp
4. Add service: base/services/java/com/android/server/VirtualInputService. java
It must inherit IVirtualInputManager. Stub so that it can be called remotely;
Declare native METHOD: private native static int native_open ();
Private native static boolean native_close ();
Private native static boolean native_sendir (int keycode, int type );
+package com.android.server;++import android.content.Context;+import android.hardware.input.IVirtualInputManager;+import android.util.Log;++import java.io.File;+import java.util.ArrayList;++public class VirtualInputService extends IVirtualInputManager.Stub {+ private static final String TAG = "VirtualInputManager";++ private final Context mContext;+ private int mVirtualInputFd = -1;++ public VirtualInputService(Context context) {+ mContext = context;+if(mVirtualInputFd == -1){+ mVirtualInputFd = native_open();+Log.d(TAG, "mVirtualInputFd:"+mVirtualInputFd);+}else+Log.d(TAG, "mVirtualInputFd1:"+mVirtualInputFd);++ }++public boolean SendIR(int keycode){+if(mVirtualInputFd > 0)+{+Log.d(TAG, "Service SendIR:"+keycode);+return native_sendir(keycode,0);+}+else +return false;+}++ private native static int native_open();+private native static boolean native_close();+private native static boolean native_sendir(int keycode, int type);++}
5. Add a new service in base/services/java/com/android/server/SystemServer. java
SerialService serial = null;+ VirtualInputService VirtualInput = null; TwilightService twilight = null;
try {+ Slog.i(TAG, "VirtualInput Service");+ VirtualInput = new VirtualInputService(context);+ ServiceManager.addService(Context.VIRTUALINPUT_SERVICE, VirtualInput);+ } catch (Throwable e) {+ Slog.e(TAG, "Failure starting VirtualInputService", e);+ }++ try { Slog.i(TAG, "Twilight Service"); twilight = new TwilightService(context); } catch (Throwable e) {
6. added the aidl interface: base/core/java/android/hardware/input/IVirtualInputManager. aidl.
+package android.hardware.input;+++/** @hide */+interface IVirtualInputManager+{+boolean SendIR(int keycode);+}
7. Implement IVirtualInputManager. java; base/core/java/android/hardware/input/VirtualInputManager. java
+package android.hardware.input;++import android.app.PendingIntent;+import android.content.Context;+import android.os.Bundle;+import android.os.ParcelFileDescriptor;+import android.os.RemoteException;+import android.os.SystemProperties;+import android.util.Log;++import java.io.IOException;+import java.util.HashMap;++/**+ * @hide+ */+public class VirtualInputManager {+ private static final String TAG = "VirtualInputManager";++ private final Context mContext;+ private final IVirtualInputManager mService;++ /**+ * {@hide}+ */+ public VirtualInputManager(Context context, IVirtualInputManager service) {+ mContext = context;+ mService = service;+Log.d(TAG,"VirtualInputManager");+ }++public boolean SendIR(int keycode) throws android.os.RemoteException{+Log.d(TAG,"keycode:"+keycode);+return mService.SendIR(keycode);+}+}
8. framwork/base/Android. mk
core/java/android/hardware/input/IInputManager.aidl \+core/java/android/hardware/input/IVirtualInputManager.aidl \ core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
9. Add the system to base/core/java/android/content/Context. java to obtain the service identifier.
+ public static final String VIRTUALINPUT_SERVICE = "virtualinput";
10. base/core/java/android/app/ContextImpl. java
+ registerService(VIRTUALINPUT_SERVICE, new ServiceFetcher() {+ public Object createService(ContextImpl ctx) {+ IBinder b = ServiceManager.getService(VIRTUALINPUT_SERVICE);+ return new VirtualInputManager(ctx, IVirtualInputManager.Stub.asInterface(b));+ }});+
The preceding steps Add a complete service...