在Android11中添加了很多新特性,编译脚本也进行了比较大的改动。例如如果一个系统方法添加了@hide
即使使用反射也无法进行函数调用,另外对于public方法如果含有包装类型参数或者返回值时必须添加 @NonNull 不能为空
以及 @Nullable 可为空
进行注解否则会导致 make update-api
失败。另外相对Android7我们在core中添加AIDL后无需再编译脚本中进行添加,因为Android11使用了.java和.aidl进行通配。
新键AIDL文件
frameworks/base/core/java/android/app/IDevInfoManager.aidl
package android.app;
/**
*@hide
*/
interface IDevInfoManager{
String getValue(String name);
int update(String name,String value,int attribute);
}
添加Context常量
frameworks/base/core/java/android/content/Context.java
/**
* add sunniwell
* 用于获取系统的一些数据接口服务
*
*/
public static final String DATA_SERVICE = "data";
创建frameworks/base/services/devinfo
文件夹添加devinfo
模块
添加服务配置文件
frameworks/base/services/devinfo/Android.bp
filegroup {
name: "services.devinfo-sources",
srcs: ["java/**/*.java"],
path: "java",
visibility: ["//frameworks/base/services"],
}
java_library_static {
name: "services.devinfo",
defaults: ["services_defaults"],
srcs: [":services.devinfo-sources"],
libs: ["services.core"],
}
请留意services.devinfo-sources
和services.devinfo
两个参数。
Java服务实现
frameworks/base/services/devinfo/java/com/android/server/devinfo/DevInfoManagerService.java
package com.android.server.devinfo;
import android.app.DevInfoManager;
import android.app.IDevInfoManager;
import android.content.Context;
public class DevInfoManagerService extends IDevInfoManager.Stub {
private mValue;
public DevInfoManagerService(Context context) {
this.mContext = context;
loadDefaultDevinfo();
}
private void loadDefaultDevinfo() {
mValue="hello"
}
@Override
public String getValue(String name) throws RemoteException {
return mValue;
}
@Override
public int update(String name, String value, int attribute)
throws RemoteException, SecurityException {
int ret = 0;
mValue = value;
return ret;
}
}
将服务添加至编译脚本
frameworks/base/services/Android.bp
filegroup {
name: "services-all-sources",
srcs: [
.....
":services.devinfo-sources",
....
],
visibility: ["//visibility:private"],
}
...
java_library {
name: "services",
installable: true,
dex_preopt: {
app_image: true,
profile: "art-profile",
},
srcs: [":services-main-sources"],
// The convention is to name each service module 'services.$(module_name)'
static_libs: [
...
"services.devinfo",
...
],
libs: [
"android.hidl.manager-V1.0-java",
"framework-tethering.stubs.module_lib",
],
// Uncomment to enable output of certain warnings (deprecated, unchecked)
//javacflags: ["-Xlint"],
}
请留意:services.devinfo-sources
和services.devinfo
两个参数。
将服务添加至系统
frameworks/base/services/java/com/android/server/SystemServer.java
import com.android.server.devinfo.DevInfoManagerService;
....
t.traceBegin("StartDevInfoManagerService");
try {
ServiceManager.addService(Context.DATA_SERVICE, new DevInfoManagerService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting System DevInfoManager Service ", e);
}
t.traceEnd();
...
注意由于该服务属于自定义请将其添加子otherSerice方法比较合理。
注册服务使得可以通过 DevInfoManager mDevInfoManager = (DevInfoManager) mContext.getSystemService(Context.DATA_SERVICE);
获取到服务。
frameworks/base/core/java/android/app/SystemServiceRegistry.java
import android.app.DevInfoManager;
import android.app.IDevInfoManager;
....
registerService(Context.DATA_SERVICE,DevInfoManager.class,
new CachedServiceFetcher<DevInfoManager>() {
@Override
public DevInfoManager createService(ContextImpl ctx) throws ServiceNotFoundException{
IBinder b = ServiceManager.getServiceOrThrow(Context.DATA_SERVICE);
IDevInfoManager service = IDevInfoManager.Stub.asInterface(b);
if (service == null) {
return null;
}
return new DevInfoManager(ctx.getOuterContext(), service);
}
}
);
...
添加DevInfoManager接口
frameworks/base/core/java/android/app/DevInfoManager.java
package android.app;
import android.app.IDevInfoManager;
import android.content.Context;
import android.os.RemoteException;
import android.util.Slog;
import android.annotation.NonNull;
import android.annotation.Nullable;
public class DevInfoManager {
private Context mContext;
private IDevInfoManager mService;
/** @hide */
public DevInfoManager(Context context, IDevInfoManager service) {
mContext = context;
mService = service;
}
/**
* 获取参数
*
*/
@Nullable
public String getValue(@NonNull String paramString) {
String value = null;
if (mService != null && paramString != null) {
try {
value = mService.getValue(paramString);
} catch (RemoteException e) {
Slog.e("SystemStatus", "RemoteException " + e);
}
}
return value;
}
/**
* update DevInfo
*
*/
public int update(@NonNull String paramString1,@NonNull String paramString2, int paramInt) {
int ret = -1;
if (mService != null&& paramString1 != null && paramString2 != null) {
try {
ret = mService.update(paramString1, paramString2, paramInt);
} catch (RemoteException e) {
Slog.e("SystemStatus", "RemoteException " + e);
}
}
return ret;
}
}
请留意文章开头提到的@NonNull 不能为空
以及 @Nullable 可为空
否则make update-api
会出现以下错误:
frameworks/base/core/java/android/app/DevInfoManager.java:xx: error: Missing nullability on method `getValue` return [MissingNullability]
frameworks/base/core/java/android/app/DevInfoManager.java:xx: error: Missing nullability on parameter `paramString` in method `getValue` [MissingNullability]
frameworks/base/core/java/android/app/DevInfoManager.java:xx: error: Missing nullability on parameter `paramString1` in method `update` [MissingNullability]
frameworks/base/core/java/android/app/DevInfoManager.java:xx: error: Missing nullability on parameter `paramString2` in method `update` [MissingNullability]
4 new API lint issues were found.
See tools/metalava/API-LINT.md for how to handle these.
另外构造方法也需要添加@hide
进行保护。
进行上述修改后在源码根目录执行make update-api
更新api文件后,进行编译即可。
app通过以下方式进行调用
DevInfoManager mDevInfoManager = (DevInfoManager) getSystemService(Context.DATA_SERVICE);
mDevInfoManager.xxxxx();