Android11添加AIDL系统服务及HIDL接口服务

软件平台:Android11

硬件平台:QCS6125

    直接上需求:首先添加自定义系统服务并且开机自启动;其次该服务要调用HW层service的方法。

    前半部分之前添加过N次,不是难点,后半部分的实现最开始也是想借助binder通信,直接去调用接口,遇到了一大堆selinux权限问题,这是google针对android8.0之后新添加的策略,使用了三个binder,分别是标准/dev/binder该节点主要用于System分区的系统服务去注册使用,/dev/hwbinder该节点主要用于运行于HW的服务注册使用,/dev/vndbinder该节点主要用于运行在vendor分区的服务注册使用,而需求中所说的HW层的服务注册的是vndbinder,自定义的服务是binder,因此系统层面是隔离的,无法通过binder直接通信,只能通过hwbinder去迂回,因为binder可以跟hwbinder通信,而hwbinder可以和vndbinder交互,从而达到binder服务和vndbinder服务通信的目的。

前半部分(系统服务)的实现:

1、创建frameworks/base/core/java/android/app/yfd/目录,建立如下文件:

HandWriteManager.java

/*************************************************************************
	* File Name: HandWriteManager.java
	* Author: kongbo 
	* Mail: shenyoutianji@126.com 
	* Created Time: 2022年11月21日 星期一 17时17分35秒
 ************************************************************************/
package android.app.yfd;

import android.content.Context;

import android.os.RemoteException;

import android.util.Slog;

public class HandWriteManager {

    Context mContext;

    IHandWriteManager mService;

    static final String TAG = "HandWriteManager";

    public HandWriteManager(Context context, IHandWriteManager service) {

        mContext = context;

        mService = service;

        if (mService != null)

            Slog.d(TAG, " mService not null");

    }
		
	public void setRefreshMode(int mode) {

        if (mService != null) {
            Slog.d(TAG, " Will setRefreshMode");
            try {
                mService.setRefreshMode(mode);

            } catch (RemoteException e) {

                Slog.d(TAG, "RemoteException " + e);

            }

        }

        //return null;
    }

    public void commitRefreshArea(int x, int y, int h, int w) {
        if (mService != null) {
            Slog.d(TAG, " Will commitRefreshArea");
            try {
                mService.commitRefreshArea(x, y, h, w);

            } catch (RemoteException e) {

                Slog.d(TAG, "RemoteException " + e);

            }

        }
    }

}

IHandWriteManager.aidl

/**

* Hand Writes Service

*/

package android.app.yfd;

interface IHandWriteManager {

    void setRefreshMode(int mode);

    void commitRefreshArea(int x, int y, int h, int w);

}

frameworks/base/services/core/java/com/android/server目录添加HandWriteManagerService.java

/*************************************************************************
	* File Name: HandWriteManagerService.java
	* Author: kongbo
	* Mail:nubility@gmail.com 
	* Created Time: 2022年11月21日 星期一 17时36分04秒
 ************************************************************************/
package com.android.server;

import android.app.yfd.IHandWriteManager;

import android.content.Context;

import android.os.Build;

import android.util.Slog;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.FileReader;

import java.io.IOException;

public class HandWriteManagerService extends IHandWriteManager.Stub {

    private Context mContext;

    static final String TAG = "HandWriteManagerService";

    private boolean Debug = true;

    private final int LEISURE_MODE = 1;

    private final int WRITE_MODE = 2;

    private final int NETWORK_MODE = 3;

    private native void HandWriteServiceNative_setRefreshMode(int mode);
    private native void HandWriteServiceNative_Init();
    private native void HandWriteServiceNative_commitRefreshArea(int x, int y, int h, int w);

	public HandWriteManagerService(Context context) {
        //Slog.e(TAG," ====== call native method HandWriteServiceNative_Init");
        HandWriteServiceNative_Init();
        mContext = context;
		/*try {
            Slog.e(TAG," ====== Runtime will exec ======");
            Runtime.getRuntime().exec("su");
            Runtime.getRuntime().exec("vndservice call display.qservice 47 i32 2");
            Slog.e(TAG," ====== Runtime exec end ======");
		} catch (IOException e) {
            Slog.e(TAG," ====== Runtime exec has exception ======");
            e.printStackTrace();
		}*/
    }

    @Override
    public void setRefreshMode(int mode) {
        BufferedWriter bufWriter = null;

        try {

            //bufWriter = new BufferedWriter(new FileWriter(LMAP_BRIGHTNESS_PATH));

            if (Debug)
                Slog.e(TAG," ====== write brightness:");

            HandWriteServiceNative_setRefreshMode(mode);

            //bufWriter.write(String.valueOf(brightness));

            //bufWriter.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    @Override
    public void commitRefreshArea(int x, int y, int h, int w) {
        HandWriteServiceNative_commitRefreshArea(x, y, h, w);
    }
}

向SystemServer完成注册:

diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3d8328bd193..1279df76dd5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -89,6 +89,7 @@ import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.ILockSettings;
+import com.android.server.HandWriteManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.appbinding.AppBindingService;
 import com.android.server.attention.AttentionManagerService;
@@ -1614,6 +1615,16 @@ public final class SystemServer {
             }
             t.traceEnd();
 
+            t.traceBegin("StartHandWriteManagerService");
+            try {
+                Slog.i(TAG, "HandWriteManagerService is create");
+                ServiceManager.addService(Context.HAND_WRITE_SERVICE,
+                        new HandWriteManagerService(context));
+            } catch (Throwable e) {
+                reportWtf("starting HandWriteManagerService", e);
+            }
+            t.traceEnd();
+
             t.traceBegin("StartNotificationManager");
             mSystemServiceManager.startService(NotificationManagerService.class);
             SystemNotificationChannels.removeDeprecated(context);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e599a5ce81e..38473ee5e6e 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -43,6 +43,8 @@ import android.app.usage.IUsageStatsManager;
 import android.app.usage.NetworkStatsManager;
 import android.app.usage.StorageStatsManager;
 import android.app.usage.UsageStatsManager;
+import android.app.yfd.HandWriteManager;
+import android.app.yfd.IHandWriteManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
 import android.companion.CompanionDeviceManager;
@@ -1189,6 +1191,17 @@ public final class SystemServiceRegistry {
                     }
                 });
 
+        registerService(Context.HAND_WRITE_SERVICE, HandWriteManager.class,
+                new CachedServiceFetcher<HandWriteManager>() {
+                    @Override
+                    public HandWriteManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder b = ServiceManager.getServiceOrThrow(
+                                Context.HAND_WRITE_SERVICE);
+                        return new HandWriteManager(ctx, IHandWriteManager.Stub.asInterface(b));
+                    }
+                });
+
         registerService(Context.SLICE_SERVICE, SliceManager.class,
                 new CachedServiceFetcher<SliceManager>() {
                     @Override

在Context.java添加服务ID定义:

diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8472144a92c..d9ee340cd55 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5024,6 +5024,15 @@ public abstract class Context {
      */
     public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
 
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.app.yfd.HandWriteManager} for handwriting
+     *
+     * @see #getSystemService(String)
+     * @see android.app.yfd.HandWriteManager
+     */
+    public static final String HAND_WRITE_SERVICE  = "hand_write";
+
     /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.se.omapi.ISecureElementService}

此时增量编译代码,会提示api需要更新还有一个lint检测的报错,API更新执行make update-api指令,去掉lint检查需要修改framework/base/Android.bp如下:

diff --git a/Android.bp b/Android.bp
index bf6c99d0cf2..bb4a6a9a4e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1219,7 +1219,8 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x
     "--api-lint-ignore-prefix android.icu. " +
     "--api-lint-ignore-prefix java. " +
     "--api-lint-ignore-prefix junit. " +
-    "--api-lint-ignore-prefix org. "
+    "--api-lint-ignore-prefix org. " +
+    "--api-lint-ignore-prefix android.app.yfd. "
 
 build = [
     "StubLibraries.bp",

在执行完make update-api之后,系统会自动更新api文件:

diff --git a/api/current.txt b/api/current.txt
index 952ccdad992..f91544dde68 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8106,6 +8106,37 @@ package android.app.usage {
 
 }
 
+package android.app.yfd {
+
+  public class HandWriteManager {
+    ctor public HandWriteManager(android.content.Context, android.app.yfd.IHandWriteManager);
+    method public void commitRefreshArea(int, int, int, int);
+    method public void setRefreshMode(int);
+  }
+
+  public interface IHandWriteManager extends android.os.IInterface {
+    method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+    method public void setRefreshMode(int) throws android.os.RemoteException;
+  }
+
+  public static class IHandWriteManager.Default implements android.app.yfd.IHandWriteManager {
+    ctor public IHandWriteManager.Default();
+    method public android.os.IBinder asBinder();
+    method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+    method public void setRefreshMode(int) throws android.os.RemoteException;
+  }
+
+  public abstract static class IHandWriteManager.Stub extends android.os.Binder implements android.app.yfd.IHandWriteManager {
+    ctor public IHandWriteManager.Stub();
+    method public android.os.IBinder asBinder();
+    method public static android.app.yfd.IHandWriteManager asInterface(android.os.IBinder);
+    method public static android.app.yfd.IHandWriteManager getDefaultImpl();
+    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+    method public static boolean setDefaultImpl(android.app.yfd.IHandWriteManager);
+  }
+
+}
+
 package android.appwidget {
 
   public class AppWidgetHost {
@@ -10190,6 +10221,7 @@ package android.content {
     field public static final String EUICC_SERVICE = "euicc";
     field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
     field public static final String FINGERPRINT_SERVICE = "fingerprint";
+    field public static final String HAND_WRITE_SERVICE = "hand_write";
     field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final String INPUT_METHOD_SERVICE = "input_method";
     field public static final String INPUT_SERVICE = "input";
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 5f15216e840..c6047ab6ff4 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -8106,6 +8106,37 @@ package android.app.usage {
 
 }
 
+package android.app.yfd {
+
+  public class HandWriteManager {
+    ctor public HandWriteManager(android.content.Context, android.app.yfd.IHandWriteManager);
+    method public void commitRefreshArea(int, int, int, int);
+    method public void setRefreshMode(int);
+  }
+
+  public interface IHandWriteManager extends android.os.IInterface {
+    method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+    method public void setRefreshMode(int) throws android.os.RemoteException;
+  }
+
+  public static class IHandWriteManager.Default implements android.app.yfd.IHandWriteManager {
+    ctor public IHandWriteManager.Default();
+    method public android.os.IBinder asBinder();
+    method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+    method public void setRefreshMode(int) throws android.os.RemoteException;
+  }
+
+  public abstract static class IHandWriteManager.Stub extends android.os.Binder implements android.app.yfd.IHandWriteManager {
+    ctor public IHandWriteManager.Stub();
+    method public android.os.IBinder asBinder();
+    method public static android.app.yfd.IHandWriteManager asInterface(android.os.IBinder);
+    method public static android.app.yfd.IHandWriteManager getDefaultImpl();
+    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+    method public static boolean setDefaultImpl(android.app.yfd.IHandWriteManager);
+  }
+
+}
+
 package android.appwidget {
 
   public class AppWidgetHost {
@@ -10190,6 +10221,7 @@ package android.content
<think>我们即将讨论如何通过反射调用HIDL服务HIDL(HALInterface DefinitionLanguage)是Android为硬件抽象层定义的接口语言,用于替换旧的HAL。在Android8.0(Oreo)及以上版本中,系统服务与硬件之间的通信使用HIDL。反射调用HIDL服务的步骤:1.获取HIDL服务的Manager(例如,通过ServiceManager获取)。2.获取服务的IBinder对象。3.通过反射获取HIDL的Stub类(通常以`IHwBinder`形式存在)。4.将IBinder转换为具体的HIDL接口。5.通过反射调用接口的方法。注意:HIDL服务通常运行在系统进程(如system_server)或硬件进程(如vendor进程)中,调用可能需要系统权限。以下是一个示例,展示如何通过反射调用`android.hardware.vibrator@1.0::IVibrator`服务的`on`方法。注意:实际应用中,由于HIDL服务通常需要系统权限,普通应用可能无法调用。此示例主要用于系统级开发或测试。步骤:1.获取ServiceManager。2.通过ServiceManager获取`vibrator`服务的IBinder。3.使用反射获取`android.hardware.vibrator@1.0::IVibrator`的Stub类。4.调用Stub的`asInterface`方法获取接口实例。5.反射调用`on`方法。代码示例: ```javaimport android.os.IBinder; importandroid.os.RemoteException; importandroid.util.Log;import java.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method;public classHidlReflectionHelper {privatestatic finalString TAG= "HidlReflectionHelper";//HIDL服务的全名,格式为"package@version::interface"private staticfinal StringVIBRATOR_HIDL_INTERFACE= "android.hardware.vibrator@1.0::IVibrator";privatestatic finalString VIBRATOR_SERVICE_NAME= "vibrator";publicstatic voidvibrateOn(inttimeoutMs) {try{//1.获取ServiceManager类Class<?> serviceManagerClass= Class.forName("android.os.ServiceManager");//2.获取getService方法Method getServiceMethod= serviceManagerClass.getMethod("getService",String.class);//3.调用getService方法获取vibrator服务的IBinderIBinder binder= (IBinder) getServiceMethod.invoke(null,VIBRATOR_SERVICE_NAME);if(binder ==null){Log.e(TAG, "Failed toget vibrator servicebinder");return;}//4.获取HIDL Stub类Class<?>stubClass= Class.forName(VIBRATOR_HIDL_INTERFACE.replace("::", "$") +"$Stub");//5.获取asInterface方法Method asInterfaceMethod= stubClass.getMethod("asInterface", android.os.IHwBinder.class);//6.调用asInterface方法获取接口实例ObjectvibratorService =asInterfaceMethod.invoke(null, (android.os.IHwBinder) binder);//7.获取on方法Method onMethod =vibratorService.getClass().getMethod("on",int.class);//8.调用on方法onMethod.invoke(vibratorService, timeoutMs);Log.d(TAG, "Vibratoron for" +timeoutMs+ "ms");}catch (ClassNotFoundException| NoSuchMethodException |IllegalAccessException |InvocationTargetException| RemoteException e) {Log.e(TAG,"Errorinvoking vibrator HIDLservice",e);}}} ```注意:-由于HIDL接口在Java中是以内部类的形式存在,所以类名中的`::`需要替换为`$`,并加上`$Stub`。-需要将IBinder转换为`android.os.IHwBinder`(因为HIDL服务使用IHwBinder)。 -调用`on`方法时,参数类型为`int`。但是,上述代码在非系统应用上可能无法运行,因为普通应用无法访问`android.os.ServiceManager`和HIDL接口类。因此,通常需要在系统应用或具有系统权限的环境下运行。另外,从Android10开始,HIDL逐渐被AIDL forHAL取代,但仍有大量设备使用HIDL。高级技巧:如果无法直接访问HIDL类,可以考虑使用`android.os.IHwBinder`和`android.os.HwRemoteBinder`来发送原始请求。但这种方式更复杂,需要构造正确的数据格式。下面是一个使用`IHwBinder`发送原始请求的示例(仅作为高级参考,通常不推荐): ```java//注意:此方法非常底层且复杂,需要了解HIDL的编解码协议publicstatic voidrawVibrateOn(IHwBinderbinder,int timeoutMs)throws RemoteException {//构造HIDL事务int transactionId=1;//每个方法在接口中有固定的事务ID,需要从.hal文件中获取android.os.HwParcelrequest=new android.os.HwParcel();android.os.HwParcel reply= newandroid.os.HwParcel();try {request.writeInterfaceToken(VIBRATOR_HIDL_INTERFACE);request.writeInt32(timeoutMs);binder.transact(transactionId, request, reply,0 /*flags */);reply.verifySuccess();} finally{request.release();reply.release();} }```在实际使用中,需要知道每个方法对应的事务ID(transactionID),这个ID定义在HIDL接口文件中。例如,在`IVibrator.hal`中,`on`方法可能被赋予事务ID1(具体ID需要查看源码或生成的Java文件)。由于这种方式非常脆弱(事务ID可能变化,且需要处理复杂的编解码),因此除非必要,否则不推荐使用。总结:反射调用HIDL服务需要系统权限和正确的类路径,通常用于系统应用或系统开发中。§§相关问题§§: 1. HIDLAIDL有什么区别?在Android中各自的应用场景是什么?2.如何为自定义硬件创建HIDL服务?3.Android10及以上版本中,AIDLfor HAL如何取代HIDL?4.如何通过反射调用Android系统服务(非HIDL)?</think># Android 反射调用 HIDL 服务的完整指南 HIDL(HAL Interface Definition Language)是 Android 8.0 引入的硬件抽象层接口定义语言,用于替代传统的 HAL。在某些场景下,开发者可能需要通过反射机制访问 HIDL 服务,尤其是在系统级开发或逆向工程中。 ## HIDL 反射调用核心原理 HIDL 服务调用的反射流程: 1. 获取 HIDL 服务的 `IBinder` 对象 2. 通过反射获取 HIDL 接口的 `Stub` 类 3. 使用 `asInterface()` 方法获取代理对象 4. 反射调用目标方法 ## 完整反射实现代码 ```java import android.os.IBinder; import android.os.IHwBinder; import android.os.RemoteException; import android.util.Log; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class HidlReflectionHelper { private static final String TAG = "HidlReflectionHelper"; /** * 反射调用 HIDL 服务 * * @param serviceName HIDL 服务名称 (如 "android.hardware.vibrator@1.0::IVibrator") * @param methodName 要调用的方法名 * @param params 方法参数 * @return 方法调用结果 */ public static Object invokeHidlService(String serviceName, String methodName, Object... params) { try { // 1. 获取 HwServiceManager Class<?> hwServiceManagerClass = Class.forName("android.os.HwServiceManager"); Method getServiceMethod = hwServiceManagerClass.getMethod("getService", String.class, String.class); // 2. 解析服务名 String[] parts = serviceName.split("::"); if (parts.length != 2) { throw new IllegalArgumentException("Invalid service name format"); } String ifaceName = parts[0]; String instanceName = parts[1]; // 3. 获取 IHwBinder IHwBinder binder = (IHwBinder) getServiceMethod.invoke(null, ifaceName, instanceName); if (binder == null) { throw new RuntimeException("HIDL service not found: " + serviceName); } // 4. 加载 Stub 类 String stubClassName = ifaceName + "$Stub"; Class<?> stubClass = Class.forName(stubClassName); // 5. 获取 asInterface 方法 Method asInterfaceMethod = stubClass.getMethod("asInterface", IHwBinder.class); // 6. 创建服务代理对象 Object serviceProxy = asInterfaceMethod.invoke(null, binder); // 7. 准备参数类型数组 Class<?>[] paramTypes = new Class<?>[params.length]; for (int i = 0; i < params.length; i++) { paramTypes[i] = params[i].getClass(); } // 8. 获取目标方法 Method targetMethod = findMethod(serviceProxy.getClass(), methodName, paramTypes); // 9. 调用服务方法 return targetMethod.invoke(serviceProxy, params); } catch (Exception e) { Log.e(TAG, "Error invoking HIDL service", e); throw new RuntimeException("Failed to invoke HIDL service", e); } } // 查找方法(处理参数类型转换) private static Method findMethod(Class<?> clazz, String methodName, Class<?>[] paramTypes) throws NoSuchMethodException { for (Method method : clazz.getDeclaredMethods()) { if (method.getName().equals(methodName)) { Class<?>[] methodParamTypes = method.getParameterTypes(); if (methodParamTypes.length == paramTypes.length) { boolean match = true; for (int i = 0; i < paramTypes.length; i++) { if (!methodParamTypes[i].isAssignableFrom(paramTypes[i])) { match = false; break; } } if (match) { return method; } } } } throw new NoSuchMethodException(methodName + " with matching parameters"); } } ``` ## 使用示例:控制设备震动 ```java public class VibratorController { private static final String VIBRATOR_SERVICE = "android.hardware.vibrator@1.0::IVibrator"; public static void vibrate(int durationMs) { try { HidlReflectionHelper.invokeHidlService( VIBRATOR_SERVICE, "on", durationMs ); Log.d("Vibrator", "Vibration started for " + durationMs + "ms"); } catch (Exception e) { Log.e("Vibrator", "Failed to vibrate", e); } } public static void cancelVibration() { try { HidlReflectionHelper.invokeHidlService( VIBRATOR_SERVICE, "off" ); Log.d("Vibrator", "Vibration cancelled"); } catch (Exception e) { Log.e("Vibrator", "Failed to cancel vibration", e); } } } ``` ## 关键点解析 ### 1. HIDL 服务命名规范 HIDL 服务名称遵循特定格式: ``` <package>@<version>::<interface> ``` 例如: - `android.hardware.vibrator@1.0::IVibrator` - `android.hardware.light@2.0::ILight` ### 2. HIDLAIDL 反射的区别 | 特性 | HIDL 反射 | AIDL 反射 | |------------------|-------------------------------|-------------------------------| | 服务管理器 | `HwServiceManager` | `ServiceManager` | | Binder 类型 | `IHwBinder` | `IBinder` | | 接口转换方法 | `Stub.asInterface(IHwBinder)` | `Stub.asInterface(IBinder)` | | 参数处理 | 使用 `HwBlob`/`HwParcel` | 使用 `Parcel` | | 主要应用场景 | 硬件抽象层服务 | 系统服务和应用服务 | ### 3. 处理复杂数据类型 当传递复杂类型时,需要使用 HIDL 的序列化机制: ```java // 创建自定义类型 public class CustomData { public int value1; public String value2; } // 序列化为 HwParcel public static android.os.HwParcel toHwParcel(CustomData data) { android.os.HwParcel parcel = new android.os.HwParcel(); parcel.writeInt32(data.value1); parcel.writeString(data.value2); return parcel; } // 在反射调用中使用 CustomData data = new CustomData(); data.value1 = 42; data.value2 = "test"; HidlReflectionHelper.invokeHidlService( "custom.package@1.0::IService", "processData", toHwParcel(data) ); ``` ### 4. 权限要求 HIDL 服务通常需要系统权限: ```xml <uses-permission android:name="android.permission.ACCESS_HARDWARE" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> ``` 在 AndroidManifest.xml 中添加: ```xml <application android:sharedUserId="android.uid.system" ...> ``` ## 高级技巧:直接使用 HwBinder 对于更底层的访问,可以直接操作 `IHwBinder`: ```java public static void rawHidlCall(String serviceName, int transactionId, Object... params) { try { // 获取 IHwBinder IHwBinder binder = getHidlBinder(serviceName); // 创建请求和响应 Parcel android.os.HwParcel request = new android.os.HwParcel(); android.os.HwParcel reply = new android.os.HwParcel(); // 写入接口令牌 request.writeInterfaceToken(getInterfaceToken(serviceName)); // 写入参数 for (Object param : params) { if (param instanceof Integer) { request.writeInt32((Integer) param); } else if (param instanceof String) { request.writeString((String) param); } // 处理其他类型... } // 执行事务 binder.transact(transactionId, request, reply, 0); // 读取响应 reply.verifySuccess(); int result = reply.readInt32(); Log.d("RawHidl", "Transaction result: " + result); } catch (Exception e) { Log.e("RawHidl", "Raw HIDL call failed", e); } } private static String getInterfaceToken(String serviceName) { return serviceName.split("::")[0]; // 返回包名@版本 } ``` ## 安全注意事项 1. **权限验证**:HIDL 服务应实现严格的权限检查 ```cpp // 在 HIDL 服务实现中 (C++) Return<void> MyService::on(uint32_t duration) { if (!checkCallingPermission("android.permission.DEVICE_POWER")) { return Void(); } // 实际实现 } ``` 2. **输入验证**:所有参数都应进行有效性检查 3. **异常处理**:捕获所有可能的异常 4. **服务稳定性**:避免频繁调用可能影响硬件稳定性的方法 ## HIDL 2.0 与 AIDL HAL 的演进 从 Android 10 开始,Google 引入了 AIDL HAL 作为 HIDL 的替代方案: - 使用标准的 AIDL 语法 - 更好的版本兼容性 - 更简单的集成方式 对于新项目,建议优先使用 AIDL HAL: ```java // AIDL HAL 服务绑定 IBinder binder = ServiceManager.getService("my.hal.service"); IMyHalService service = IMyHalService.Stub.asInterface(binder); service.doSomething(); ``` ## 常见问题解决 **问题:`ClassNotFoundException` for HIDL Stub** - 确保 HIDL 接口在设备上已实现 - 检查类名是否正确(区分大小写) - 确认设备 Android 版本支持该 HIDL 版本 **问题:`NoSuchMethodException`** - 使用 `getDeclaredMethods()` 检查可用方法 - 确认方法签名(参数类型和顺序) - 检查 HIDL 版本是否匹配 **问题:权限拒绝** - 确保应用具有系统签名 - 在 `AndroidManifest.xml` 中声明所需权限 - 检查 SELinux 策略是否允许访问
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值