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是何方神圣,它其实是一个接口,其定义如下:

/**
     * Base interface for classes that fetch services.
     * These objects must only be created during static initialization.
     */
    static abstract interface ServiceFetcher<T> {
        T getService(ContextImpl ctx);
    }

再来看一下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是在ActivityManagerService.attachApplicationLocked里面调用的

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ......
        try {
            ......
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                                   mCoreSettingsObserver.getCoreSettingsLocked());
             ......
            
        } catch (Exception e) {
            ......
        }
        ......
        return true;
    }

而ActivityManagerService.attachApplicationLocked是在ActivityManagerService.attachApplication里面调用的,

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

而ActivityManagerService.attachApplication是在ActivityThread.attach里面调用的,

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ......
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
       }
}

而ActivityThread.attach又是在ActivityThread.main里面调用的,此处就不贴代码了。我们再返回到ActivityManagerService.attachApplicationLocked的代码里面看看,调用ActivityThread.bindApplication时参数services传的是getCommonServicesLocked(app.isolated),

private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
        // Isolated processes won't get this optimization, so that we don't
        // violate the rules about which services they have access to.
        if (isolated) {
            if (mIsolatedAppBindArgs == null) {
                mIsolatedAppBindArgs = new HashMap<>();
                mIsolatedAppBindArgs.put("package", ServiceManager.getService("package"));
            }
            return mIsolatedAppBindArgs;
        }

        if (mAppBindArgs == null) {
            mAppBindArgs = new HashMap<>();

            // Setup the application init args
            mAppBindArgs.put("package", ServiceManager.getService("package"));
            mAppBindArgs.put("window", ServiceManager.getService("window"));
            mAppBindArgs.put(Context.ALARM_SERVICE,
                    ServiceManager.getService(Context.ALARM_SERVICE));
        }
        return mAppBindArgs;
    }

可知,services里面最多有三个系统服务的代理对象PackageManagerService、WindowManagerService、AlarmManagerService,并且可以知道这三个服务的获取又绕回到ServiceManager.getService方法,这里可知,当我们的应用进程创建好之后,如果我们获取的是PackageManagerService、WindowManagerService、AlarmManagerService这三者服务,这就从ServiceManager的sCache里面获取,其他服务目前来看,是通过getIServiceManager().getService()方法获取的,看下文讲述。

上面再说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;
    }

BinderInternal.getContextObject()返回的是一个BinderProxy对象,所以ServiceManagerNative.asInterface返回对象其实是一个ServiceManagerProxy对象。我们来看一下ServiceManagerProxy的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;
    }

 

总结:

获取系统服务最终都是通过java层先拿到native底层的ServiceManager的代理ServiceManagerProxy,然后通过这个代理从底层获取我们所需服务的代理对象,这个底层就是Binder的底层驱动。

 

其实系统服务start之后,都会通过ServiceManager.addService方法把服务的原始Binder对象对象添加到binder底层中去,不add如何get呢,以PackageManagerService为例,在其main方法中

public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();

        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        ServiceManager.addService("package", m);
        return m;
    }

各种系统服务的启动请请参考我的另一篇博客《SystemServer解析》。

 

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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android海纳百川

打赏加微信,送跑车加管理

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值