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

相关文章

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G

Java后端微服务架构下的API限流策略:Guava RateLimiter

Java后端微服务架构下的API限流策略:Guava RateLimiter 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在微服务架构中,API限流是保护服务不受过度使用和拒绝服务攻击的重要手段。Guava RateLimiter是Google开源的Java库中的一个组件,提供了简单易用的限流功能。 API限流概述 API限流通过控制请求的速率来防止

【微服务】Ribbon(负载均衡,服务调用)+ OpenFeign(服务发现,远程调用)【详解】

文章目录 1.Ribbon(负载均衡,服务调用)1.1问题引出1.2 Ribbon负载均衡1.3 RestTemplate整合Ribbon1.4 指定Ribbon负载均衡策略1.4.1 配置文件1.4.2 配置类1.4.3 定义Ribbon客户端配置1.4.4 自定义负载均衡策略 2.OpenFeign面向接口的服务调用(服务发现,远程调用)2.1 OpenFeign的使用2.1 .1创建

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的