链接:
https://blog.csdn.net/weixin_44845266/article/details/121531578
前言:实现过程,App注册Callback,此时Callback注册进RemoteCallbackList中统一管理。
????????例如在App传入x、y,在Framework实现加法运算返回运算结果 z 给App,那么就在ServiceManager.aidl中定义一个void sum(int x, int y)接口,在Callback.aidl中定义print(int z)接口,在实现接口的函数sum的函数体末尾加上执行print(int z),在sum函数中执行完 z=x+y 调用print函数,传入参数z,哪个App需要看到结果哪个App就重写print方法,即可得到回调的加和结果。下列例子中会做一个介绍。
? ? ? ? 建议在AndroidStudio编写程序,然后改好包名粘贴进源码中参与编译,因为有些未知的import导包需要AndroidStudio识别。编译若报错为缺少哪些包,那就import导入哪些包再编译。
一、编写AIDL文件
路径:frameworks/base/core/java/android/app/IDmsServiceManager.aidl
外部调用接口:IDmsServiceManager.aidl
package android.app;
import android.app.IDmsCallback;
interface IDmsServiceManager {
void registerCallback(IDmsCallback callback);
void unregisterCallback(IDmsCallback callback);
void sendMessage(int value);
}
路径:frameworks/base/core/java/android/app/IDmsCallback.aidl
callback:IDmsCallback.aidl
package android.app;
interface IDmsCallback{
void print(int value);
}
目录:frameworks/base/Android.bp
? ??????"core/java/android/app/IDmsCallBack.aidl", ? ? ? ? "core/java/android/app/IDmsServiceManager.aidl",
? ? ? ? 如下所示,将这两行写入Android.bp文件中,在编译的时候会自动生成stub类
java_library {
name: "framework",
srcs: [
// From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
"core/java/**/*.java",
"graphics/java/**/*.java",
"location/java/**/*.java",
"lowpan/java/**/*.java",
..........
"core/java/android/app/IWallpaperManager.aidl",
"core/java/android/app/IWallpaperManagerCallback.aidl",
"core/java/android/app/IDmsCallBack.aidl",
"core/java/android/app/IDmsServiceManager.aidl",
"core/java/android/app/admin/IDeviceAdminService.aidl",
"core/java/android/app/admin/IDevicePolicyManager.aidl",
..........
二、编写Manager类对app层暴露接口
路径:frameworks/base/core/java/android/app/DmsManager.java
DMS管理类,应用层调用的接口:DmsManager.java
package android.app;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
public class DmsManager {
private final Context mContext;
private final IDmsServiceManager mService;
public DmsManager(Context context, IDmsServiceManager service) {
mContext = context;
mService = service;
}
public void register(IDmsallback callback) {
try {
mService.registerCallback(callback);
} catch (RemoteException e) {
Log.w(TAG, "remote exception happen");
e.printStackTrace();
}
}
public void unregister(IDmsCallback callback) {
try {
mService.unregisterCallback(callback);
} catch (RemoteException e) {
Log.w(TAG, "remote exception happen");
e.printStackTrace();
}
}
/**
* Send data to DmsService.
*/
public void sendMessage(int value) {
try {
mService.sendMessage(value);
} catch (RemoteException e) {
Log.w(TAG, "remote exception happen");
e.printStackTrace();
}
}
}
三、接口实现
路径:frameworks/base/services/core/java/com/android/server/DmsService.java
实现IDmsServiceManager.aidl定义的接口:DmsService.java
package com.android.server
import android.app.IDmsServiceManager;
import android.app.IDmsCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import content.Context;
import android.util.Slog;
public class DmsService extends IDmsServiceManager.Stub{
private final static String TAG = "DMS_SERVICE";
private RemoteCallbackList<IDmsCallback> mCallbackList = new RemoteCallbackList<>();
private final Context mContext;
public DmsService (Context context){
mContext = context;
}
@Override
public void sendMessage(int value){
Slog.i(TAG, "" + value);
//注册在列表中的callback数量
int count = mCallbackList.getRegisteredCallbackCount();
if (count > 0) {
final int size = mCallbackList.beginBroadcast();
//遍历列表中的callback,对注册的每个callback执行print方法,客户端重写print方法后可以获得sendMessage执行结果
for (int i = 0; i < size; i++) {
IDmsCallback cb = mCallbackList.getBroadcastItem(i);
try {
if (cb != null) {
cb.print(value);
}
} catch (RemoteException e) {
e.printStackTrace();
Log.d(TAG, "remote exception:" + e.getMessage());
}
}
}
mCallbackList.finishBroadcast();
}
@Override
public void registerCallback(IDmsCallback callback){
mCallbackList.register(callback);
}
@Override
public void unregisterCallback(IDmsCallback callback){
mCallbackList.unregister(callback);
}
}
应用层注册的callback都会传进RemoteCallbackList列表中,调用回调接口时,可以轮询callback列表,对所有注册的callback进行回调。
接口都在该文件中实现,外部调用DmsManager方法是,调用的也是这里实现的方法。
四、注册系统服务
服务的接口已经实现,方法也对外界暴露,现在剩的就是注册成为系统服务和外界如何调用接口了。服务以系统服务进程的子线程的形式存在,Log打印在system_process进程中。
路径:frameworks/base/services/java/com/android/server/SystemServer.java
在该文化中注册成为系统服务,系统服务开启子线程
package com.android.server
private void startOtherServices() {
// 部分代码省略...
// start SystemEventService
try {
//Context.DMS_SERVICE是String类型,是服务名称
ServiceManager.addService(Context.DMS_SERVICE,
new DmsService(mSystemContext));
} catch (Throwable e) {
reportWtf("starting SystemEventService", e);
}
// 部分代码省略...
}
此时文件已经注册到系统服务中,系统开启时会自动开启DMS服务。
五、应用层调用接口
采用的是反射调用的方法,注册Manager文件,即DmsManager.java文件。注册后Manager会存入一个HasMap中,应用调用时通过getSystemService(Context.DMS_SERVICE);经过一系列方法找到对应的系统服务对象。
路径:frameworks/base/core/java/android/app/SystemServiceRegistry.java
package android.app;
static {
// 部分代码省略, 参考其他代码, 注册Manger
registerService(Context.DMS_SERVICE, DmsManager.class,
new CachedServiceFetcher<SystemEventManager>() {
@Override
public SystemEventManager createService(ContextImpl ctx) {
// 获取服务
IBinder b = ServiceManager.getService(Context.DMS_SERVICE);
// 返回DmsManager对象供调用
IDmsServiceManager service = IDmsServiceManager.Stub.asInterface(b);
return new DmsManager(ctx.getOuterContext(), service);
}});
}
六、还有部分权限问题,需要设置SELinux的权限
后面会告知service_contexts.te和service.te修改的位置
service_contexts.te
wifiscanner u:object_r:wifiscanner_service:s0
wifi u:object_r:wifi_service:s0
window u:object_r:window_service:s0
# 部分代码省略...
# dms是系统服务名称,即Context.DMS_SERVICE
# dms_service 是新定义的参数,在下面的service.te文件中type定义为系统服务,这里需要百度一下,我不懂
dms u:object_r:dms_service:s0
* u:object_r:default_android_service:s0
service.te
# 加入刚刚定义好的 dms_service 类型, 表明它是系统服务,大家可以百度查查
type dms_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
配置SELinux的sepolicy文件夹目录结构如下所示:
下面的两个文件按照上面的service_contexts.te和service.te代码段添加
? ? ? ? 1、system/sepolicy/prebuilts/api/26.0/private/service_contexts.te
? ? ? ? 2、system/sepolicy/prebuilts/api/26.0/public/service.te
? ? ? ? 3、api目录下27.0和28.0目录同样的更改
? ? ? ? 4、system/sepolicy/private/service.te
? ? ? ? 5、system/sepolicy/public/service_contexts.te
? ? ? ? 这些文件都更改一下肯定没有问题,但是也许可以只修改28.0目录的文件和4、5对应的文件,可以修改试一下,缺哪个SELinux权限就添加哪个SELinux权限。
七、编译
????????在android目录下执行make_environment.sh脚本导入环境(或者执行
????????????????????????????????????????????????????????????????????????source build/envsetup.sh和lunch 59)
????????make update-api 更新api
????????make -j8八线程编译
八、应用调用接口实现
1、make -j8 后的生成的中间文件classes.jar导入AndroidStudio中的lib目录下
????????目录:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
2、build.gradle文件配置
allprojects {
repositories {
google()
jcenter()
}
//添加如下部分,以便调用方法的时候会优先使用导入的包classes.jar
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xbootclasspath/p:app/libs/classes.jar'
}
}
}
3、MainActivity.java
package com.example.dms;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.app.IDmsCallBack;
import android.content.Context;
import android.os.Bundle;
import android.app.DmsManager;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button send_btn;
private Button register_btn;
private Button unregister_btn;
private String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取Context.DMS_SERVICE对应的系统服务,定义在classes.jar包中,编译的时候找不到,但可以编译通过
DmsManager dms = (DmsManager) getSystemService(Context.DMS_SERVICE);
requestPermissions(new String[]{Manifest.permission.UPDATE_DEVICE_STATS}, 0);
camera_btn = findViewById(R.id.cameraPreview);
register_btn = findViewById(R.id.registerCallback);
unregister_btn = findViewById(R.id.unregisterCallback);
send_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
dms.sendMessage(5);
} catch (Exception e) {
e.printStackTrace();
}
}
});
//注册下面实现的回调接口callBack
register_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
dms.registerCallBack(callBack);
} catch (Exception e) {
e.printStackTrace();
}
}
});
//注销下面实现的回调接口callBack
unregister_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
dms.unregisterCallBack(callBack);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//实现IDmsCallback回调接口定义的回调方法,可以再App看到打印的Log值
private IDmsCallBack.Stub callBack = new IDmsCallBack.Stub() {
@Override
public void print(int value) throws RemoteException {
Log.d(TAG, "" + value);
}
};
}
4、AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.dms">
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="DMS"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DMS">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
layout部分自行编写,就不贴了
此时build完成后,安装App实现调用
学习链接:
|