Android中getSystemService流程
来源:互联网 发布:可以看亚丝娜本子软件 编辑:程序博客网 时间:2024/04/30 21:03
在平时的android开发中,我们经常会通过Context来获取系统服务,比如ActivityManagerService,AccountManagerService等系统服务,今天我们就来看下getSystemService(String name)的整个调用流程。
找到Context的实现类
打开Context类,可以看到Context是一个抽象类,那么getSystemService一定是在其实现类来调用的,具体我们都猜得到ContextImpl
public abstract class Context { ......}
为什么是ContextImpl呢?我们都知道当我们启动一个Activity的时候,其实是在ActivityThread#performLaunchActivity方法中启动的,这一点可以参考上一篇文章” Activity启动流程 “,一个Activity的入口是
ActivityThread的main方法,看下main方法
public static void main(String[] args) { ....... // 主线程消息循环 Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}
可以看到上面在main方法中,调用了自身的attach方法。
private void attach(boolean system) { ........ if (!system) { final IActivityManager mgr = ActivityManagerNative.getDefault(); try { // 通过binder获取到的ActivityManagerService关联当前mAppThread mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore }}
可以看到在main方法中,通过调用activityThread的attach方法,并且参数为false,表示非系统应用,会通过binder与
ActivityManagerService通信,并且最后会调用performLaunchActivity方法。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { .... } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (activity != null) { // 创建Context的实例 Context appContext = createBaseContextForActivity(r, activity); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor); ....... } r.paused = true; mActivities.put(r.token, r); } catch (SuperNotCalledException e) { ..... } return activity; }
可以看到创建Context的具体实现是在ActivityThread#createBaseContextForActivity方法中完成的
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { // 可以看到这里创建的具体实例是ContextImpl ContextImpl appContext = ContextImpl.createActivityContext( this, r.packageInfo, displayId, r.overrideConfig); appContext.setOuterContext(activity); Context baseContext = appContext; ...... return baseContext;}
好了,到现在位置我们可以看到Context的实现类就是ContextImpl,那么关于getSystemService的具体实现也应该在ContextImpl里面了。
getSystemService的具体实现
ContextImpl#getSystemService的实现如下
@Overridepublic Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name);}
可以看到实际上ContextImpl也是通过SystemServiceRegistry.getSystemService来获取具体的服务,那么下面看看SystemServiceRegistry.getSystemService
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<?>>();
可看到实际上获取系统服务是通过ServiceFetcher的getService来获取的,并且SYSTEM_SERVICE_FETCHERS实际上就是一个Map实例,所以肯定是通过put方法为它赋值的。通过搜索,我们发现只有一个地方在做put操作:
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);}
顾名思义,这个方法是用来注册系统服务的,当注册系统服务的时候,就会调用到SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);将当前的服务put到SYSTEM_SERVICE_NAMES集合中
static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx);}
ServiceFetcher是一个接口,又三个实现类:CachedServiceFetcher,StaticServiceFetcher,StaticOuterContextServiceFetcher,具体不同的服务可能对应不同的实现类
这些系统服务都是在SystemServiceRegistry的static静态代码块中进行注册的,如下:
static {..... 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); }}); registerService(Context.ACTIVITY_SERVICE, ActivityManager.class, new CachedServiceFetcher<ActivityManager>() { @Override public ActivityManager createService(ContextImpl ctx) { return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }});.....}
这里,我们以ActivityManagerService为例来进行学习。在注册该服务的时候,将Context.ACTIVITY_SERVICE作为键,将CachedServiceFetcher作为值,并且重写了createService方法,createService是在当前ServiceFetcher的
getService里执行的,这里会返回一个ActivityManager的实例,ctx.mMainThread.getHandler()就是ActivityThread中的H,在”activity 启动流程”一文,我们已经知道了,启动activity最终就会通过ActivityThread$H的handleMessage进行处理,实际上,包括service的启动以及Broadcast的处理都是在H里处理的,这个后面会细说。
在SystemServer中启动系统服务
我们知道android系统第一次开机的时候,会通过ZygoteInit来启动SystemServer,简单看下ZygoteInit#main方法
public static void main(String argv[]) { try { boolean startSystemServer = false; for (int i = 1; i < argv.length; i++) { // 通过系统传递过来的命令来判断是否需要启动运行SystemServer类 if ("start-system-server".equals(argv[i])) { startSystemServer = true; } } if (startSystemServer) { // 启动运行SystemServer类 startSystemServer(abiList, socketName); } }}
此时会执行SystemServer的main方法
public static void main(String[] args) { new SystemServer().run();}
比较简单,内部运行自身的run方法
private void run() { // 如果当前系统时间小于1970年,则设置为1970 if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // 设置默认的语言和地区 if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } // Mmmmmm... more memory! VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services. System.loadLibrary("android_servers"); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // 启动服务 try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { throw ex; } // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
在上面的run方法中,和service相关的操作主要就是通过下面的方法启动:开机,核心,以及其他服务
startBootstrapServices();startCoreServices();startOtherServices();
其实在这个三个start服务中,不止启动系统服务,还会将这些服务和ServiceManager进行关联,以方便ServiceManager的管理
比如:
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
好了,到这里为止,getSystemService的流程就走完了,作为自己的学习记录。如果又不对的地方,敬请指教。
- Android中getSystemService流程
- Android中服务管理相关流程getSystemService
- android中getSystemService详解
- android中getSystemService详解
- Android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- Android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- android中getSystemService详解
- 建立一个带有头结点的单向链表,并将存储在数组中的字符依次转储到链表的各个结点中
- R-CNN 简单梳理
- SpringMVC 之 后台接收参数 与前台传递数据
- OC 跳出多层for循环嵌套 goto
- 使用ServletContext对象统计网站的访问量
- Android中getSystemService流程
- TextView之SpannableStringBuilder使用总结
- 2016.11.05 第一篇博客
- Mongodb 忘记密码
- 反向传播算法的直观理解
- js正则笔记
- Glide源码解析
- 【Oracle】流程控制
- IntelliJ IDEA打开Maven项目,所有依赖红名,不可用,简单解决方案