Framework 层添加SystemService和Manager的超详细步骤

Framework 层添加SystemService和Manager的超详细步骤

本文适用于Android 12中增加系统服务。

目录

1.总体步骤

2、详细步骤

2.1 创建AIDL文件

2.2 报错修改

2.2.1 AIDL文件自动生成的Java文件报错

2.2.2 AIDL文件Observer/Callback/Listener命名报错修改

2.2.3 注册方法报错

2.2.4 避免使用枚举类enum

2.2.5 Callback如何让APP访问到

3. Context中定义service name

4. 编写SystemService

5. 在SystemServer类中注册新增的系统服务

6. 编写系统Manager类

7. 注册系统Manager类

8. 应用调用


1.总体步骤


2、详细步骤

2.1 创建AIDL文件

在framework/base/core/java/android/app下创建AIDL文件,如果业务比较复杂,可以创建模块文件夹。代码示例如下:

framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl

//framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl
package android.app.devicemanager;
 
import android.app.devicemanager.DeviceEntity;
import android.app.devicemanager.IDeviceObserver;
 
interface IDeviceManager {
    int bindDivice(int deviceId);
    DeviceEntity getDeviceEntity(int deviceId);
    void registerDeviceObserver(in IDeviceObserver observer);
    void unregisterDeviceObserver(in IDeviceObserver observer);
}

framework/base/core/java/android/app/devicemanager/IDiviceObserver.aidl

//framework/base/core/java/android/app/devicemanager/IDeviceObserver.aidl
package android.app.devicemanager;
 
import android.app.devicemanager.DeviceEntity;
oneway interface IDiviceObserver{
    void onBindChanged(int state, int deviceId);
    void onStateChanged(int state, int deviceId);
}

framework/base/core/java/android/app/devicemanager/DeviceEntity.aidl

package android.app.devicemanager;
 
parcelable DeviceEntity;

2.2 报错修改

上述写法会报非常多的错,请参考Android 12  API规范:请参考 https://www.cnblogs.com/wanghongzhu/p/14729469.html 。

针对上述代码所犯的错误,也就是大家在Android 12版本中使用make -j32 framework-minus-apex编译framework层的报错修改。

2.2.1 AIDL文件自动生成的Java文件报错

这是因为AIDL自动生成的Java文件不满足Android 12 framework API的规范:framework层不能直接暴露原生AIDL文件。

修改的方式是在aidl文件上添加@hide,如下所示,这样就可以解决所有AIDL自动生成的文件。(这是扒遍国内全网都没在找到,在Google中才找到的根本解决办法)

//framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl
package android.app.devicemanager;
 
import android.app.devicemanager.DeviceEntity;
import android.app.devicemanager.IDeviceObserver;
 
/** @hide */
interface IDeviceManager {
    int bindDivice(int deviceId);
    DeviceEntity getDeviceEntity(int deviceId);
    void registerDeviceObserver(in IDeviceObserver observer);
    void unregisterDeviceObserver(in IDeviceObserver observer);
}

out/srcjars/android/app/devicemanager/IDiviceObserver.java:60: error: Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) [RethrowRemoteException]

out/srcjars/android/app/devicemanager/IDiviceObserver.java:70: error: Missing nullability on method `asBinder` return [MissingNullability]
out/srcjars/android/app/devicemanager/IDiviceObserver.java:75: error: Raw AIDL interfaces must not be exposed: Stub extends Binder [RawAidl]

2.2.2 AIDL文件Observer/Callback/Listener命名报错修改

Observer命名报错,Android Lint 工具对callback和listener有严格的校验,不建议使用Observer作为回调,要用callback或者listener。

  • 当只有一个回调方法且永远不会有其他回调方法时使用Listener,且注册监听和解注册监听的方法必须是add/remove开头,否则Android Lint编译不过。
  • 当有多个回调方法时,或者有关联的常量时,应该使用Callback。Callback类可以是一个interface或者abstract class。添加callback和去掉callback应该使用register和unregister开头的方法。
  • callback中的方法应该以on-开头。

请中招的小伙伴自行修改。

2.2.3 注册方法报错

Registration methods should have overload that accepts delivery Executor: `registerDeviceCallback` [ExecutorRegistration]

是不是一脸懵,看不明白啥意思,以前很早的framework层的manager,没啥参考价值,推荐参考新的manager和API规范,因为现有的注册回调的方法必须是两个参数,其中一个必须为Executor,如下所示。

public void registerFooCallback( @NonNull @CallbackExecutor Executor executor,
                                 @NonNull FooCallback callback)
//unregister方法不需要添加Executor
public void unregisterFooCallback(@NonNull FooCallback callback) {}
 2.2.4 避免使用枚举类enum

在Framework层使用enum会报错:Enums are discouraged in Android APIs [Enum],因此一般都用@intDef代替,使用新的注解表示。

2.2.5 Callback如何让APP访问到

前边2.2.1 AIDL文件自动生成的Java文件报错,为了解决需要添加@hide,但是添加该注解后,Apps就访问不到该callback,如何实现Binder通信呢?

解决办法:

  • 创建一个public abstract class DeviceCallback,对apps暴露该类,让Apps添加注册的时候创建该类的实例。
  • 然后再framework层manager中实现DeviceManager类与IDeviceCallback.aidl的一一映射关系。

这样做的好处:

  • 即能避免暴露原生的AIDL文件,而且Apps不用实现ICallback.aidl中所有的方法。

//创建暴露给Apps的抽象类 

//framework/base/core/java/android/app/devicemanager/DeviceCallback.java
package android.app.devicemanager;
 
public abstract class DiviceCallback {
    void onBindChanged(int state, int deviceId);
    void onStateChanged(int state, int deviceId);
}

//Manager中对应的映射关系 

//framework/base/core/java/android/app/devicemanager/DeviceManager.java
package android.app.devicemanager;
 
import android.app.devicemanager.IDeiceCallback;
import android.app.devicemanager.DevoceCallback;
import java.util.concurrent.Executor;
 
public class DeviceManager {
 
    private ArrayMap<DeviceCallback, DeviceCallbackEntry> mCallbackMap = new ArrayMap<>();
 
    //AIDL ICallback真正实现的类
    private static final class DeviceCallbackEntry extends IDeviceCallback.Stub {
        final DeviceCallback mCallback;
        final Executor mExecutor;
        
        DeviceCallbackEntry( DeviceCallback callback, Executor executor) {
            mCallback = callback;
            mExecutor = executor;
        }
 
        //当Binder server端IDeviceCallback的onBindChanged回调时,会调用Apps端注册的
        // DeviceCallback类对应的方法,此时就完成了ICallback到Callback抽象类的映射。
        public void onBindChanged(int state, int deviceId) {
            mExecutor.executor(() -> mCallback.onBindChanged(state, deviceId));
        }
        ...
    }
 
    public void registerDeviceCallback(@Nullable Executor executor,
                                       @NonNull DeviceCallback callback) {
        if(callback == null || mCallbackMap.containsKey(calback)) {
            return;
        }
 
        DeviceCallbackEntry entry = new DeviceCallbackEntry(callback, executor);
        mCallbackMap.put(callback, entry);
        
        final IDeviceManager service = getService();
        try {
            //注意:此处调用的系统服务对应的注册方法中参数是ICallback的实现类,即entry,
            //而不是Apps直接注册的抽象类
            service.registerDeviceCallback(entry);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

3. Context中定义service name

在frameworks/base/core/java/android/content/Context.java中增加一句

public static final String DEVICE_MANAGER_SERVICE = "device_manager";

4. 编写SystemService

在framework/base/services/core/java/com/android/service/下创建系统服务,如果业务比较复杂,可以创建模块文件夹。

framework/base/services/core/java/com/android/service/devicemanage/DeviceManagerService.java

  • extends IDeviceManager.Stub,重写该AILD文件中方法。该AIDL文件是SystemService与系统manager进行IPC的桥梁。
  • 定义静态内部类Lifecycle,extends SystemService,重写onStart()方法,把DeviceManagerService发布到ServiceManger服务中。
t.traceBegin("StartLocationManagerService");
mSystemServiceManager.startService(DeviceManagerService.Lifecycle.class);
t.traceEnd();

5. 在SystemServer类中注册新增的系统服务

在frameworks/base/services/java/com/android/server/SystemServer.java的startOtherServices()中添加以下代码

t.traceBegin("StartLocationManagerService");
mSystemServiceManager.startService(DeviceManagerService.Lifecycle.class);
t.traceEnd();

6. 编写系统Manager类

在framework/base/core/java/android/app/devicemanager下创建DeviceManager类

  • 在DeviceManager类上加注解@SystemService(),参数是第2步中Context中定义service name。注意该参数与DeviceManagerService中的静态内部类的Lifecycle的onStart()方法中publishBinderService(Context.DEVICE_MANAGER_SERVICE, mService)一致。
  • 实现getService()方法,返回IDeviceManager的单例;
  • 利用Singleton工具类通过Binder获取DeviceManagerService的单例;
  • 对外提供接口,内部实现调用service对应的实现接口。
package android.app.devicemanager;
 
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
 
@SystemService(Context.DEVICE_MANAGER_SERVICE)
public class DeviceManager {
    private mContext mContext;
    private DeviceManager(Context context) {
        this.mContext = context;
    }
 
    public static IDeviceManager getService() {
        return IDeviceManagerSingleton.get();
    }
 
    public static final Singleton<IDeviceManager> IDeviceManagerSingleton =
            () -> {
                final IBinder binder = ServiceManager.getService(Context.DEVICE_MANAGER_SERVICE);
                return IDeviceManager.Stub.asInterface(binder);
            };
 
    public int bindDivice(int deviceId) {
        final IDeviceManager service = getService();
        try {
            return service.bindDivice(deviceId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
 
}

7. 注册系统Manager类

在framework/base/core/java/android/app/SystemServiceRegistry.java类的j静态代码块static{}中增加以下代码

registerService(Context.DEVICE_MANAGER_SERVICE, DeviceManager.class, 
    new CachedServiceFetcher<DeviceManager>() {
        @Override
        public DeviceManager createService(ContextImpl ctx) {
            return new DeviceManager(ctx.getOuterContext());
        }});

8. 应用调用

DeviceManager mDeviceManager = (DeviceManager) mContext.getSystemService(Context.DEVICE_MANAGER_SERVICE);
int deviceId = 1;
mDeviceManager.bindDevice(deviceId);

以上是在framework层添加一个完整SystemService和manager的过程。

在Android 12中添加一个系统service,简直到处踩雷,阅读了整个API规范,各种追踪源码,才把framework层的编译通过,如果你喜欢请收藏或者点赞哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值