Android O HIDL Framework 层实现

继续来记录 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\n", 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 调用到本次实现的接口,最终来完善整体的调用过程。

 

posted @ 2020-07-16 23:18  Zackary丶Liu  阅读(569)  评论(0)    收藏  举报