赞
踩
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):
frameworks\base\core\tests\coretests\src\com\android\internal\app\ChooserActivityTest.java
frameworks\base\core\java\android\app\Activity.java
@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。
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
AutofillManager.AutofillClient {
private static final String TAG = "Activity";
xxxxxxx
}
2、ContextThemeWrapper.getSystemService方法的源码:
frameworks\base\core\java\android\view\ContextThemeWrapper.java
@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 的源码:
frameworks\base\core\java\android\app\ContextImpl.java
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
4、SystemServiceRegistry.getSystemService 的源码:
frameworks\base\core\java\android\app\SystemServiceRegistry.java
/**
* 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直接返回服务对象,比如ACCESSIBILITY_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流程解析》
https://blog.csdn.net/singledevil0/article/details/119324199
好了,本文到这里就把getSystemService的流程分析了一遍,只追踪到Java层,再往下Native层的工作就不分析了
————————————————
版权声明:本文为CSDN博主「Android海纳百川」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_27196493/article/details/81543108
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。