-
获取系统的具体 Service 可以调用,如getSystemService(Context.VIBRATOR_SERVICE)。 这里最终返回的基本都是 XxxManager, 如 ActivityManager, ActivityTaskManager, NotificationManager, WindowManager 等。
但是也不一定都是 XxxManager, 这个仅仅是命名上的差异而已,如 String VIBRATOR_SERVICE = "vibrator" 返回的就是 Vibrator (实际为实现类 SystemVibrator)。
总之返回的都是 Binder 的 Client 对象,有时候统称为 XxxManager. -
Context # abstract Object getSystemService() 原理
他的实现实在
- VibratorService 是怎么注册为系统服务的
- 在 SystemServer 中将 Service 添加到 ServiceManager 中:
VibratorService vibrator = null;
t.traceBegin("StartVibratorService");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
t.traceEnd();
t.traceBegin("MakeVibratorServiceReady");
try {
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("making Vibrator Service ready", e);
}
t.traceEnd();
- 在对应的 XxxManager (此处为 VibratorService.java) 中获取服务器端的代理
private final IVibratorService mService;
mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
// 或下面,asInterface 的参数实际上市 IBinder 类型
// 有些地方还是采用的 ServiceManager.getServiceOrThrow 形式
// IBinder b = ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE);
IBinder b = ServiceManager.getService("vibrator");
mService = IVibratorService.Stub.asInterface(b);
一般在 XxxManager 的构造中获取的代理,fw 中相关的引用命名都为 mService, 可以通过正则 "mService = .+Stub" 搜索。或者 ServiceManager.getService 搜索
- app 端如何调用相应 Service 的功能
- 获取 XxxxManager(下文讲如何获取这个), 调用它的方法。因为在 XxxxManager 中已经有 mService 存在了,他就可以调用服务端的方法(这个方法就是aidl中声明的)。如:此处的 XxxxManager 为 Vibrator --> SystemVibrator
@Override
public boolean hasVibrator() {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
return false;
}
try {
return mService.hasVibrator(); // 此处 binder 跨进程调用服务端的方法
} catch (RemoteException e) {
}
return false;
}
- app 端如何获取 XxxManager 的
Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
从上看出是通过 Context(实际是 ContextImpl ) 的 getSystemService(Context.VIBRATOR_SERVICE) 获取
ContextImol.java
@Override
public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
// We may override this API from outer context.
final boolean isUiContext = isUiContext() || isOuterUiContext();
// Check incorrect Context usage.
if (isUiComponent(name) && !isUiContext) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
final String message = "Visual services, such as WindowManager, WallpaperService "
+ "or LayoutInflater should be accessed from Activity or other visual "
+ "Context. Use an Activity or a Context created with "
+ "Context#createWindowContext(int, Bundle), which are adjusted to "
+ "the configuration and visual bounds of an area on screen.";
final Exception exception = new IllegalAccessException(errorMessage);
StrictMode.onIncorrectContextUsed(message, exception);
Log.e(TAG, errorMessage + " " + message, exception);
}
}
return SystemServiceRegistry.getSystemService(this, name); // 核心,具体实现
}
SystemServiceRegistry
可以看到是根据 Service 的 name, 通一个 map: SYSTEM_SERVICE_FETCHERS 中获取到 ServiceFetcher,并且在根据 context 获取到真正的 XxxManager (ret).
/**
* Gets a system service from a given context.
* @hide
*/
public static Object getSystemService(ContextImpl ctx, String name) {
...
final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
final Object ret = fetcher.getService(ctx);
...
return ret;
}
再追溯源,看这个 map 是如何保存的:
private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new ArrayMap<String, ServiceFetcher<?>>();
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
private static <T> void registerService(@NonNull String serviceName,
@NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher); // 此处 put 的
SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}
继续追 registerService 的调用,参数中传递了 Service 的 name:
static {
registerService(Context.VIBRATOR_SERVICE, Vibrator.class,
new CachedServiceFetcher<Vibrator>() {
@Override
public Vibrator createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});A
}
同时在 SystemServiceRegistry 的 static 块中,发现了大量的 registerService,好多系统服务都通通过 registerService 在回调 createService 中 通过 new 对应的 XxxxManager 来获取客户端调用的 Manager 的,再如:
registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
new CachedServiceFetcher<KeyguardManager>() {
@Override
public KeyguardManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new KeyguardManager(ctx);
}});
提下其他大量的 registerService:
360软件小助手截图20211031192500.jpg
另外,为何有些 XxxManager 中没有 Service.Stub.asInterface
大多数 XxxxManager 可能如上面这样写,但是有些没有,但是并不影响其通过 Binder 引用调用 Service 的方法。
如:
registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
new CachedServiceFetcher<AccountManager>() {
@Override
public AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE);
IAccountManager service = IAccountManager.Stub.asInterface(b);
return new AccountManager(ctx, service); // 已经提前获取了,直接传递到了 AccountManager 中了
}});
网友评论