HIDL Hal 开发笔记8----添加硬件访问服务

目录

  • [一、 添加 aidl 文件](#一、 添加 aidl 文件)
  • 二、实现服务端
  • [三、JNI 层实现](#三、JNI 层实现)
  • 四、客户端实现
  • 五、服务端和客户端的注册
    • [5.1 注册服务端](#5.1 注册服务端)
    • [5.2 注册客户端](#5.2 注册客户端)
    • [5.3 更新api文件](#5.3 更新api文件)
  • [六、Selinux 配置](#六、Selinux 配置)
    • [6.1 `service_contexts`](#6.1 service_contexts)
    • [6.2 `service.te`](#6.2 service.te)
    • [6.3 `platform_app.te`](#6.3 platform_app.te)
    • [6.4 `untrusted_app.te`](#6.4 untrusted_app.te)
    • [6.5 `system_server.te`](#6.5 system_server.te)
  • 七、编译运行

|--------------|
| 添加硬件访问服务 |

一、 添加 aidl 文件

添加 aidl 文件 frameworks/base/core/java/android/os/IHelloService.aidl :

c 复制代码
package android.os;

interface IHelloService
{
    void write(String str);
    String read();
}

二、实现服务端

添加 frameworks/base/services/core/java/com/android/server/HelloService.java 文件:

c 复制代码
package com.android.server;

import android.os.IHelloService;

// 硬件服务的服务端实现
public class HelloService extends IHelloService.Stub {

    public native void natvieWrite(String str);
    public native String nativeRead();
    
    public void write(String str) throws android.os.RemoteException  {
        natvieWrite(str);
    }
    
    public String read() throws android.os.RemoteException  {
        return nativeRead();
    }
}

三、JNI 层实现

添加 frameworks/base/services/core/jni/com_android_server_HelloService.cpp JNI 实现:

c 复制代码
#define LOG_TAG "HelloService"

#include <jni.h>
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>

#include <stdio.h>
#include <string>

#include <nativehelper/JNIHelp.h>

#include <henry/hardware/hello_hidl/1.0/IHello.h>  //编译生产文件
#include <hidl/LegacySupport.h>

using android::sp;
using henry::hardware::hello_hidl::V1_0::IHello;
using android::hardware::Return;
using android::hardware::hidl_string;


namespace android
{

static void helloWrite(JNIEnv* env, jobject clazz, jstring str)
{   
   // 获取服务代理端对象
    android::sp<IHello> hw_device = IHello::getService();
    if (hw_device == nullptr) {
              ALOGD("failed to get hello-hidl");
              return;
    }
    const char* cStr = env->GetStringUTFChars(str, 0);
    // 通过代理端对象发起远程调用
    hw_device->write(cStr);
}

static jstring helloRead(JNIEnv* env, jobject clazz)
{
    jstring res = nullptr;
   // 获取服务代理端对象
    android::sp<IHello> hw_device = IHello::getService();
    if (hw_device == nullptr) {
              ALOGD("failed to get hello-hidl");
              return res;
    }

    hw_device->read([&](hidl_string result){
        ALOGD("%s\n", result.c_str());
        res = env->NewStringUTF(result.c_str());
    });

    return res;
}

    // public native void natvieOpen();
    // public native void natvieWrite(String str);
    // public native String nativeRead();

static const JNINativeMethod method_table[] = {

    { "natvieWrite", "(Ljava/lang/String;)V", (void*)helloWrite },
    { "nativeRead", "()Ljava/lang/String;", (void*)helloRead }
};


int register_android_server_HelloService(JNIEnv *env)
{   
    ALOGD("hellotest_jni_register");
    return jniRegisterNativeMethods(env, "com/android/server/HelloService",
            method_table, NELEM(method_table));
}

};

其中 hardware/hello_hidl/1.0/IHello.h是编译生成文件 编译会报错,需要在frameworks/base/services/core/jni/Android.bp中引入HIDL 接口库"henry.hardware.hello_hidl@1.0"

frameworks/base/services/core/jni/Android.bp 中添加:

c 复制代码
git diff 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..f9d0f7e6bf 100644
--- a/frameworks/base/services/core/jni/Android.bp
+++ b/frameworks/base/services/core/jni/Android.bp
@@ -36,6 +36,7 @@ cc_library_static {
         "gnss/Utils.cpp",
         "stats/SurfaceFlingerPuller.cpp",
         "com_android_server_adb_AdbDebuggingManager.cpp",
+        "com_android_server_HelloService.cpp",
         "com_android_server_ActivityManagerService.cpp",
         "com_android_server_am_BatteryStatsService.cpp",
         "com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp",
@@ -176,6 +177,7 @@ cc_defaults {
         "android.hardware.vibrator@1.2",
         "android.hardware.vibrator@1.3",
         "android.hardware.vr@1.0",
+        "henry.hardware.hello_hidl@1.0",
         "android.hidl.token@1.0-utils",
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",

frameworks/base/services/core/jni/onload.cpp 中添加:

c 复制代码
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..7ce091a509 100644
--- a/frameworks/base/services/core/jni/onload.cpp
+++ b/frameworks/base/services/core/jni/onload.cpp
@@ -64,6 +64,7 @@ int register_android_server_FaceService(JNIEnv* env);
 int register_android_server_GpuService(JNIEnv* env);
 int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
 int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);
+int register_android_server_HelloService(JNIEnv* env);
 };
 
 using namespace android;
@@ -121,5 +122,6 @@ extern "C" jint JNI_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);
     return JNI_VERSION_1_4;
 }

四、客户端实现

添加一个接口 frameworks/base/core/java/android/os/Hello.java

java 复制代码
package android.os;
  
import android.annotation.Nullable;  // 导入空指针注解
import android.annotation.NonNull;
import android.annotation.SuppressLint; // 导入Lint抑制注解

@SuppressLint("RethrowRemoteException")
public abstract class Hello {

    public Hello() {
    }

    public abstract int write(@NonNull String st);

    @Nullable
    public abstract String read();
}

实现接口 frameworks/base/core/java/android/os/HelloManager.java

c 复制代码
package android.os;

import android.annotation.NonNull;      // 导入非空注解
import android.annotation.Nullable;     // 导入可空注解
import android.annotation.SuppressLint; // 导入Lint抑制注解
import android.content.Context;
import android.os.ServiceManager;       // 补全ServiceManager导入(原代码漏了)
import android.os.RemoteException;      // 导入RemoteException用于捕获
import android.os.ServiceSpecificException; // 新增:系统推荐的RuntimeException子类
import android.util.Log;

/**
 * Vibrator implementation that controls the main system vibrator.
 *
 * @hide
 */
// 抑制RethrowRemoteException(核心,解决异常声明问题)
@SuppressLint("RethrowRemoteException")
public class HelloManager extends Hello {

    private static final String TAG = "HelloManager";
    private final IHelloService mService;

    // 获取Hello服务的代理端
    public HelloManager() {
        mService = IHelloService.Stub.asInterface(
                ServiceManager.getService("HelloService"));
    }

    @Override
    public int write(@NonNull String str) {
        if (str == null) {
            Log.e(TAG, "write str is null");
            throw new IllegalArgumentException("str must not be null");
        }
        if (mService != null) {
            try {
                mService.write(str);
                return 0; // 调用成功返回0
            } catch (RemoteException e) {
                Log.e(TAG, "write failed: ", e);
                throw new ServiceSpecificException(1002, "write remote service failed: " + e.getMessage());
            }
        }
        Log.w(TAG, "mService is null, write failed");
        return -1; // 服务为空返回-1
    }

    @Nullable
    @Override
    public String read() {
        if (mService != null) {
            try {
                return mService.read(); // 调用成功返回读取结果
            } catch (RemoteException e) {
                Log.e(TAG, "read failed: ", e);
                throw new ServiceSpecificException(1003, "read remote service failed: " + e.getMessage());
            }
        }
        Log.w(TAG, "mService is null, read return null");
        return null; // 服务为空返回null
    }
}

五、服务端和客户端的注册

最最最重要的莫过于这里服务端和客户端的注册了

frameworks/base/core/java/android/content/Context.java 中添加:

c 复制代码
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
index 3dc3d78153..4d0c92299c 100644
--- a/frameworks/base/core/java/android/content/Context.java
+++ b/frameworks/base/core/java/android/content/Context.java
@@ -3600,6 +3600,7 @@ public abstract class Context {
 
     /** @hide */
     @StringDef(suffix = { "_SERVICE" }, value = {
+            HELLO_SERVICE,
             POWER_SERVICE,
             //@hide: POWER_STATS_SERVICE,
             WINDOW_SERVICE,
@@ -3961,6 +3962,8 @@ public abstract class Context {
      */
     public static final String POWER_SERVICE = "power";
 
+    public static final String HELLO_SERVICE = "hello";
+
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.os.PowerStatsService} for accessing power stats

5.1 注册服务端

修改 frameworks/base/services/java/com/android/server/SystemServer.java:

c 复制代码
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
index 16c9475658..f104d7185b 100644
--- a/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -1457,6 +1457,10 @@ public final class SystemServer implements Dumpable {
             mSystemServiceManager.startService(KeyChainSystemService.class);
             t.traceEnd();
 
+            t.traceBegin("StartHelloService");
+            ServiceManager.addService("HelloService", new HelloService());
+            t.traceEnd();
+
             t.traceBegin("StartSchedulingPolicyService");
             ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
             t.traceEnd()

5.2 注册客户端

c 复制代码
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
index 32ea41b2c7..5e2d6b0b57 100644
--- a/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -147,6 +147,8 @@ import android.net.vcn.VcnManager;
 import android.net.wifi.WifiFrameworkInitializer;
 import android.net.wifi.nl80211.WifiNl80211Manager;
 import android.nfc.NfcManager;
+import android.os.Hello;
+import android.os.HelloManager;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.BatteryStatsManager;
@@ -290,6 +292,13 @@ public final class SystemServiceRegistry {
                 return new AccountManager(ctx, service);
             }});
 
+        registerService(Context.HELLO_SERVICE, Hello.class,
+            new CachedServiceFetcher<Hello>() {
+            @Override
+            public Hello createService(ContextImpl ctx) {
+                return new HelloManager();
+            }});
+
         registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                 new CachedServiceFetcher<ActivityManager>() {
             @Override

5.3 更新api文件

c 复制代码
git diff frameworks/base/core/api/current.txt
diff --git a/frameworks/base/core/api/current.txt b/frameworks/base/core/api/current.txt
index 624ded0577..cf65840113 100644
--- a/frameworks/base/core/api/current.txt
+++ b/frameworks/base/core/api/current.txt
@@ -10644,6 +10644,7 @@ package android.content {
     field public static final String FINGERPRINT_SERVICE = "fingerprint";
     field public static final String GAME_SERVICE = "game";
     field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
+    field public static final String HELLO_SERVICE = "hello";
     field public static final String INPUT_METHOD_SERVICE = "input_method";
     field public static final String INPUT_SERVICE = "input";
     field public static final String IPSEC_SERVICE = "ipsec";
@@ -31288,6 +31289,12 @@ package android.os {
     field public static final float UNDEFINED_TEMPERATURE = -3.4028235E38f;
   }
 
+  public abstract class Hello {
+    ctor public Hello();
+    method @Nullable public abstract String read();
+    method public abstract int write(@NonNull String);
+  }
+
   public interface IBinder {

六、Selinux 配置

在自己的项目下更改或添加如下规则

6.1 service_contexts

c 复制代码
HelloService              u:object_r:HelloServiceType:s0
规则语句 含义作用
HelloService u:object_r:HelloServiceType:s0 系统服务名称「HelloService」与 SELinux 安全上下文「u:object_r:HelloServiceType:s0」做绑定映射;安全上下文格式固定为 用户:角色:SELinux类型:安全级别,核心有效内容为HelloServiceType

6.2 service.te

c 复制代码
type HelloServiceType, app_api_service, system_server_service, service_manager_type;
规则语句 含义作用
type HelloServiceType, app_api_service, system_server_service, service_manager_type; 显式定义一个全新的 SELinux 自定义类型「HelloServiceType」,并为该类型绑定 3 个系统预置的核心属性标签,多个属性用逗号分隔

6.3 platform_app.te

c 复制代码
allow platform_app HelloServiceType:service_manager find;
规则语句 含义作用
allow platform_app HelloServiceType:service_manager find; 遵循 SELinux 核心语法:允许「主体类型 - platform_app」对「客体类型 - HelloServiceType」的「资源类别 - service_manager(系统服务管理器)」执行「find(查找)」这一个权限

6.4 untrusted_app.te

c 复制代码
allow untrusted_app HelloServiceType:service_manager find;
规则语句 含义作用
allow untrusted_app HelloServiceType:service_manager find; 遵循 SELinux 核心语法:允许「主体类型 - untrusted_app」对「客体类型 - HelloServiceType」的「资源类别 - service_manager」执行「find(查找)」权限

6.5 system_server.te

c 复制代码
allow system_server HelloServiceType:service_manager { add find };
allow system_server hello_hidl_hwservice:hwservice_manager { find };
allow system_server hello_hidl:binder { call };
规则语句 含义作用
allow system_server HelloServiceType:service_manager { add find }; 遵循 SELinux 核心语法:允许「主体类型 - system_server」对「客体类型 - HelloServiceType」的「资源类别 - service_manager」执行「add(注册)+find(查找)」两个权限
allow system_server hello_hidl_hwservice:hwservice_manager { find }; 遵循 SELinux 核心语法:允许「主体类型 - system_server」对「客体类型 - hello_hidl_hwservice」的「资源类别 - hwservice_manager(HIDL 服务管理器)」执行「find(查找)」权限
allow system_server hello_hidl:binder { call }; 遵循 SELinux 核心语法:允许「主体类型 - system_server」对「客体类型 - hello_hidl」的「资源类别 - binder(安卓跨进程通信核心)」执行「call(远程调用)」权限

七、编译运行

c 复制代码
source build/envsetup.sh
lunch xxx
make -j32
相关推荐
鹏程十八少2 小时前
1.Android 3分钟跑通腾讯 Shadow 插件化官方Demo:零反射、手把手实战(基于源码依赖)
android·前端·面试
SY_FC2 小时前
niapp开发的 H5 被app嵌套,H5调用ios和安卓方法
android·ios·cocoa
假装我不帅2 小时前
rider开发asp.net webform项目
android·okhttp·asp.net
元媛媛2 小时前
UiPath |5个基础自动化场景
android·java·自动化
未来之窗软件服务2 小时前
幽冥大陆(九十七)分词服务训练源码dic生成 —东方仙盟练气期
android
Kapaseker2 小时前
千锤百炼写View 摸爬滚打名声就
android·kotlin
虫小宝2 小时前
微信群发消息API接口对接中Java后端的请求参数校验与异常反馈优化技巧
android·java·开发语言
三少爷的鞋3 小时前
架构避坑:为什么 UseCase 不该启动协程,也不该切线程?
android
Mr -老鬼3 小时前
Android studio 最新Gradle 8.13版本“坑点”解析与避坑指南
android·ide·android studio