TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
其中mContext是Context的一个实例
frameworks/base/core/java/android/content/Context.java
public final T getSystemService(Class serviceClass) {
// Because subclasses may override getSystemService(String) we cannot
// perform a lookup by class alone. We must first map the class to its
// service name then invoke the string-based method.
String serviceName = getSystemServiceName(serviceClass);
return serviceName != null ? (T)getSystemService(serviceName) : null;
}
先用getSystemServiceName获取服务名字,然后getSystemService返回结果,
frameworks/base/core/java/android/app/ContextImpl.java
public String getSystemServiceName(Class> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
frameworks/base/core/java/android/app/SystemServiceRegistry.java
public static String getSystemServiceName(Class> serviceClass) {
return SYSTEM_SERVICE_NAMES.get(serviceClass);
}
private static final HashMap, String> SYSTEM_SERVICE_NAMES =
new HashMap, String>();
SYSTEM_SERVICE_NAMES是HashMap,key是类,值是名字,初始化在registerService方法
private static void registerService(String serviceName, Class serviceClass,
ServiceFetcher serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
registerService方法在static静态调用块中使用
static {
...
registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
new CachedServiceFetcher() {
@Override
public TelephonyManager createService(ContextImpl ctx) {
return new TelephonyManager(ctx.getOuterContext());
}});
...
}
getSystemServiceName相关流程分析完毕,接下来是getSystemService流程:
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
代码又回到SystemServiceRegistry.java中
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同样是个HashMap,TelephonyManager.class对应的值其实就是刚才静态代码块中初始化代码中的:
new CachedServiceFetcher() {
@Override
public TelephonyManager createService(ContextImpl ctx) {
return new TelephonyManager(ctx.getOuterContext());
}}
CachedServiceFetcher定义如下:
static abstract class CachedServiceFetcher implements ServiceFetcher {
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);
mCacheIndex就是系统服务的索引,每增加一个服务值就加1 ;mServiceCache是一个数组,依靠数组索引就可以获取服务。从代码可见service是单例的,只有在为null的时候才会创建,后续从数组获取即可。createService的实现在代码SystemServiceRegistry的static静态调用块中,前面已贴出,就是new了一个TelephonyManager的实例。由于service数组的引用最终是一个静态的数组,所以一个进程中的SystemService如TelephonyManager只有一个实例。
流程到这里还有个小问题,就是TelephonyManager传递进去的context会一直有引用,那么岂不是第一个获取TelephonyManager的实例的地方会有内存泄漏。例如传递进去一个Activity,那么Activity岂不是会泄漏?其实Android有处理的,答案在TelephonyManager的构造函数中:
public TelephonyManager(Context context) {
Context appContext = context.getApplicationContext();
if (appContext != null) {
mContext = appContext;
} else {
mContext = context;
}
...
}
引用指向的是ApplicationContext,是没有泄漏这个问题的。
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
这个是跨进程binder相关,网上早有多个大神分析过binder机制,例如罗升阳的 Android进程间通信(IPC)机制Binder简要介绍和学习计划,ServiceManager的addService和getService有详细的分析。
/**
* Return the handle to a system-level service by class.
*
* Currently available classes are:
* {@link android.view.WindowManager}, {@link android.view.LayoutInflater},
* {@link android.app.ActivityManager}, {@link android.os.PowerManager},
* {@link android.app.AlarmManager}, {@link android.app.NotificationManager},
* {@link android.app.KeyguardManager}, {@link android.location.LocationManager},
* {@link android.app.SearchManager}, {@link android.os.Vibrator},
* {@link android.net.ConnectivityManager},
* {@link android.net.wifi.WifiManager},
* {@link android.media.AudioManager}, {@link android.media.MediaRouter},
* {@link android.telephony.TelephonyManager}, {@link android.telephony.SubscriptionManager},
* {@link android.view.inputmethod.InputMethodManager},
* {@link android.app.UiModeManager}, {@link android.app.DownloadManager},
* {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler},
* {@link android.app.usage.NetworkStatsManager}.
*
*/
列举了SystemService形式使用的多种xxManager,除了有TelephonyManager,还有:
*
* Note: System services obtained via this API may be closely associated with
* the Context in which they are obtained from. In general, do not share the
* service objects between various different contexts (Activities, Applications,
* Services, Providers, etc.)
*
避免了用多个Context实例化XXmanager, 通过SystemService每个进程的每个服务最多只有一个实例(没有用到的服务不会分配内存),节省内存;避免了多次创建和销毁服务的情况,加载一次服务后服务不会销毁,加快了速度。使用Context的SystemService不用考虑context传入后可能的内存泄漏,也不必顾忌多个SystemService实例消耗的内存。