Android13源码添加系统服务

本文基于Android 13的framework层添加系统接口,为应用层提供读写函数、以及执行命令!

添加接口

frameworks/base/core/java/android/app/IDevices.aidl

package android.app;
interface IDevices
{//读取文件String readFile(String path);//写入文件void writeFile(String path,String data);//执行shell命令String shellExec(String cmd);
}

添加系统服务的Manager

frameworks/base/core/java/android/app/DevicesManager.java

package android.app;import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.util.Slog;@SystemService(Context.DEVICES_SERVICE)
public class DevicesManager {Context mContext;IDevices mService;public DevicesManager(Context context,IDevices service){if(service==null){Slog.e("DevicesManager","Construct service is null");}mContext = context;mService = service;}public String shellExec(String cmd){if(mService != null){try{Slog.e("DevicesManager","shellExec");return mService.shellExec(cmd);}catch(RemoteException e){Slog.e("DevicesManager","RemoteException "+e);}}else{Slog.e("DevicesManager","mService is null");}return "";}public String readFile(String path){if(mService != null){try{Slog.e("DevicesManager","readFile");return mService.readFile(path);}catch(RemoteException e){Slog.e("DevicesManager","RemoteException "+e);}}else{Slog.e("DevicesManager","mService is null");}return "";}public void writeFile(String path,String data){if(mService != null){try{Slog.e("DevicesManager","writeFile");mService.writeFile(path,data);}catch(RemoteException e){Slog.e("DevicesManager","RemoteException "+e);}}else{Slog.e("DevicesManager","mService is null");}}}

添加系统服务,实现aidl文件的接口

frameworks/base/services/core/java/com/android/server/DevicesService.java

package com.android.server; import android.app.IDevices;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.util.Slog;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;import libcore.io.IoUtils;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;import android.util.Base64;public class DevicesService extends IDevices.Stub {private Context mContext;private String TAG="DevicesService";public DevicesService(Context context){super();mContext = context;Slog.d(TAG,"Construct");}@Overridepublic String shellExec(String cmd){Runtime mRuntime = Runtime.getRuntime();try {//Process中封装了返回的结果和执行错误的结果Slog.d(TAG,"shellExec data:"+cmd);Process mProcess = mRuntime.exec(cmd);BufferedReader mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));StringBuffer mRespBuff = new StringBuffer();char[] buff = new char[1024];int ch = 0;while ((ch = mReader.read(buff)) != -1) {mRespBuff.append(buff, 0, ch);}mReader.close();return mRespBuff.toString();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();Slog.d(TAG,"shellExec err:"+e.getMessage());}return "";}public static void writeTxtToFile(String strcontent, String filePath) {String strFilePath = filePath;String strContent = strcontent + "\n";  // \r\n 结尾会变成 ^Mtry {File file = new File(strFilePath);makeFilePath(file.getParent(),file.getName());if (!file.exists()) {file.getParentFile().mkdirs();file.createNewFile();}RandomAccessFile raf = new RandomAccessFile(file, "rwd");raf.setLength(0);// 写文件的位置标记,从文件开头开始,后续读取文件内容从该标记开始long writePosition = raf.getFilePointer();raf.seek(writePosition);raf.write(strContent.getBytes());raf.close();//} catch (Exception e) {Log.d("DevicesService","Error on write File:" + e);}}// 生成文件public static File makeFilePath(String filePath, String fileName) {File file = null;makeRootDirectory(filePath);try {file = new File(filePath +"/"+ fileName);if (!file.exists()) {file.createNewFile();}} catch (Exception e) {e.printStackTrace();}return file;}// 生成文件夹public static void makeRootDirectory(String filePath) {File file = null;try {Log.d("FileHelper", "makeRootDirectory "+filePath);file = new File(filePath);if (!file.exists()) {boolean isok= file.mkdir();Log.d("FileHelper", "makeRootDirectory "+filePath+" "+isok);}} catch (Exception e) {Log.d("DevicesService", e+"");}}public static String readFileAll(String path) {File file = new File(path);StringBuilder sb=new StringBuilder();if (file != null && file.exists()) {InputStream inputStream = null;BufferedReader bufferedReader = null;try {inputStream = new FileInputStream(file);bufferedReader = new BufferedReader(new InputStreamReader(inputStream));String outData;while((outData=bufferedReader.readLine())!=null){sb.append(outData+"\n");}} catch (Throwable t) {} finally {try {if (bufferedReader != null) {bufferedReader.close();}} catch (Exception e) {e.printStackTrace();}try {if (inputStream != null) {inputStream.close();}} catch (Exception e) {e.printStackTrace();}}}return sb.toString();}@Overridepublic String readFile(String path){return readFileAll(path);}@Overridepublic void writeFile(String path,String data){writeTxtToFile(data,path);}}

添加服务名称

frameworks/base/core/java/android/content/Context.java

        @StringDef(suffix = { "_SERVICE" }, value = {POWER_SERVICE,
/*add_longzhiye*/++    DEVICES_SERVICE,//@hide: POWER_STATS_SERVICE,WINDOW_SERVICE,LAYOUT_INFLATER_SERVICE,ACCOUNT_SERVICE,ACTIVITY_SERVICE,ALARM_SERVICE,public static final String POWER_SERVICE = "power";
++public static final String DEVICES_SERVICE = "devices";

将实现的服务注册到系统中去

frameworks/base/core/java/android/app/SystemServiceRegistry.java

registerService(Context.SEARCH_SERVICE, SearchManager.class,new CachedServiceFetcher<SearchManager>() {@Overridepublic SearchManager createService(ContextImpl ctx) throws ServiceNotFoundException {return new SearchManager(ctx.getOuterContext(),ctx.mMainThread.getHandler());}});
//add longzhiye
registerService(Context.DEVICES_SERVICE,DevicesManager.class,new CachedServiceFetcher<DevicesManager>(){@Overridepublic DevicesManager createService(ContextImpl ctx){IBinder b = ServiceManager.getService(Context.DEVICES_SERVICE);return new DevicesManager(ctx,IDevices.Stub.asInterface(b));} });   
//add end       
registerService(Context.SENSOR_SERVICE, SensorManager.class,new CachedServiceFetcher<SensorManager>() {@Overridepublic SensorManager createService(ContextImpl ctx) {return new SystemSensorManager(ctx.getOuterContext(),ctx.mMainThread.getHandler().getLooper());}});

将注册的服务设置成开机启动服务

frameworks/base/services/java/com/android/server/SystemServer.java

t.traceBegin("StartTelephonyRegistry");
telephonyRegistry = new TelephonyRegistry(context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
//add longzhiye
t.traceBegin("StartDevicesService");
try{ServiceManager.addService(Context.DEVICES_SERVICE,new DevicesService(context));
} catch(Throwable e){Slog.e("DevicesService","Failed to start DevicesService Service "+e);
}
t.traceEnd();
//add end

让lint检查忽略掉自己的模块

注(Android 11 以后谷歌强制开启lint检查,lint检查不过编译会报错)

frameworks/base/Android.bp

// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
metalava_framework_docs_args = "" +"--api-lint-ignore-prefix android.app. " +     //add_longzhiye"--api-lint-ignore-prefix android.icu. " +"--api-lint-ignore-prefix java. " +"--api-lint-ignore-prefix junit. " +"--api-lint-ignore-prefix org. " +"--error NoSettingsProvider " +"--error UnhiddenSystemApi " +"--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +"--hide BroadcastBehavior " +"--hide CallbackInterface " +"--hide DeprecationMismatch " +"--hide HiddenSuperclass " +"--hide HiddenTypeParameter " +"--hide MissingPermission " +"--hide-package android.audio.policy.configuration.V7_0 " +"--hide-package com.android.server " +"--hide RequiresPermission " +"--hide SdkConstant " +"--hide Todo " +"--hide Typo " +"--hide UnavailableSymbol " +"--manifest $(location core/res/AndroidManifest.xml) "

编译源码 更新api接口

make update-api

检查服务是否开启

将编译好的rom 刷入手机,查看sevice list
这里可以看到我们的服务 已经启动了:
服务名称:79 devices: [android.app.IDevices]

longzhiye@longzhiye-laptop:~$ adb shell
coral:/ # service list |grep Device
60    companiondevice: [android.companion.ICompanionDeviceManager]
75    device_identifiers: [android.os.IDeviceIdentifiersPolicyService]
76    device_policy: [android.app.admin.IDevicePolicyManager]
77    device_state: [android.hardware.devicestate.IDeviceStateManager]
78    deviceidle: [android.os.IDeviceIdleController]
79    devices: [android.app.IDevices]
251    virtualdevice: [android.companion.virtual.IVirtualDeviceManager]
coral:/ #

调用测试

应用层项目中引入aidl

// IDevices.aidl
package android.app;// Declare any non-default types here with import statementsinterface IDevices {String shellExec(String cmd);String readFile(String path);void writeFile(String path,String data);
}


调用测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/151749.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之中介模式

文章目录 一、介绍二、生活中的中介模式三、中介模式中的角色四、案例演示1. 角色分析 五、优缺点 一、介绍 中介模式(Mediator Pattern)&#xff0c;属于行为型设计模式。目的是把系统中对象之间的调用关系从一对多转变成一对一的调用关系&#xff0c;以此来降低多个对象和类…

2023全新TwoNav开源网址导航系统源码 | 去授权版

2023全新TwoNav开源网址导航系统源码 已过授权 所有功能可用 测试环境&#xff1a;NginxPHP7.4MySQL5.6 一款开源的书签导航管理程序&#xff0c;界面简洁&#xff0c;安装简单&#xff0c;使用方便&#xff0c;基础功能免费。 TwoNav可帮助你将浏览器书签集中式管理&#x…

LeetCode:1465. 切割后面积最大的蛋糕(C++)

目录 1465. 切割后面积最大的蛋糕 题目描述&#xff1a; 实现代码与解析&#xff1a; 贪心 原理思路&#xff1a; 1465. 切割后面积最大的蛋糕 题目描述&#xff1a; 矩形蛋糕的高度为 h 且宽度为 w&#xff0c;给你两个整数数组 horizontalCuts 和 verticalCuts&#xff…

基于机器视觉的行人口罩佩戴检测 计算机竞赛

简介 2020新冠爆发以来&#xff0c;疫情牵动着全国人民的心&#xff0c;一线医护工作者在最前线抗击疫情的同时&#xff0c;我们也可以看到很多科技行业和人工智能领域的从业者&#xff0c;也在贡献着他们的力量。近些天来&#xff0c;旷视、商汤、海康、百度都多家科技公司研…

安装使用vcpkg的简易教程

目录 1. 首先安装vcpkg2. 在vcpkg目录下运行bootstrap-vcpkg.bat 命令3. 接着vs进行集成4. 使用vcpkg搜索可用的包5.下载安装所需包6.下载安装完成 1. 首先安装vcpkg 使用git命令下载 git clone https://github.com/Microsoft/vcpkg.git如果下载失败可直接下载文件 (vcpkg-ma…

计算机视觉 激光雷达结合无监督学习进行物体检测的工作原理

一、简述 激光雷达是目前正在改变世界的传感器。它集成在自动驾驶汽车、自主无人机、机器人、卫星、火箭等中。该传感器使用激光束了解世界,并测量激光击中目标返回所需的时间,输出是点云信息,利用这些信息,我们可以从3D点云中查找障碍物。 从自动驾驶汽车的角度看激光雷达…

【Java】电子病历编辑器源码(云端SaaS服务)

电子病历编辑器极具灵活性&#xff0c;它既可嵌入到医院HIS系统中&#xff0c;作为内置编辑工具供多个模块使用&#xff0c;也可以独立拿出来&#xff0c;与第三方业务厂商展开合作&#xff0c;为他们提供病历书写功能&#xff0c;充分发挥编辑器的功能。 电子病历基于云端SaaS…

8、电路综合-基于简化实频的SRFT微带线的带通滤波器设计

8、电路综合-基于简化实频的SRFT微带线的带通滤波器设计 此处介绍微带线综合的巴特沃斯带通滤波器和切比雪夫带通滤波器的设计方法。对于理查德域的网络综合技术而言&#xff0c;这种带通综合和低通综合在本质上并无区别&#xff0c;因为理查德域函数是周期的。低通滤波器的SR…

Python中的*args 和 **kwargs

在Python中的代码中经常会见到这两个词 args 和 kwargs&#xff0c;前面通常还会加上一个或者两个星号。其实这只是编程人员约定的变量名字&#xff0c;args 是 arguments 的缩写&#xff0c;表示位置参数&#xff1b;kwargs 是 keyword arguments 的缩写&#xff0c;表示关键字…

Jmeter的接口自动化测试

在去年实施了一年的三端&#xff08;PC、无线M站、无线APP【Android、IOS】&#xff09;后&#xff0c;今年7月份开始&#xff0c;我们开始进行接口自动化的实施&#xff0c;目前已完成了整个框架的搭建以及接口的持续测试集成。今天做个简单的分享。 在开始自动化投入前&#…

JS加密/解密之逻辑运算符加密进阶篇

前言 ​ 前篇给大家介绍了运算符不为人知的基础知识。他们的各种表达形式&#xff0c;今天我们从这个基础上&#xff0c;继续进一步告诉大家&#xff0c;如何对字符串进行加密处理。还是那句话&#xff0c;技术人不废话&#xff0c;直接晒代码。 示例源代码 // 字符串加密示…

数据可视化报表分享:区域管理驾驶舱

在零售数据分析中&#xff0c;区域管理驾驶舱报表是用来分析企业运营数据&#xff0c;以制定销售策略和提高利润。因此这张报表需要整合大量数据&#xff0c;数据整合、分析、指标计算的工作量极大&#xff0c;在讲究高效率、高度及时性的大数据时代&#xff0c;BI数据可视化分…