rk3566-Android11 从驱动到 app 第三章添加 hello 服务

2024-01-26 11:28

本文主要是介绍rk3566-Android11 从驱动到 app 第三章添加 hello 服务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1. 添加 aidl 接口
    • 2. 添加 HelloService
    • 3. 添加 HelloManager 服务
    • 4. 增加 selinux 权限

作者: baron

hall 层是啥, 就是 so 库, 这个 so 库是 c++ 写的的, 而我们的系统服务和 app 有部分是 java 写的. 没法直接用啊, 于是 JNI 闪亮登场. JNI 是干啥的, 很简单, 就是将我们 hall 层的 c++ 接口转换成 java 接口. 然后我们的 framework 再将这个 java 接口导出到服务. app 就可以直接通过服务的接口操作我们的 hello 设备啦.

正常的顺序应该是添加 JNI, 但是添加之后没法直接验证, 所以先加服务方便验证和理解. 服务是啥, 服务就是长期在后台运行的进程, 我们也称之为任务组件. 它不需要用户界面进行操作. 服务的本质是进程, 因此服务与服务之间, 服务与app之间的接口调用的本质是进程间通讯. 在安卓中就是 binder.

1. 添加 aidl 接口

AIDL(Android Interface Definition Language)是 Android 中用于定义进程间通信(IPC)接口的一种语言,我们可以借助 AIDL 工具给我们自动生成继承 binder 方法的类. 来添加我们的 AIDL 吧.

创建文件 frameworks/base/core/java/android/os/IHelloService.aidl文件的内容如下所示.

package android.os;/** {@hide} */
interface IHelloService {void setVal(String value);String getVal();
}

注意了在安卓 11 之后要加上 /** {@hide} */这个注释, 不加会报错的. 我在这里卡了一天 =-= , 查不出任何问题. 这个问题请参考这篇文章, 增加aidl 文件提示Methods calling system APIs should rethrow `RemoteException` as `RuntimeException.

添加之后 AIDL 工具会帮我们生成支持 binder 的方法的类, 但我们还需扩展这个类并且实现对应的方法. 创建文件 frameworks/base/core/java/com/android/server/HelloService.java. 内容如下

package com.android.server;import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IHelloService;
import android.os.RemoteException;
import android.os.TokenWatcher;
import android.os.UpdateLock;
import android.os.UserHandle;
import android.util.Slog;import com.android.internal.util.DumpUtils;import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;//  HelloService 继承由 AIDL 自动生成的 Binder Stub 类
public class HelloService extends IHelloService.Stub {static final String TAG = "HelloService";Context mContext;// 构造函数public HelloService(Context context) {Slog.i(TAG, "HelloService init");mContext = context;}// setVal 方法@Overridepublic void setVal(String value) throws RemoteException {Slog.i(TAG, "setVal value = "+value);}// getVal 方法实现@Overridepublic String getVal() throws RemoteException {Slog.i(TAG, "getVal ");return "getVal";}
}

这里 setVal 方法和 getVal 方法直接打印 log 就行了, 后面会替换为 jni 转换 hall 接口 之后的接口. 打开 frameworks/base/Android.bp我们可以发现

filegroup {name: "framework-core-sources",srcs: ["core/java/**/*.java","core/java/**/*.aidl",],path: "core/java",
}

安卓 11 之后默认就会添加 core/java/**/下的 java 和 aidl 文件因此就不再需要我们修改 bp 文件了.

2. 添加 HelloService

添加服务之前首先需在 Context 中添加我们 HELLO_SERVICE 常量, 以后通过这个常量我们就能获取到对应的服务了.修改如下

diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5caf70aa72e0..210220bb315c 100644
-- a/core/java/android/content/Context.java
++ b/core/java/android/content/Context.java
@@ -3400,6 +3400,7 @@ public abstract class Context {STORAGE_STATS_SERVICE,WALLPAPER_SERVICE,TIME_ZONE_RULES_MANAGER_SERVICE,
+            HELLO_SERVICE,VIBRATOR_SERVICE,//@hide: STATUS_BAR_SERVICE,CONNECTIVITY_SERVICE,
@@ -5018,6 +5019,8 @@ public abstract class Context {*/public static final String TIME_ZONE_RULES_MANAGER_SERVICE = "timezone";+    public static final String HELLO_SERVICE = "hello";
+/*** Use with {@link #getSystemService(String)} to retrieve a* {@link android.content.pm.CrossProfileApps} for cross profile operations.

接下来就是在 SystemServer 中注册 HelloService , 修改文件 frameworks/base/services/java/com/android/server/SystemServer.java

diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8cb3753c0ed6..57e31c5677de 100755
-- a/services/java/com/android/server/SystemServer.java
++ b/services/java/com/android/server/SystemServer.java
@@ -1226,6 +1226,9 @@ public final class SystemServer {mSystemServiceManager.startService(PinnerService.class);t.traceEnd();+            Slog.i(TAG, "start hello Service");
+            ServiceManager.addService(Context.HELLO_SERVICE, new HelloService(context));
+t.traceBegin("IorapForwardingService");mSystemServiceManager.startService(IorapForwardingService.class);t.traceEnd();

我们的 HelloService 也是在这里实例化的. 注册之后我们就可以通过 ServiceManager.getServiceOrThrow(Context.HELLO_SERVICE)拿到 HelloService的 binder, 然后通过这个 binder 获取到这里注册的 IHelloService了.

3. 添加 HelloManager 服务

为了 app 能够获取到服务, 我们需要对 HelloService 再一次进行封装, 添加文件 frameworks/base/core/java/android/app/HelloManager.java

package android.app;import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IHelloService;
import android.util.Log;public class HelloManager {IHelloService mService;/*** @hide*/public HelloManager(Context ctx,IHelloService service){mService = service;}/*** @hide*/public void setVal(String value){try{Log.e("HelloManager","HelloManager setVal");mService.setVal(value);}catch(Exception e){Log.e("HelloManager",e.toString());e.printStackTrace();}}/*** @hide*/public String getVal(){try{Log.e("HelloManager","HelloManager getVal");return mService.getVal();}catch(Exception e){Log.e("HelloManager",e.toString());e.printStackTrace();}return null;}
}

注意了 @hide相关的注释不能去掉不然会报错. 接下来实例化这个服务并注册进系统

diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0e184fcc618b..cdafd815bb9f 100644
-- a/core/java/android/app/SystemServiceRegistry.java
++ b/core/java/android/app/SystemServiceRegistry.java
@@ -169,6 +169,7 @@ import android.os.image.IDynamicSystemService;import android.os.incremental.IIncrementalService;import android.os.incremental.IncrementalManager;import android.os.storage.StorageManager;
+import android.os.IHelloService;import android.os.IRnService;import android.permission.PermissionControllerManager;import android.permission.PermissionManager;
@@ -1233,6 +1234,23 @@ public final class SystemServiceRegistry {}});+        registerService(Context.HELLO_SERVICE, HelloManager.class,
+             new CachedServiceFetcher<HelloManager>() {
+                 @Override
+                 public HelloManager createService(ContextImpl ctx) {
+                                        try {
+                       IBinder b = ServiceManager.getServiceOrThrow(Context.HELLO_SERVICE);
+                                          Log.i(TAG, "registerService HELLO_SERVICE b = "+b);
+                       IHelloService service = IHelloService.Stub.asInterface(b);
+                                          Log.i(TAG, "registerService HELLO_SERVICE service = "+service);
+                       return new HelloManager(ctx, service);
+                     } catch (ServiceNotFoundException e) {
+                                          Log.i(TAG, "registerService ServiceNotFoundException e = "+e);
+                                          onServiceNotFound(e);
+                       return new HelloManager(ctx,null);
+                    }
+                 }});
+registerService(Context.TIME_DETECTOR_SERVICE, TimeDetector.class,new CachedServiceFetcher<TimeDetector>() {@Override

修改的全部文件如下所示

运行 make update-api更新接口, 运行之后会增加下面两个文件, 就是编译器自动给我们新增对应的接口.

之后再运行 ./build.sh -UKAup整编. 刷机报错如下所示.

01-18 11:26:10.933   429   429 I SystemServer: start hello Service
01-18 11:26:10.934   429   473 D PinnerService: pinRangeStream: null
01-18 11:26:10.935   429   429 I HelloService: HelloService init
01-18 11:26:10.935   429   473 D PinnerService: pinRangeStream: null
01-18 11:26:10.936   133   133 E SELinux : avc:  denied  { add } for pid=429 uid=1000 name=hello scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
01-18 11:26:10.936   429   473 D PinnerService: pinRangeStream: null
01-18 11:26:10.937   429   467 I DropBoxManagerService: add tag=system_server_strictmode isTagEnabled=true flags=0x2
01-18 11:26:10.940   429   429 E System  : ******************************************
01-18 11:26:10.941   429   429 E System  : ************ Failure starting core service
01-18 11:26:10.941   429   429 E System  : ******************************************
01-18 11:26:10.947   429   473 D PinnerService: pinRangeStream: null
01-18 11:26:10.948   429   473 I chatty  : uid=1000(system) android.bg identical 1 line
01-18 11:26:10.949   429   473 D PinnerService: pinRangeStream: null
01-18 11:26:10.955   429   429 E System  : ************ Failure starting system services
01-18 11:26:10.955   429   429 E System  : java.lang.SecurityException:

4. 增加 selinux 权限

请参考 SELinux权限问题解决参考

  1. 修改 system/sepolicy/public/service.te b/public/service.te
diff --git a/public/service.te b/public/service.te
index f27772eab..45d368f20 100644
-- a/public/service.te
++ b/public/service.te
@@ -146,6 +146,7 @@ type permissionmgr_service, app_api_service, ephemeral_app_api_service, system_stype persistent_data_block_service, system_api_service, system_server_service, service_manager_type;type pinner_service, system_server_service, service_manager_type;type power_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
+type hello_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;type print_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;type processinfo_service, system_server_service, service_manager_type;type procstats_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;

需要改的文件如下, 每个都要改

  1. 修改 system/sepolicy/private/service_contexts b/private/service_contexts
diff --git a/private/service_contexts b/private/service_contexts
index 5c6f1a476..157737f81 100644
-- a/private/service_contexts
++ b/private/service_contexts
@@ -166,6 +166,7 @@ phone2                                    u:object_r:radio_service:s0phone                                     u:object_r:radio_service:s0pinner                                    u:object_r:pinner_service:s0power                                     u:object_r:power_service:s0
+hello                                     u:object_r:hello_service:s0print                                     u:object_r:print_service:s0processinfo                               u:object_r:processinfo_service:s0procstats                                 u:object_r:procstats_service:s0

需要修改的文件如下, 每个都要改

改完之后编译下载. log 如下成功添加服务.

01-18 12:02:30.899   429   429 D SystemServerTiming: PinnerService took to complete: 12ms
01-18 12:02:30.899   429   429 I SystemServer: start hello Service
01-18 12:02:30.900   429   464 I DropBoxManagerService: add tag=system_server_strictmode isTagEnabled=true flags=0x2
01-18 12:02:30.900   429   473 D PinnerService: pinRangeStream: null
01-18 12:02:30.901   429   429 I HelloService: HelloService init

我们 adb shell 之后运行 service list在系统里面找见我们添加的服务.

这篇关于rk3566-Android11 从驱动到 app 第三章添加 hello 服务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/646655

相关文章

sysmain服务可以禁用吗? 电脑sysmain服务关闭后的影响与操作指南

《sysmain服务可以禁用吗?电脑sysmain服务关闭后的影响与操作指南》在Windows系统中,SysMain服务(原名Superfetch)作为一个旨在提升系统性能的关键组件,一直备受用户关... 在使用 Windows 系统时,有时候真有点像在「开盲盒」。全新安装系统后的「默认设置」,往往并不尽编

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

RabbitMQ消息总线方式刷新配置服务全过程

《RabbitMQ消息总线方式刷新配置服务全过程》SpringCloudBus通过消息总线与MQ实现微服务配置统一刷新,结合GitWebhooks自动触发更新,避免手动重启,提升效率与可靠性,适用于配... 目录前言介绍环境准备代码示例测试验证总结前言介绍在微服务架构中,为了更方便的向微服务实例广播消息,