您的位置:首页 > 移动开发 > Android开发

android 7.0 Activity 的getSystemService()

2017-05-11 14:25 381 查看
当我们的应用需要调用系统服务时,我们是通过getSystemService()方法来获取系统服务并直接调用。系统服务的进程和当前应用程序的进程肯定是不同的,不同的进程间是不能直接进行通信的。那为什么可以这个方法获取直接调用呢?我们来看看到底是怎么实现的。
getSystemService()方法是在ContextImpl中,因为Activity时的Context对象的实现类是ContextImpl。


frameworks\base\core\java\android\app\ContextImpl.java->getSystemService():

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


再看看SystemServiceRegistry.java。

frameworks\base\core\java\android\app\SystemServiceRegistry.java->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;
}
... ...
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();


那这个SYSTEM_SERVICE_FETCHERS又是存的什么呢?整个类中我们只找到了一个用put的方法:

/**
* 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);
}


这里存的是ServiceFetcher类型

static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}


registerService看名字似乎是注册服务的时候用的,还是个私有的类,我们再往下找找,可以发现在SystemServiceRegistry.java的静态代码块注册了这些系统服务:

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);
}});
... ...
}


可以看到存入的值都是CachedServiceFetcher类型,CachedServiceFetcher类继承createService。

/**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;

public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
}

@Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service = cache[mCacheIndex];
if (service == null) {
service = createService(ctx);
cache[mCacheIndex] = service;
}
return (T)service;
}
}

public abstract T createService(ContextImpl ctx);
}


可以看到createService是在当前ServiceFetcher的 getService里执行的。

哦,明白了,当获取到的服务是在另一个进程时,比如上面的AccountManager.class;先通过ServiceManager获取到了该服务的BP段,然后通过IAccountManager.Stub.asInterface(b);通过Binder驱动找到该服务的Bn端,然后将Bn端保存起来。这样getSystemService()得到的是该服务的Bn端,就可以跨进程通信了。(这里涉及到了Binder跨进程通信和AIDL)


*注:当Android系统第一次开机启动时,会开始注册系统服务,并把这些服务和ServiceManager进行关联
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  class android