继续来记录 android 应用层到 HAL 层的通信打通过程,本篇随笔实现 framework 层面。
framework 层的实现并不算杂,主要是依次完成 AIDL、JNI、SERVICE 的实现,代码量并不大就是比较分散,
需要注意的是在实现方法调用、传参的过程中要仔细和耐心,我可以在这里可是吃了大亏。
一、AIDL 实现:
① 创建 frameworks/base/core/java/android/hardware/hidldebug/IHidlDebugService.aidl
1 package android.hardware.hidldebug; 2 3 interface IHidlDebugService { 4 String hidl_debug_test(String str); 5 }
② 修改 frameworks/base/Android.mk,将刚创建的AIDL文件名加入
1 diff --git a/frameworks/base/Android.mk b/frameworks/base/Android.mk 2 index a722b30..0911c6a 100755 3 --- a/frameworks/base/Android.mk 4 +++ b/frameworks/base/Android.mk 5 @@ -201,6 +201,7 @@ LOCAL_SRC_FILES += 6 core/java/android/hardware/hdmi/IHdmiRecordListener.aidl 7 core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl 8 core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl 9 + core/java/android/hardware/hidldebug/IHidlDebugService.aidl 10 core/java/android/hardware/input/IInputManager.aidl 11 core/java/android/hardware/input/IInputDevicesChangedListener.aidl 12 core/java/android/hardware/input/ITabletModeChangedListener.aidl
二、JNI 实现:
① 创建 frameworks/base/services/core/jni/com_android_server_hidldebug_HidlDebugService.cpp
1 #include <jni.h> 2 #include <nativehelper/JNIHelp.h> 3 #include <binder/IServiceManager.h> 4 #include <android/hardware/hidldebug/1.0/IHidldebug.h> 5 #include <log/log.h> 6 7 using android::sp; 8 using android::hardware::hidl_string; 9 using android::hardware::hidldebug::V1_0::IHidldebug; 10 11 namespace android { 12 13 sp<IHidldebug> hw_device; 14 15 static jstring charToJstring(JNIEnv *env, const char *pat) { 16 17 jclass strClass = env->FindClass("java/lang/String"); 18 jmethodID ctorID = env->GetMethodID(strClass, "<init>","([BLjava/lang/String;)V"); 19 jbyteArray bytes = env->NewByteArray(strlen(pat)); 20 env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat); 21 jstring encoding = env->NewStringUTF("utf-8"); 22 23 return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); 24 } 25 26 static jstring android_server_hidldebug_HidlDebugService(JNIEnv* env,jobject /* clazz */, jstring name) { 27 28 const char* str; 29 jstring ret; 30 str = env->GetStringUTFChars(name, NULL); 31 32 ALOGW("JNI hidldebug android_server_hidldebug_HidlDebugService."); 33 34 hw_device = IHidldebug::getService(); 35 if (hw_device == nullptr) { 36 ALOGW("ALOGWJNI hidldebug failed to get IHidldebug service."); 37 return NULL; 38 } 39 40 hw_device->helloWorld(str, [&](hidl_string result) { 41 ALOGW("%s ", result.c_str()); 42 ret = charToJstring(env, result.c_str()); 43 }); 44 45 return ret; 46 } 47 48 /* 49 * JNI registration. 50 */ 51 static const JNINativeMethod gMethods[] = { 52 { "hidl_debug_test_native", "(Ljava/lang/String;)Ljava/lang/String;", (void*)android_server_hidldebug_HidlDebugService }, 53 }; 54 55 int register_android_server_hidldebug_HidlDebugService(JNIEnv* env) 56 { 57 int res = jniRegisterNativeMethods(env, "com/android/server/hidldebug/HidlDebugService", 58 gMethods, NELEM(gMethods)); 59 LOG_FATAL_IF(res < 0, "Unable to register HidlDebugService native methods."); 60 return res; 61 } 62 63 }; // namespace android
② 修改 frameworks/base/services/core/jni/onload.cpp,以便我们编译的JNI可以顺利的注册到系统中
1 diff --git a/frameworks/base/services/core/jni/onload.cpp b/frameworks/base/services/core/jni/onload.cpp 2 index e96bda9..011ca54 100755 3 --- a/frameworks/base/services/core/jni/onload.cpp 4 +++ b/frameworks/base/services/core/jni/onload.cpp 5 @@ -23,6 +23,7 @@ namespace android { 6 int register_android_server_AlarmManagerService(JNIEnv* env); 7 int register_android_server_BatteryStatsService(JNIEnv* env); 8 int register_android_server_ConsumerIrService(JNIEnv *env); 9 +int register_android_server_hidldebug_HidlDebugService(JNIEnv *env); 10 int register_android_server_InputApplicationHandle(JNIEnv* env); 11 int register_android_server_InputWindowHandle(JNIEnv* env); 12 int register_android_server_InputManager(JNIEnv* env); 13 @@ -65,6 +66,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) 14 15 register_android_server_PowerManagerService(env); 16 register_android_server_SerialService(env); 17 + register_android_server_hidldebug_HidlDebugService(env); 18 register_android_server_InputApplicationHandle(env); 19 register_android_server_InputWindowHandle(env); 20 register_android_server_InputManager(env);
③ 修改 frameworks/base/services/core/jni/Android.mk,加入 JNI 源文件
1 diff --git a/frameworks/base/services/core/jni/Android.mk b/frameworks/base/services/core/jni/Android.mk 2 index 40d7bb7..382bbaf 100755 3 --- a/frameworks/base/services/core/jni/Android.mk 4 +++ b/frameworks/base/services/core/jni/Android.mk 5 @@ -17,6 +17,7 @@ LOCAL_SRC_FILES += 6 $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp 7 $(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp 8 $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp 9 + $(LOCAL_REL_DIR)/com_android_server_hidldebug_HidlDebugService.cpp 10 $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp 11 $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp 12 $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp 13 @@ -92,6 +93,7 @@ LOCAL_SHARED_LIBRARIES += 14 android.hardware.light@2.0 15 android.hardware.power@1.0 16 android.hardware.thermal@1.0 17 + android.hardware.hidldebug@1.0 18 android.hardware.tv.cec@1.0 19 android.hardware.tv.input@1.0 20 android.hardware.vibrator@1.0
三、SERVICE 实现:
① 创建 frameworks/base/services/core/java/com/android/server/hidldebug/HidlDebugService.java
1 package com.android.server.hidldebug; 2 import android.hardware.hidldebug.IHidlDebugService; 3 4 public class HidlDebugService extends IHidlDebugService.Stub { 5 public HidlDebugService(){ 6 android.util.Log.d("HidlDebug", "Start IHidlDebugService..."); 7 } 8 9 @Override 10 public String hidl_debug_test(String names){ 11 android.util.Log.d("HidlDebug", "hidl_debug_test()"); 12 return hidl_debug_test_native(names); 13 } 14 15 private static native String hidl_debug_test_native(String names);
② 修改 frameworks/base/services/java/com/android/server/SystemServer.java,加入我们实现过的 service,保证其在系统时可以加入到 ServiceManager
1 diff --git a/frameworks/base/services/java/com/android/server/SystemServer.java b/frameworks/base/services/java/com/android/server/SystemServer.java 2 index 1eb63d7..2c1bf04 100755 3 --- a/frameworks/base/services/java/com/android/server/SystemServer.java 4 +++ b/frameworks/base/services/java/com/android/server/SystemServer.java 5 @@ -113,6 +113,8 @@ import com.android.server.vr.VrManagerService; 6 import com.android.server.webkit.WebViewUpdateService; 7 import com.android.server.wm.WindowManagerService; 8 9 +import com.android.server.hidldebug.HidlDebugService; 10 + 11 import dalvik.system.VMRuntime; 12 13 import java.io.File; 14 @@ -770,6 +772,10 @@ public final class SystemServer { 15 telephonyRegistry = new TelephonyRegistry(context); 16 ServiceManager.addService("telephony.registry", telephonyRegistry); 17 traceEnd(); 18 + 19 + traceBeginAndSlog("StartHidlDebugService"); 20 + ServiceManager.addService("zackary.HidlDebugService", new HidlDebugService()); 21 + traceEnd(); 22 23 traceBeginAndSlog("StartEntropyMixer"); 24 mEntropyMixer = new EntropyMixer(context);
四、代码编译
1 可以选择重新编译整个系统或者 mmm frameworks/base 单独编译后将成果物拷贝到设备中 2 如果在编译的过程中遇到缺少依赖的情况,例如 NEED BY ... 3 这时可以使用 mmma 命令来主动编译缺少的依赖 4 还可能遇到提示需要 update-api 的情况,只要 make update-api 后就可以解决
五、测试验证
① 查看我们实现的 service 是否被成功加载
1 / # service list | grep hidl 2 75 zackary.HidlDebugService: [android.hardware.hidldebug.IHidlDebugService]
② 如果成功加载,可以使用 service call 来验证流程是否打通,call 之前不要忘记启动我们之前实现的 hidl service
1 / # service call zackary.HidlDebugService 1 s16 zackary. 2 Result: Parcel( 3 0x00000000: 00000000 0000001e 0054005b 00730065 '........[.T.e.s.' 4 0x00000010: 00200074 006f0052 00740075 006e0069 't. .R.o.u.t.i.n.' 5 0x00000020: 005d0065 00480020 006c0065 006f006c 'e.]. .H.e.l.l.o.' 6 0x00000030: 0020002c 0061007a 006b0063 00720061 ',. .z.a.c.k.a.r.' 7 0x00000040: 002e0079 00000000 'y....... ')
调用成功,可以看到是返回了一个 Parcel,内容正是我们在 HAL 中实现的字符串拼接后的结果,
好的,framework 层就是这样来实现了,下一篇我们继续来完成一个简单的 android app 调用到本次实现的接口,最终来完善整体的调用过程。