美文网首页
SystemService 相关介绍

SystemService 相关介绍

作者: fsdffdaga | 来源:发表于2021-10-31 19:23 被阅读0次
    • 获取系统的具体 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 是怎么注册为系统服务的
    1. 在 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();
    
    1. 在对应的 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 搜索

    捕获.PNG
    • app 端如何调用相应 Service 的功能
    1. 获取 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 中了
        }});
    

    相关文章

      网友评论

          本文标题:SystemService 相关介绍

          本文链接:https://www.haomeiwen.com/subject/kuioaltx.html