getSystemService追根溯源

getSystemService追根溯源

在安卓开发过程中,我们经常会用到getSystemService方法来获取各种系统服务,比如下面几种常见的获取服务代码:

NetworkInfo networkInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE)

简单说一下系统服务,系统服务对于第三方app来说简直是神一样的存在,它们拥有者各种各样的系统权限和资源,第三方app很多功能都得指望它们来做事。其实这些系统服务都是运行在一个进程之中,这个进程叫做system_server进程,每个服务都运行在各自的线程之中,比如ActivityManagerService、PackageManagerService等。我们下面来逆向分析一下我们是怎么得到系统服务对象或者是代理对象的。

1、先来看一下Activity.getSystemService的源码(我的源码版本是android 7.1.1):

@Override
public Object getSystemService(@ServiceName @NonNull String name) {
    if (getBaseContext() == null) {
        throw new IllegalStateException(
                "System services not available to Activities before onCreate()");
    }

    if (WINDOW_SERVICE.equals(name)) {
        return mWindowManager;
    } else if (SEARCH_SERVICE.equals(name)) {
        ensureSearchManager();
        return mSearchManager;
    }
    return super.getSystemService(name);
}

上面的代码中,会先根据服务名称判断是否为WINDOW_SERVICE或者SEARCH_SERVICE,是这两个的话,因为Activity对象里面已经持有这两个服务的代理对象了,所以可以直接返回,如果不是这两个服务,则调用父类的getSystemService方法,其父类ContextThemeWrapper。

2、ContextThemeWrapper.getSystemService方法的源码:

@Override
public Object getSystemService(String name) {
    if (LAYOUT_INFLATER_SERVICE.equals(name)) {
        if (mInflater == null) {
            mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
        }
        return mInflater;
    }
    return getBaseContext().getSystemService(name);
}
 

上面代码中,会判断是否是获取LAYOUT_INFLATER_SERVICE服务,如果是,则返回其持有的服务对象,如果不是,则调用getBaseContext().getSystemService(name)方法。我们先看getBaseContext()返回值是什么:

/**
 * @return the base context as set by the constructor or setBaseContext
 */
public Context getBaseContext() {
    return mBase;
}
public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
        //此处省略n行代码

}
 

通过代码调试可知,mBase的类型其实是ContextImpl,我们来看一下ContextImpl.getSystemService的源码。此处附一张Context的继承关系类图。

3、ContextImpl.getSystemService的源码:

@Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

4、SystemServiceRegistry.getSystemService的源码:

/**
     * Gets a system service from a given context.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

我们先来看一下ServiceFetcher是何方神圣,它其实是一个接口,其定义如下:

/**
     * Gets a system service from a given context.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

再来看一下SYSTEM_SERVICE_FETCHERS的定义:

private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();

可知SYSTEM_SERVICE_FETCHERS是一个HashMap对象,其存放的是<String,ServiceFetcher>键值对,String表示服务名字,ServiceFetcher持有服务对象或者是代理对象。那么接下来我们要研究的就是SYSTEM_SERVICE_FETCHERS是什么put数据的。SYSTEM_SERVICE_FETCHERS存放数据是在registerService方法里面:

/**
     * Statically registers a system service with the context.
     * This method must be called during static initialization only.
     */
    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }

而registerService方法的调用是在SystemServiceRegistry类的静态代码块里面:

static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});

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

        registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                new CachedServiceFetcher<AccountManager>() {
            @Override
            public AccountManager createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);
                IAccountManager service = IAccountManager.Stub.asInterface(b);
                return new AccountManager(ctx, service);
            }});
      //目测了一下,这里大概注册了七十多个服务

}

在上面的代码中,我们可以看到返回服务对象的两种方法,一种是通过new或者getInstance直接返回服务对象,比如ACCESIBILITY_SERVICE;而另一种是通过IBinder返回服务的代理对象,比如ACCOUNT_SERVICE。第一种的服务我们就不再跟踪了,其产生机制到这里已经明白了。我们要研究的是第二种服务代理的对象,因为通过代码可以看出这种服务的对象本身不是在这里创建的,是通过ServiceManager.getService方法获取的,所以我们继续看下ServiceManager.getService方法。

5、ServiceManager.getService的源码:

/**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

从上面代码可知,IBinder对象有两种途径获取,一种是从sCache里面获取,另一种是通过getIServiceManager().getService()方法获取。我们先看第一种从sChache里面获取,sChache是一个HashMap对象,我们来看其存储数据的过程,首先是ServiceManager.initServiceCache方法:

/**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     * 
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache(Map<String, IBinder> cache) {
        if (sCache.size() != 0) {
            throw new IllegalStateException("setServiceCache may only be called once");
        }
        sCache.putAll(cache);
    }

我们再来看看该方法在哪被调用的,该方法是在ActivityThread.bindApplication方法里面调用的,

public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);

            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            sendMessage(H.BIND_APPLICATION, data);
        }

而ActivityThread.bindApplication是在ApplicationThreadNative的onTransact里面调用的

case BIND_APPLICATION_TRANSACTION:
        {
            data.enforceInterface(IApplicationThread.descriptor);
            String packageName = data.readString();
            ApplicationInfo info =
                ApplicationInfo.CREATOR.createFromParcel(data);
            List<ProviderInfo> providers =
                data.createTypedArrayList(ProviderInfo.CREATOR);
            ComponentName testName = (data.readInt() != 0)
                ? new ComponentName(data) : null;
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle testArgs = data.readBundle();
            IBinder binder = data.readStrongBinder();
            IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
            binder = data.readStrongBinder();
            IUiAutomationConnection uiAutomationConnection =
                    IUiAutomationConnection.Stub.asInterface(binder);
            int testMode = data.readInt();
            boolean enableBinderTracking = data.readInt() != 0;
            boolean trackAllocation = data.readInt() != 0;
            boolean restrictedBackupMode = (data.readInt() != 0);
            boolean persistent = (data.readInt() != 0);
            Configuration config = Configuration.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            HashMap<String, IBinder> services = data.readHashMap(null);
            Bundle coreSettings = data.readBundle();
            bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
                    testWatcher, uiAutomationConnection, testMode, enableBinderTracking,
                    trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,
                    coreSettings);
            return true;

再往下面跟services的来源就跟到Native层了,本文这里就不往下追踪了。

上面再说ServiceManager的getService方法里面,第二种服务对象的来源getIServiceManager().getService()还没说,这里续上。我们先来看一下getIServiceManager()的源码:

private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

由上面的java代码可以看出,返回对象其实是Native层生成的ServiceManager服务的代理对象。我们来看一下ServiceManagerNative的getService代码:

public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

从上面代码可以看出,getService也是通过底层Native层获取到的我们所想要的服务的对象的。

总结:

getSystemService方法获取到的系统服务来源是,先通过ApplicationThreadNative服务从底层获取,然后这些服务对象会放进ServiceManager的map中,如果map里面找不到对应名字的服务,再通过ServiceManagerNative从底层获取到。至于服务对象是何时添加到ServiceManagerNative里面的,请参考博客SystemServer解析

好了,本文到这里就把getSystemService的流程逆向分析了一遍,由于才疏学浅只追踪到Java层,再往下Native层的工作就先不分析了,请读者们见谅,欢迎多提意见,

猜你喜欢

转载自blog.csdn.net/baidu_27196493/article/details/81543108