传统 Hal 开发笔记5 —— 添加硬件访问服务

目录


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

一、添加 aidl 文件

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

java 复制代码
package android.os;
  
/**
 * @hide
 */
interface IHelloService {
    void open();
    void write(String str);
    String read();
}

二、服务端实现

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

java 复制代码
package com.android.server;
  
import android.os.IHelloService;

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

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

    public void open() throws android.os.RemoteException {
        natvieOpen();
    }

    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 <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
{

static hw_module_t *gHelloModule = NULL;
static hello_hal_device_t *gHelloHalDevice = NULL;

static void helloOpen(JNIEnv env, jobject clazz)
{
    ALOGD("Hello_test_jni_open");
    if (gHelloModule != NULL) {
        return;
    }

    int err = hw_get_module(HELLO_HAL_HARDWARE_MODULE_ID, (hw_module_t const**)&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);
    }
}


static void helloWrite(JNIEnv* env, jobject clazz, jstring str)
{

    if (gHelloHalDevice) {
         ALOGD("Hello_test_jni_write");
        const char * 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.");
    }
}

static jstring helloRead(JNIEnv* env, jobject clazz) {
    if (gHelloHalDevice) {
        ALOGD("Hello_test_jni_read");
        char* data = (char*)malloc(1024);
        if (data == NULL) {
            ALOGE("helloRead: malloc data failed");
            return env->NewStringUTF("malloc fail");
        }
        memset(data, 0, 1024);
        int ret = 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_t str_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, (const jbyte *)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);
            return retStr;
        } else {
            free(data);
            return env->NewStringUTF("no msg");
        }
    }
    return env->NewStringUTF("no msg");
}

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

static const JNINativeMethod method_table[] = {
    { "natvieOpen", "()V", (void*)helloOpen },
    { "natvieWrite", "(Ljava/lang/String;)V", (void*)helloWrite },
    { "nativeRead", "()Ljava/lang/String;", (void*)helloRead }
};


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

};                                                                                  

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

c 复制代码
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..6884e332e4 100644
--- 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 中添加:

c 复制代码
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..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;
 // 在这里注册 JNI 函数
// java 层的 native 方法就能调用到对应的 native 层函数了
@@ -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 open();

    public abstract int write(@NonNull String st);

    @Nullable
    public abstract String read();
}

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

java 复制代码
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 open() {
        if (mService != null) {
            try {
                mService.open();
                return 0; // 调用成功返回0
            } catch (RemoteException e) {
                Log.e(TAG, "open failed: ", e);
                throw new ServiceSpecificException(1001, "open remote service failed: " + e.getMessage());
            }
        }
        Log.w(TAG, "mService is null, open failed");
        return -1; // 服务为空返回-1
    }

    @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 中添加:

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
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:

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
index 16c9475658..ce7e147950 100644
--- a/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -1457,6 +1457,11 @@ 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 注册客户端

java 复制代码
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
index 32ea41b2c7..4603e03935 100644
--- a/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -184,6 +184,8 @@ import android.os.image.IDynamicSystemService;
 import android.os.incremental.IIncrementalService;
 import android.os.incremental.IncrementalManager;
 import android.os.storage.StorageManager;
+import android.os.Hello;
+import android.os.HelloManager;
 import android.permission.LegacyPermissionManager;
 import android.permission.PermissionCheckerManager;
 import android.permission.PermissionControllerManager;
@@ -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 复制代码
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
index 624ded0577..df3a5edaa6 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,13 @@ package android.os {
     field public static final float UNDEFINED_TEMPERATURE = -3.4028235E38f;
   }
 
+  public abstract class Hello {
+    ctor public Hello();
+    method public abstract int open();
+    method @Nullable public abstract String read();
+    method public abstract int write(@NonNull String);
+  }
+
   public interface IBinder {

六、Selinux 配置

修改 system/sepolicy/service.te

c 复制代码
type HelloServiceType, app_api_service, system_server_service, service_manager_type;

修改 system/sepolicy/service_contexts

c 复制代码
HelloService                              u:object_r:HelloServiceType:s0

修改 system/sepolicy/platform_app.te,让系统 App 可以访问我们自定义的 Binder 服务:

c 复制代码
allow platform_app HelloServiceType:service_manager find;

修改 system/sepolicy/untrusted_app.te,让普通 App 可以访问我们自定义的 Binder 服务:

c 复制代码
allow untrusted_app HelloServiceType:service_manager find;

最后,让 SystemServer 可以访问到 hello 驱动,修改 system/sepolicy/system_server.te

c 复制代码
allow system_server hello_dev_t:chr_file { open read write };
相关推荐
恋猫de小郭6 小时前
Android 宣布 Runtime 编译速度史诗级提升:在编译时间上优化了 18%
android·前端·flutter
csj506 小时前
安卓基础之《(4)—Activity组件》
android
游戏开发爱好者87 小时前
H5 混合应用加密 Web 资源暴露到 IPA 层防护的完整技术方案
android·前端·ios·小程序·uni-app·iphone·webview
2501_915106327 小时前
最新版本iOS系统设备管理功能全面指南
android·macos·ios·小程序·uni-app·cocoa·iphone
走在路上的菜鸟8 小时前
Android学Dart学习笔记第十四节 库和导库
android·笔记·学习·flutter
姜西西_8 小时前
自动化测试框架pytest之fixture
android·java·pytest
尐葮阿譽8 小时前
Ubuntu 25.10 安装 Waydroid 安卓模拟器
android·ubuntu·安卓模拟器·waydroid
_李小白8 小时前
【Android FrameWork】实战:跟踪Android APP Surface创建流程
android
2501_915918418 小时前
iOS 性能监控 运行时指标与系统行为的多工具协同方案
android·macos·ios·小程序·uni-app·cocoa·iphone