Android11 - 添加自定义服务注意事项
添加自定义服务注意事项:
a:(Android 11)快速编译framework.jar ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-xx.ninja framework-minus-apex
b:在framework/base/core目录下添加文件java和aidl文件后,编译时需要先make update-api去更新current.txt文件,然后才能完整编译android,但Android 11 以后谷歌强制开启lint检查,lint检查不过编译会报错,可以让lint检查忽略掉自己的模块在framework/base下的Android.bp忽略掉代码检查,或者可以添加@hide 避免报错:
metalava_framework_docs_args =
...
"--api-lint-ignore-prefix android.app. " + //add_text
"--api-lint-ignore-prefix junit. " +
"--api-lint-ignore-prefix com.xxx.test. " //其中 com.xxx.test是包名的前缀。
c:编译的时候报错:
out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates/classes.jar contains class file com/xxx/test/XXXApiManager.class,
whose package name com.xxx.test is empty or not in the allow list build/make/core/tasks/check_boot_jars/package_allowed_list.txt of packages allowed on the bootclasspath.
怎么解决,看报错去找这个 build/make/core/tasks/check_boot_jars/package_allowed_list.txt
,找到这个文件,添加
###################################################
# framework.jar
javax\.microedition\.khronos\.opengles
...
# Packages used for Android in Chrome OS
org\.chromium\.arc
org\.chromium\.arc\..*
# Packages user for test add
com\.xxx\.test //add
com\.xxx\.test\..* //add
d:在Framework中新增AIDL接口,默认是non-sdk的接口,APK在调用使用时会因Restrictions on non-SDK interfaces功能导致Crash,日志中有如下打印信息:
Accessing hidden method 类完整路径 -> 方法名()V (blacklist, linking, denied)
如何让隐藏方法允许应用层调用?在 /frameworks/base/config/hiddenapi-greylist-packages.txt
添加对应的名单,注意不能有空行!!!
Lcom/xxx/test/XXXApiManager;-><init>(Landroid/content/Context;)V
Lcom/xxx/test/XXXApiManager;->setVolume(I)V
或者直接加包名前缀:
com.xxx.test
e:调用aidl的方法,报错java.lang.SecurityException: Permission Denial: package=android does not belong to uid=10132
,调用端没有权限导致的!!!
如果没办法再调用端更新权限,就修改被调用端的系统服务,采取Handler的方式执行函数:
frameworks\base\core\java\com\xxx\test\
XXXApiManager.java
IXXXApiService.aidl
frameworks\base\services\core\java\com\android\server\xxx\test\
XXXApiService.java
public class XXXApiService extends IXXXApiService.Stub {
...
final H mHandler = new H();
@Override
public void testJJ(int mode) throws RemoteException {
Message msg = Message.obtain();
msg.what = CORE_0;
msg.obj = "linux";
mHandler.sendMessage(msg);
}
final class H extends android.os.Handler {
public static final int CORE_0 = 0;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CORE_0: {
realFunctionName();
break;
}
}
}
}
private void realFunctionName() {
//do something
}
...
}
关于Android系统的UID:
系统进程UID有三种:
- android:sharedUserId="android.uid.system"
- android:sharedUserId="android.uid.shared"
- android:sharedUserId="android.media"
因此在android中PID,和UID都是用来识别应用程序的身份的,但UID是为了不同的程序来使用共享的数据。
对于一个APK来说,如果要使用某个共享UID的话,必须做一下两部步:
1、相同的在Manifest节点中增加android:sharedUserId属性。
2、相同的在Android.mk中增加LOCAL_CERTIFICATE的定义。(既签名相同)
系统源码可以看到一些系统应用就是这样:
系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加 android:sharedUserId=“android.uid.system”,然后在Android.mk中增加 LOCAL_CERTIFICATE := platform。可以参见Settings等
系统中所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加 android:sharedUserId=“android.uid.shared”,然后在Android.mk中增加 LOCAL_CERTIFICATE := shared。可以参见Launcher等
系统中所有使用android.media作为共享UID的APK,都会在manifest节点中增加 android:sharedUserId=“android.media”,然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。
关于签名:
build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用:
1、testkey:普通APK,默认情况下使用。
2、platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
3、shared:该APK需要和home/contacts进程共享数据。
4、media:该APK是media/download系统中的一环。
f:封装自定义服务,提供jar供第三方应用开发者调用
在vendor目录添加zdz目录,创建Android.bp,编译生成jar包!
/vendor/zdz/Android.bp
java_library_static {
name: "zdz-sdk-api",
srcs: ["com/zdz/**/*.java"],
}
/vendor/zdz/com/zdz/api/ApiManager.java
package com.zdz.api;
import android.content.Context;
import com.xxx.test.XXXApiManager;
public class ApiManager {
private static final String TAG = "XXXApiManager";
private final Context mContext;
private XXXApiManager mXXXApiManager;
public ApiManager(Context context) {
mContext = context;
mXXXApiManager = (XXXApiManager) context.getSystemService("xxx_service");
}
public boolean test() {
return mXXXApiManager.test();
}
}
mma vendor/zdz/ 或者 make zdz-sdk-api 生成zdz-sdk-api. jar
Android11.0Frameworks中添加一个自定义系统服务,并提供jar包供应用开发调用_安卓framework自定义manager-CSDN博客
Android原生系统开发如何优雅的提供系统级的API供第三方程序调用?
[Android AIDL系列 1] 手动编译aidl文件,生成Java、C++[android]、C++[ndk]、Rust接口_aidl c++-CSDN博客
android源码中编译jar
在Android系统中实现AIDL接口回调
1.创建 XXXApiManager.java 和 IXXXApiService.aidl
2.创建对应的XXXApiService.java
3.注册服务:frameworks/base/core/java/android/app/SystemServiceRegistry.java
Context.xxx_TEST_SERVICE = "xxx_service"--->不想在Context.java中定义的话,直接用字符串,保证相同就行了
static {
...
registerService("xxx_service", XXXApiManager.class,
new CachedServiceFetcher<XXXApiManager>() {
@Override
public XXXApiManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow("xxx_service");
return new XXXApiManager(ctx, IXXXApiService.Stub.asInterface(b));
}
});
...
}
4.启动服务:frameworks/base/services/java/com/android/server/SystemServer.java,所有的系统服务都在这里初始化
XXXApiService xxxApi = null;//add
private void startOtherServices(@NonNull TimingsTraceAndSlog t){
...
+ traceBeginAndSlog("StartTestService");
+ try {
+ Slog.i(TAG, "add test Service");
+ xxxApi = new XXXApiService(context);
+ ServiceManager.addService("xxx_service", xxxApi);
+ } catch (Throwable e) {
+ reportWtf("starting test Service", e);
+ }
+ traceEnd();
...
}
5.添加编译规则,Android11的framework的Android.bp,默认全部加载,所以不需要去加了!!!
6.添加SELinux权限,其他的参考上面链接,这个这是简单梳理一下流程!!!
最后验证:全编译刷机验证,adb shell service list,查看系统中的服务列表!!!!