文章目录
1. 定义接口
定义aidl接口
//frameworks/base/core/java/android/hello/IHelloService.aidl
package android.hello;
interface IHelloService {
void hello(String name);
}
frameworks/base/Android.bp framework-defaults 模块中添加我们刚刚加的 aidl 文件 "core/java/android/pure/IHelloService.aidl"
mm成功,会有hello目录IHelloService.java
2 实现接口
//frameworks/base/services/core/java/com/android/server
package com.android.server;
import android.hello.IHelloService;
import android.util.Log;
public class HelloService extends IHelloService.Stub {
private final String TAG = "HelloService";
public HelloService() {
Log.d(TAG, "create hello service");
}
@Override
public void hello(String name) {
Log.d(TAG, "hello " + name);
}
}
3 添加到ServiceManager
// frameworks/base/services/java/com/android/server/SystemServer.java startOtherServices
// add hello service
traceBeginAndSlog("HelloService");
ServiceManager.addService("HelloService", new HelloService());
traceEnd();
编译运行,系统起不来,错误log
12-20 23:46:47.308 1526 1526 E SELinux : avc: denied { add } for service=HelloService pid=3521 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
没有添加SELinux规则
4 selinux规则
android 10的selinux在sysem/sepolicy,每个版本不尽相同。参考network_time_update_service
cd system/sepolicy
grep -nr network_time_update_service
找到所有service.te 和service_context,参考network_time_update_service加上HelloService配置
service_context 加上
HelloService u:object_r:HelloService:s0
service.te加上
type HelloService, system_server_service, service_manager_type;
5 验证
整编后 service list 发现
HelloService:[andorid.hello.IHelloService]
6 客户端使用
6.1 系统源码中使用
Android.bp
android_app {
src: ["src/**/*.java"],
resource_dirs: ["res"],
certificate: "platform",
platform_apis: true,
}
platform_apis 要设置为true,不然没法调用系统服务
public class MainActivity extends Activity {
private static final String TAG = "PureSettings";
private IHelloService service = null;
private Button button;
private void test() {
Log.d(TAG, "test");
try {
service.hello("hello");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
service = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
}
}
将模块添加到系统
pure.mk
PRODUCT_PACKAGES += PureSettings
编译运行,闪退,错误日志
E SELinux : avc: denied { find } for service=HelloService pid=4266 uid=10102 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:HelloService:s0 tclass=service_manager permissive=0
看起来还是有selinux权限需要添加,具体分析如下
- 缺少什么权限 {find}
- 谁缺少权限 scontext=u:r:platform_app:s0:c512,c768
- 对哪个文件缺少权限: tcontext=u:object_r:HelloService:s0
- 什么类型的文件: tclass=service_manager
- 完整的意思: platform_app 缺少 service_manager 类型的 HelloService 的 find 权限。
- 在 platform_app.te 中添加 HelloService 的 find 权限即可
alllo platform_app HelloService:service_manager find;
,找到所有private/platform_app.te 都加上,
重新编译运行就正常。
6.2 非系统源码使用
实际项目中,非系统源码使用系统服务,需要封装一层接口出来。apk –> HelloApi –> HelloService
我们按以下目录结构创建 HelloApi 模块:
qiushao@qiushao-pc:~/source/android-10/device/qiushao/pure/models$ tree HelloApi/
HelloApi/
├── Android.bp
└── java
└── com
└── pure
└── api
└── HelloManager.java
4 directories, 2 files
qiushao@qiushao-pc:~/source/android-10/device/qiushao/pure/models$
Android.bp
java_library {
name: "com.pure.api",
installable: true,
srcs: [
"java/**/*.java", //文件列表
],
}
//device/qiushao/pure/models
import android.os.RemoteException;
import android.os.ServiceManager;
import android.pure.IHelloService;
public class HelloManager {
private static HelloManager mInstance = null;
public static HelloManager getInstance() {
if (null == mInstance) {
mInstance = new HelloManager();
}
return mInstance;
}
private IHelloService mService = null;
private HelloManager() {
mService = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
}
public void sayHello(String name) {
try {
mService.hello(name);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
HelloApi 目录 mm 编译模块,得到 out/target/common/obj/JAVA_LIBRARIES/com.pure.api_intermediates/classes.jar 文件
生成class.har, 复制到as创建的项目中,add as library, 然后我们就可以在 apk 的代码中使用 com.pure.api.jar 的接口了:
...
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HelloManager.getInstance().sayHello("qiushao");
}
}
编译运行,又有错误
E SELinux : avc: denied { find } for service=HelloService pid=4266 uid=10102 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:HelloService:s0 tclass=service_manager permissive=0
alllow untrusted_app HelloService:service_manager find;
7 添加回调
//frameworks/base/core/java/android/hello
package android.pure;
interface ICallback {
void onMessage(in String message);
}
frameworks/base/Android.bp framework-defaults 模块中添加aidl文件
"core/java/android/hello/ICallback.aidl",
,会生成ICallback.java文件
8 添加注册回调
修改 IHelloService.aidl
package android.hello;
import android.pure.ICallback;
interface IHelloService {
void hello(in String name);
void registerCallback(in int pid, in ICallback callback);
void unregisterCallback(in int pid);
}
HelloService.java 修改如下:
package com.android.server;
import android.os.RemoteException;
import android.pure.IHelloService;
import android.pure.ICallback;
import android.util.Log;
import java.util.HashMap;
import java.util.Map;
public class HelloService extends IHelloService.Stub {
private final String TAG = "HelloService";
private Map<Integer, ICallback> mClients;
public HelloService() {
Log.d(TAG, "create hello service");
mClients = new HashMap<>();
}
@Override
public void hello(String name) {
Log.d(TAG, "hello " + name);
try {
for (ICallback callback : mClients.values()) {
callback.onMessage("message from service");
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void registerCallback(int pid, ICallback callback) {
mClients.put(pid, callback);
Log.d(TAG, "registerCallback client's size = " + mClients.size());
}
@Override
public void unregisterCallback(int pid) {
mClients.remove(pid);
Log.d(TAG, "unregisterCallback client's size = " + mClients.size());
}
}
9 注册回调接口
//MainActivity
public class MainActivity extends Activity {
private static final String TAG = "PureSettings";
private IHelloService service = null;
private Button button;
private ICallback callback = new ICallback.Stub() {
@Override
public void onMessage(String message) throws RemoteException {
Log.d(TAG, "onMessage:" + message);
}
};
private void test() {
Log.d(TAG, "test");
try {
service.hello("qiushao");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
service = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
}
@Override
protected void onResume() {
super.onResume();
try {
service.registerCallback(android.os.Process.myPid(), callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onStop() {
super.onStop();
try {
service.unregisterCallback(android.os.Process.myPid());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
编译运行成功