最近在整理Usb 的默认MTP模式方案整理,涉及到app ->system server-> hal 流程,因为他们属于不同的进程,中间涉及到跨进程的调用,既然后面要写USB 流程,那么就用adb 的例子看看实际的调用流程.
app 如何调用System server 的服务?
直接看例子,两种方式
try{
//方式一
IBinder b = ServiceManager.getService(Context.ADB_SERVICE);
IAdbManager service = IAdbManager.Stub.asInterface(b);
Log.d("xss", "IBinder = "+service.toString());
Log.d("xss", "IBinder = "+service.isAdbWifiQrSupported());
Log.d("xss", "IBinder = "+service.getPairedDevices().toString());
//方式二
AdbManager adbManager = (AdbManager)getActivity().getSystemService(Context.ADB_SERVICE);
Log.d("xss", "service = "+adbManager.toString());
Log.d("xss", "service = "+adbManager.isAdbWifiQrSupported());
//Log.d("xss", "IBinder = "+adbManager.getPairedDevices().toString());
}catch(Exception e){
Log.d("xss", "Exception = "+e.toString());
}
方式一:
System app 可以调用,通过代理的方式调用,为什么普通app 不能这么调用呢?
点进去看看就知道了,hide api ,所以普通的应用调用不了啦.
/** @hide */
public final class ServiceManager {
}
方式二:
普通app 调用方式,写应用层面的比较常见这种方式,当然系统app也可以这么用.
两种方式有啥区别?
这个涉及到AIDL 的调用流程,因为涉及到两个进程(app ,system server),简单来说,方式二是暴露给app 进程的接口函数,最终调用的是方式一里面的函数,所以方式一的函数数量>=方式二的函数数量,明白?
画图解释下,我们先不管这个Service 哪来的,我们先对比下两种方式函数的差异.
可以看到 system server 通过方式一代理的方式直接调用 Service 中的函数,这些函数中有不想暴露给app 调用的,所有通过UsbManager 封装了一层,暴露上app,所以上面注释掉的方法,方式二调用不了,就是这个道理.
//Log.d("xss", "IBinder = "+adbManager.getPairedDevices().toString());
Service 哪里来的?
这个获取的是服务对象,那这个服务是何时启动的呢?
UsbService
Lifecycle 可以理解为运行在系统进程的服务,启动的时候发布服务
**
* UsbService manages all USB related state, including both host and device support.
* Host related events and calls are delegated to UsbHostManager, and device related
* support is delegated to UsbDeviceManager.
*/
public class UsbService extends IUsbManager.Stub {
public static class Lifecycle extends SystemService {
private UsbService mUsbService;
//.......
@Override
public void onStart() {
SystemServerInitThreadPool.submit(() -> {
mUsbService = new UsbService(getContext());
publishBinderService(Context.USB_SERVICE, mUsbService);
mOnStartFinished.complete(null);
}, "UsbService$Lifecycle#onStart");
}
}
/**
* Publish the service so it is accessible to other services and apps.
*
* @param name the name of the new service
* @param service the service object
*/
protected final void publishBinderService(@NonNull String name, @NonNull IBinder service) {
publishBinderService(name, service, false);
}
/**
* Get a binder service by its name.
*
* @hide
*/
protected final IBinder getBinderService(String name) {
return ServiceManager.getService(name);
}
/**
* Publish the service so it is only accessible to the system process.
*
* @hide
*/
protected final <T> void publishLocalService(Class<T> type, T service) {
LocalServices.addService(type, service);
}
/**
* Get a local service by interface.
*
* @hide
*/
protected final <T> T getLocalService(Class<T> type) {
return LocalServices.getService(type);
}
private SystemServiceManager getManager() {
return LocalServices.getService(SystemServiceManager.class);
}
}
打开SystemService 发现服务类型有两种:
BinderService 提供其他服务调用,和app (系统app ,三方app)
LocalService 仅仅是系统进程可以使用,即system server 内部调用.
如何添加自己的Service 给app 调用?
未完待续