目录
- 一、添加 aidl 文件
- 二、服务端实现
- 三、JNI 层实现
- 四、客户端实现
- 五、服务端和客户端的注册
- 5.1 注册服务端
- 5.2 注册客户端
- 5.3 更新api文件
- 六、Selinux 配置
| 添加硬件访问服务 |
一、添加 aidl 文件
添加 aidl 文件frameworks/base/core/java/android/os/IHelloService.aidl:
packageandroid.os;/** * @hide */interfaceIHelloService{voidopen();voidwrite(Stringstr);Stringread();}二、服务端实现
添加frameworks/base/services/core/java/com/android/server/HelloService.java文件:
packagecom.android.server;importandroid.os.IHelloService;// 硬件服务的服务端实现publicclassHelloServiceextendsIHelloService.Stub{publicnativevoidnatvieOpen();publicnativevoidnatvieWrite(Stringstr);publicnativeStringnativeRead();publicvoidopen()throwsandroid.os.RemoteException{natvieOpen();}publicvoidwrite(Stringstr)throwsandroid.os.RemoteException{natvieWrite(str);}publicStringread()throwsandroid.os.RemoteException{returnnativeRead();}}三、JNI 层实现
添加frameworks/base/services/core/jni/com_android_server_HelloService.cppJNI 实现:
#defineLOG_TAG"HelloService"#include<jni.h>#include<nativehelper/JNIHelp.h>#include"android_runtime/AndroidRuntime.h"#include<utils/misc.h>#include<utils/Log.h>#include<hardware/hello_hal.h>#include<stdio.h>#include<string>namespace android{statichw_module_t*gHelloModule=NULL;statichello_hal_device_t*gHelloHalDevice=NULL;staticvoidhelloOpen(JNIEnv env,jobject clazz){ALOGD("Hello_test_jni_open");if(gHelloModule!=NULL){return;}interr=hw_get_module(HELLO_HAL_HARDWARE_MODULE_ID,(hw_module_tconst**)&gHelloModule);if(err){ALOGE("Couldn't load %s module (%s)",HELLO_HAL_HARDWARE_MODULE_ID,strerror(-err));}else{if(gHelloModule){ALOGD("Hello_test_jni_open get module sucess");hello_hal_methods_open(gHelloModule,&gHelloHalDevice);}}if(gHelloHalDevice){gHelloHalDevice->hello_hal_open(gHelloHalDevice);}}staticvoidhelloWrite(JNIEnv*env,jobject clazz,jstring str){if(gHelloHalDevice){ALOGD("Hello_test_jni_write");constchar*c_str=NULL;jboolean isCopy;c_str=env->GetStringUTFChars(str,&isCopy);//从jstring指针中获取数据ALOGD("Hello_test_jni_write %s",c_str);gHelloHalDevice->hello_hal_write(gHelloHalDevice,c_str);}else{ALOGW("Tried to hello but there is no hello device.");}}staticjstringhelloRead(JNIEnv*env,jobject clazz){if(gHelloHalDevice){ALOGD("Hello_test_jni_read");char*data=(char*)malloc(1024);if(data==NULL){ALOGE("helloRead: malloc data failed");returnenv->NewStringUTF("malloc fail");}memset(data,0,1024);intret=gHelloHalDevice->hello_hal_read(gHelloHalDevice,data);ALOGD("Hello_test_jni_read result is %s, ret=%d",data,ret);if(ret>0&&data[0]!='\0'){size_tstr_len=strnlen(data,ret);if(str_len==(size_t)ret){if(ret<1023){// 留空间data[ret]='\0';str_len=ret;}else{data[1023]='\0';// 截断str_len=1023;}}jbyteArray array=env->NewByteArray(str_len);env->SetByteArrayRegion(array,0,str_len,(constjbyte*)data);jstring strEncode=env->NewStringUTF("UTF-8");jclass cls=env->FindClass("java/lang/String");jmethodID ctor=env->GetMethodID(cls,"<init>","([BLjava/lang/String;)V");jstring retStr=(jstring)env->NewObject(cls,ctor,array,strEncode);// 释放free(data);env->DeleteLocalRef(array);env->DeleteLocalRef(strEncode);env->DeleteLocalRef(cls);returnretStr;}else{free(data);returnenv->NewStringUTF("no msg");}}returnenv->NewStringUTF("no msg");}// public native void natvieOpen();// public native void natvieWrite(String str);// public native String nativeRead();staticconstJNINativeMethod method_table[]={{"natvieOpen","()V",(void*)helloOpen},{"natvieWrite","(Ljava/lang/String;)V",(void*)helloWrite},{"nativeRead","()Ljava/lang/String;",(void*)helloRead}};intregister_android_server_HelloService(JNIEnv*env){ALOGD("Hello_test_jni_register");returnjniRegisterNativeMethods(env,"com/android/server/HelloService",method_table,NELEM(method_table));}};在frameworks/base/services/core/jni/Android.bp中添加:
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/services/core/jni/Android.bp diff--git a/frameworks/base/services/core/jni/Android.bp b/frameworks/base/services/core/jni/Android.bp index b01b2fa5c2..6884e332e4100644---a/frameworks/base/services/core/jni/Android.bp+++b/frameworks/base/services/core/jni/Android.bp @@-72,6+72,7@@ cc_library_static{"com_android_server_am_LowMemDetector.cpp","com_android_server_pm_PackageManagerShellCommandDataLoader.cpp","com_android_server_sensor_SensorService.cpp",+"com_android_server_HelloService.cpp","onload.cpp",":lib_cachedAppOptimizer_native",":lib_networkStatsFactory_native",在frameworks/base/services/core/jni/onload.cpp中添加:
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/services/core/jni/onload.cpp diff--git a/frameworks/base/services/core/jni/onload.cpp b/frameworks/base/services/core/jni/onload.cpp index b50472d7b9..7ce091a509100644---a/frameworks/base/services/core/jni/onload.cpp+++b/frameworks/base/services/core/jni/onload.cpp @@-64,6+64,7@@intregister_android_server_FaceService(JNIEnv*env);intregister_android_server_GpuService(JNIEnv*env);intregister_android_server_stats_pull_StatsPullAtomService(JNIEnv*env);intregister_android_server_sensor_SensorService(JavaVM*vm,JNIEnv*env);+intregister_android_server_HelloService(JNIEnv*env);};using namespace android;// 在这里注册 JNI 函数// java 层的 native 方法就能调用到对应的 native 层函数了@@-121,5+122,6@@extern"C"jintJNI_OnLoad(JavaVM*vm,void*/* reserved */)register_android_server_GpuService(env);register_android_server_stats_pull_StatsPullAtomService(env);register_android_server_sensor_SensorService(vm,env);+register_android_server_HelloService(env);returnJNI_VERSION_1_4;}四、客户端实现
添加一个接口frameworks/base/core/java/android/os/Hello.java:
packageandroid.os;importandroid.annotation.Nullable;// 导入空指针注解importandroid.annotation.NonNull;importandroid.annotation.SuppressLint;// 导入Lint抑制注解@SuppressLint("RethrowRemoteException")publicabstractclassHello{publicHello(){}publicabstractintopen();publicabstractintwrite(@NonNullStringst);@NullablepublicabstractStringread();}实现接口frameworks/base/core/java/android/os/HelloManager.java:
packageandroid.os;importandroid.annotation.NonNull;// 导入非空注解importandroid.annotation.Nullable;// 导入可空注解importandroid.annotation.SuppressLint;// 导入Lint抑制注解importandroid.content.Context;importandroid.os.ServiceManager;// 补全ServiceManager导入(原代码漏了)importandroid.os.RemoteException;// 导入RemoteException用于捕获importandroid.os.ServiceSpecificException;// 新增:系统推荐的RuntimeException子类importandroid.util.Log;/** * Vibrator implementation that controls the main system vibrator. * * @hide */// 抑制RethrowRemoteException(核心,解决异常声明问题)@SuppressLint("RethrowRemoteException")publicclassHelloManagerextendsHello{privatestaticfinalStringTAG="HelloManager";privatefinalIHelloServicemService;// 获取Hello服务的代理端publicHelloManager(){mService=IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));}@Overridepublicintopen(){if(mService!=null){try{mService.open();return0;// 调用成功返回0}catch(RemoteExceptione){Log.e(TAG,"open failed: ",e);thrownewServiceSpecificException(1001,"open remote service failed: "+e.getMessage());}}Log.w(TAG,"mService is null, open failed");return-1;// 服务为空返回-1}@Overridepublicintwrite(@NonNullStringstr){if(str==null){Log.e(TAG,"write str is null");thrownewIllegalArgumentException("str must not be null");}if(mService!=null){try{mService.write(str);return0;// 调用成功返回0}catch(RemoteExceptione){Log.e(TAG,"write failed: ",e);thrownewServiceSpecificException(1002,"write remote service failed: "+e.getMessage());}}Log.w(TAG,"mService is null, write failed");return-1;// 服务为空返回-1}@Nullable@OverridepublicStringread(){if(mService!=null){try{returnmService.read();// 调用成功返回读取结果}catch(RemoteExceptione){Log.e(TAG,"read failed: ",e);thrownewServiceSpecificException(1003,"read remote service failed: "+e.getMessage());}}Log.w(TAG,"mService is null, read return null");returnnull;// 服务为空返回null}}五、服务端和客户端的注册
最最最重要的莫过于这里服务端和客户端的注册了
在frameworks/base/core/java/android/content/Context.java中添加:
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/core/java/android/content/Context.java diff--git a/frameworks/base/core/java/android/content/Context.java b/frameworks/base/core/java/android/content/Context.java index3dc3d78153..4d0c92299c100644---a/frameworks/base/core/java/android/content/Context.java+++b/frameworks/base/core/java/android/content/Context.java @@-3600,6+3600,7@@publicabstractclassContext{/** @hide */@StringDef(suffix={"_SERVICE"},value={+HELLO_SERVICE,POWER_SERVICE,//@hide: POWER_STATS_SERVICE,WINDOW_SERVICE,@@-3961,6+3962,8@@publicabstractclassContext{*/publicstaticfinalStringPOWER_SERVICE="power";+publicstaticfinalStringHELLO_SERVICE="hello";/** * Use with {@link #getSystemService(String)} to retrieve a * {@link android.os.PowerStatsService} for accessing power stats5.1 注册服务端
修改frameworks/base/services/java/com/android/server/SystemServer.java:
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/services/java/com/android/server/SystemServer.java diff--git a/frameworks/base/services/java/com/android/server/SystemServer.java b/frameworks/base/services/java/com/android/server/SystemServer.java index16c9475658..ce7e147950100644---a/frameworks/base/services/java/com/android/server/SystemServer.java+++b/frameworks/base/services/java/com/android/server/SystemServer.java @@-1457,6+1457,11@@publicfinalclassSystemServerimplementsDumpable{mSystemServiceManager.startService(KeyChainSystemService.class);t.traceEnd();+t.traceBegin("StartHelloService");+ServiceManager.addService("HelloService",newHelloService());+t.traceEnd();++t.traceBegin("StartSchedulingPolicyService");ServiceManager.addService("scheduling_policy",newSchedulingPolicyService());t.traceEnd();5.2 注册客户端
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/core/java/android/app/SystemServiceRegistry.java diff--git a/frameworks/base/core/java/android/app/SystemServiceRegistry.java b/frameworks/base/core/java/android/app/SystemServiceRegistry.java index32ea41b2c7..4603e03935100644---a/frameworks/base/core/java/android/app/SystemServiceRegistry.java+++b/frameworks/base/core/java/android/app/SystemServiceRegistry.java @@-184,6+184,8@@importandroid.os.image.IDynamicSystemService;importandroid.os.incremental.IIncrementalService;importandroid.os.incremental.IncrementalManager;importandroid.os.storage.StorageManager;+importandroid.os.Hello;+importandroid.os.HelloManager;importandroid.permission.LegacyPermissionManager;importandroid.permission.PermissionCheckerManager;importandroid.permission.PermissionControllerManager;@@-290,6+292,13@@publicfinalclassSystemServiceRegistry{returnnewAccountManager(ctx,service);}});+registerService(Context.HELLO_SERVICE,Hello.class,+newCachedServiceFetcher<Hello>(){+@Override+publicHellocreateService(ContextImplctx){+returnnewHelloManager();+}});+registerService(Context.ACTIVITY_SERVICE,ActivityManager.class,newCachedServiceFetcher<ActivityManager>(){@Override5.3 更新api文件
xuejie@vt-PowerEdge-R740:~/A11a133a12$ git diff frameworks/base/core/api/current.txt diff--git a/frameworks/base/core/api/current.txt b/frameworks/base/core/api/current.txt index624ded0577..df3a5edaa6100644---a/frameworks/base/core/api/current.txt+++b/frameworks/base/core/api/current.txt @@-10644,6+10644,7@@ package android.content{field publicstaticfinal String FINGERPRINT_SERVICE="fingerprint";field publicstaticfinal String GAME_SERVICE="game";field publicstaticfinal String HARDWARE_PROPERTIES_SERVICE="hardware_properties";+field publicstaticfinal String HELLO_SERVICE="hello";field publicstaticfinal String INPUT_METHOD_SERVICE="input_method";field publicstaticfinal String INPUT_SERVICE="input";field publicstaticfinal String IPSEC_SERVICE="ipsec";@@-31288,6+31289,13@@ package android.os{field publicstaticfinalfloatUNDEFINED_TEMPERATURE=-3.4028235E38f;}+public abstract class Hello{+ctor publicHello();+method public abstractintopen();+method @Nullable public abstract Stringread();+method public abstractintwrite(@NonNull String);+}+public interface IBinder{六、Selinux 配置
修改system/sepolicy/service.te:
type HelloServiceType,app_api_service,system_server_service,service_manager_type;修改system/sepolicy/service_contexts:
HelloService u:object_r:HelloServiceType:s0修改system/sepolicy/platform_app.te,让系统 App 可以访问我们自定义的 Binder 服务:
allow platform_app HelloServiceType:service_manager find;修改system/sepolicy/untrusted_app.te,让普通 App 可以访问我们自定义的 Binder 服务:
allow untrusted_app HelloServiceType:service_manager find;最后,让 SystemServer 可以访问到 hello 驱动,修改system/sepolicy/system_server.te:
allow system_serverhello_dev_t:chr_file{open read write};