Android(安卓)7.0 ActivityManagerService(1) AMS的启动过程
一、概况
ActivityManagerService(AMS)是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。
AMS通信结构如下图所示:
从图中可以看出:
1、AMS继承自ActivityManagerNative(AMN),并实现了Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。
2、AMN继承Java的Binder类,同时实现了IActivityManager接口,即AMN将作为Binder通信的服务端为用户提供支持。
3、在ActivityManagerNative类中定义了内部类ActivityManagerProxy,该类同样实现了IActivityManager接口,将作为客户端使用的服务端代理。
4、其它进程将使用ActivityManager来使用AMS的服务。ActivityManager通过AMN提供的getDefault接口得到ActivityManagerProxy,然后再以Binder通信的方式调用AMS的接口。
对AMS的基本情况有一个大概的了解后,我们一起来分析一下AMS的启动过程。
由于AMS启动涉及的内容比较多,我们将分段进行分析。
二、createSystemContext
在进入到AMS相关的流程前,我们需要先了解一下相关的准备工作。
我们已经知道了,zygote创建出的第一个java进程是SystemServer。
在SystemServer的run函数中,在启动AMS之前,调用了createSystemContext函数。
其代码如下所示:
.............//SystemServer在启动任何服务之前,就调用了createSystemContext//创建出的Context保存在mSystemContext中// Initialize the system context.createSystemContext();// Create the system service manager.//SystemServiceManager负责启动所有的系统服务,使用的Context就是mSystemContextmSystemServiceManager = new SystemServiceManager(mSystemContext);.............
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
我们跟进一下createSystemContext:
private void createSystemContext() { //调用ActivityThread的systemMain函数,其中会创建出系统对应的Context对象 ActivityThread activityThread = ActivityThread.systemMain(); //取出上面函数创建的Context对象,保存在mSystemContext中 mSystemContext = activityThread.getSystemContext(); //设置系统主题 mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
以上函数中,最重要的就是ActivityThread.systemMain了,我们分析一下该函数。
1、ActivityThread.systemMain
public static ActivityThread systemMain() { // The system process on low-memory devices do not get to use hardware // accelerated drawing, since this can add too much overhead to the // process. if (!ActivityManager.isHighEndGfx()) { //虽然写着ActivityManager,但和AMS没有任何关系 //就是利用系统属性和配置信息进行判断 //关闭硬件渲染功能 ThreadedRenderer.disable(true); } else { ThreadedRenderer.enableForegroundTrimming(); } //创建ActivityThread ActivityThread thread = new ActivityThread(); //调用attach函数,参数为true thread.attach(true); return thread;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
从上面的代码可以看出,ActivityThread的systemMain函数中,除了进行是否开启硬件渲染的判断外,主要作用是:
创建出ActivityThread对象,然后调用该对象的attach函数。
ActivityThread的构造函数比较简单:
ActivityThread() { mResourcesManager = ResourcesManager.getInstance();}
- 1
- 2
- 3
- 1
- 2
- 3
比较关键的是它的成员变量:
..........//定义了AMS与应用通信的接口final ApplicationThread mAppThread = new ApplicationThread();//拥有自己的looper,说明ActivityThread确实可以代表事件处理线程final Looper mLooper = Looper.myLooper();//H继承Handler,ActivityThread中大量事件处理依赖此Handlerfinal H mH = new H();//用于保存该进程的ActivityRecordfinal ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>()..........//用于保存进程中的Servicefinal ArrayMap<IBinder, Service> mServices = new ArrayMap<>();...........//用于保存进程中的Applicationfinal ArrayList<Application> mAllApplications = new ArrayList<Application>();...........
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
我们需要知道的是,ActivityThread是android Framework中一个非常重要的类,它代表一个应用进程的主线程,其职责就是调度及执行在该线程中运行的四大组件。
在Android中,应用进程指那些运行APK的进程,它们由zygote fork出来,其中运行着独立的dalvik虚拟机。
与应用进程相对的就是系统进程,例如zygote和SystemServer。
注意到此处的ActivityThread创建于SystemServer进程中。
由于SystemServer中也运行着一些系统APK,例如framework-res.apk、SettingsProvider.apk等,因此也可以认为SystemServer是一个特殊的应用进程。
对于上面提到的ActivityThread的成员变量,其用途基本上可以从名称中得知,这里仅说明一下ApplicationThread。
AMS负责管理和调度进程,因此AMS需要通过Binder机制和应用进程通信。
为此,Android提供了一个IApplicationThread接口,该接口定义了AMS和应用进程之间的交互函数。
如上图所示,ActivityThread作为应用进程的主线程代表,在其中持有ApplicationThread。ApplicationThread继承ApplicationThreadNative。
当AMS与应用进程通信时,ApplicationThread将作为Binder通信的服务端。
AMS与应用进程通信时,通过ApplicationThreadNative获取应用进程对应的ApplicationThreadProxy对象。
通过ApplicationThreadProxy对象,将调用信息通过Binder传递到ActivityThread中的ApplicationThread。
这个调用过程,今后还会遇到,碰到的时候再详细分析。
2、ActivityThread.attach
我们看看ActivityThread的attach函数:
//此时,我们传入的参数为true,表示该ActivityThread是系统进程的ActivityThreadprivate void attach(boolean system) { //创建出的ActivityThread保存在类的静态变量sCurrentActivityThread //AMS中的大量操作将会依赖于这个ActivityThread sCurrentActivityThread = this; mSystemThread = system; if (!system) { //应用进程的处理流程 .......... } else { //系统进程的处理流程,该情况只在SystemServer中处理 // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. //设置DDMS(Dalvik Debug Monitor Service)中看到的SystemServer进程的名称为“system_process” android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { //创建ActivityThread中的重要成员:Instrumentation、Application和Context mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); mInitialApplication = context.mPackageInfo.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } //以下系统进程和非系统进程均会执行 ................ //注册Configuration变化的回调通知 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { //当系统配置发生变化时(例如系统语言发生变化),回调该接口 ............... } ............. });}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
从上面的代码可以看出,对于系统进程而言,ActivityThread的attach函数最重要的工作就是创建了Instrumentation、Application和Context。
2.1 Instrumentation
Instrumentation是Android中的一个工具类,当该类被启用时,它将优先于应用中其它的类被初始化。
此时,系统先创建它,再通过它创建其它组件。
此外,系统和应用组件之间的交互也将通过Instrumentation来传递。
因此,Instrumentation就能监控系统和组件的交互情况了。
实际使用时,可以创建该类的派生类进行相应的操作。
这个类在介绍启动Activity的过程时还会碰到,此处不作展开。
2.2 Context
Context是Android中的一个抽象类,用于维护应用运行环境的全局信息。
通过Context可以访问应用的资源和类,甚至进行系统级的操作,例如启动Activity、发送广播等。
ActivityThread的attach函数中,通过下面的代码创建出系统应用对应的Context:
.......//ContextImpl是Context的实现类ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo);.......
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
2.2.1 getSystemContext
我们先看看ActivityThread中getSystemContext的内容:
public ContextImpl getSystemContext() { synchronized (this) { if (mSystemContext == null) { //调用ContextImpl的静态函数createSystemContext mSystemContext = ContextImpl.createSystemContext(this); } return mSystemContext; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
进入ContextImpl的createSystemContext函数:
static ContextImpl createSystemContext(ActivityThread mainThread) { //创建LoadedApk类,代表一个加载到系统中的APK //注意此时的LoadedApk只是一个空壳 //PKMS还没有启动,估无法得到有效的ApplicationInfo LoadedApk packageInfo = new LoadedApk(mainThread); //调用ContextImpl的构造函数 ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY); //初始化资源信息 context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(), context.mResourcesManager.getDisplayMetrics()); return context;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可以看出createSystemContext的内容就是创建一个LoadedApk,然后初始化一个ContextImpl对象。
似乎没有什么特别的,那么为什么函数名被叫做create “System” Context?
为了回答这个问题,就要看看LoadedApk的构造函数了:
LoadedApk(ActivityThread activityThread) { mActivityThread = activityThread; mApplicationInfo = new ApplicationInfo(); //packageName为"android" mApplicationInfo.packageName = "android"; mPackageName = "android"; //下面许多参数为null ................}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
注意到createSystemContext函数中,创建的LoadApk对应packageName为”android”,也就是framwork-res.apk。
由于该APK仅供SystemServer进程使用,因此创建的Context被定义为System Context。
现在该LoadedApk还没有得到framwork-res.apk实际的信息。
当PKMS启动,完成对应的解析后,AMS将重新设置这个LoadedApk。
2.2.2 ContextImpl.createAppContext
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); return new ContextImpl(null, mainThread, packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
相对而言,createAppContext的内容就比较简单了,就是利用ActivityThread和LoadedApk构造出ContextImpl。
ContextImpl的构造函数主要是完成一些变量的初始化,建立起ContextImpl与ActivityThread、LoadedApk、ContentResolver之间的关系。
代码简单但是冗长,此处不做展开。
2.3 Application
Android中Application类用于保存应用的全局状态。
我们经常使用的Activity和Service均必须和具体的Application绑定在一起。
通过上图的继承关系,每个具体的Activity和Service均被加入到Android运行环境中。
在ActivityThread中,针对系统进程,通过下面的代码创建了初始的Application:
..............//调用LoadedApk的makeApplication函数mInitialApplication = context.mPackageInfo.makeApplication(true, null);//启动ApplicationmInitialApplication.onCreate();..............
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
我们看一下LoadedApk.makeApplication:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } ............. Application app = null; String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { //系统进程中,对应下面的appClass appClass = "android.app.Application"; } try { java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { ............ } ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //实际上最后通过反射创建出Application app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { .......... } //一个进程支持多个Application,mAllApplications用于保存该进程中的Application对象 mActivityThread.mAllApplications.add(app); mApplication = app; ..............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
从上面的代码不难看出,这部分主要是创建framework-res.apk对应的Application,然后调用它的onCreate函数,完成启动。
总结
至此,createSystemContext函数介绍完毕。
当SystemServer调用createSystemContext完毕后:
1、得到了一个ActivityThread对象,它代表当前进程 (此时为系统进程) 的主线程;
2、得到了一个Context对象,对于SystemServer而言,它包含的Application运行环境与framework-res.apk有关。
在继续分析AMS之前,我们先停下来思考一下,为什么在启动所有的服务前,SystemServer先要调用createSystemContext?
个人觉得《深入理解Android》对这个问题,解释的比较好,大致意思如下:
Android努力构筑了一个自己的运行环境。
在这个环境中,进程的概念被模糊化了。组件的运行及它们之间的交互均在该环境中实现。
createSystemContext函数就是为SystemServer进程搭建一个和应用进程一样的Android运行环境。
Android运行环境是构建在进程之上的,应用程序一般只和Android运行环境交互。
基于同样的道理,SystemServer进程希望它内部运行的应用,
也通过Android运行环境交互,因此才调用了createSystemContext函数。
创建Android运行环境时,
由于SystemServer的特殊性,调用了ActivityThread.systemMain函数;
对于普通的应用程序,将在自己的主线程中调用ActivityThread.main函数。
上图表示了进程的Android运行环境涉及的主要类之间的关系。
其中的核心类是ContextImpl,通过它可以得到ContentResolver、系统资源、应用信息等。
三、AMS初始化
创建完Android运行环境后,SystemServer调用startBootstrapServices,其中就创建并启动了AMS:
private void startBootstrapServices() { Installer installer = mSystemServiceManager.startService(Installer.class); // Activity manager runs the show. //启动AMS,然后获取AMS保存到变量中 mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); //以下均是将变量存储到AMS中 mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); ..........}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
注意到上面的代码并没有直接启动AMS,而是启动AMS的内部类Lifecycle。
这是迫不得已的做法,由于AMS并没有继承SystemService,因此不能通过SystemServiceManager的startService直接启动它。
可以这样理解:内部类Lifecycle对于AMS而言,就像一个适配器一样,让AMS能够像SystemService一样被SystemServiceManager通过反射的方式启动。
public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; public Lifecycle(Context context) { //Lifecycle由SystemServiceManager启动,传入的context就是SystemServer创建出的SystemContext super(context); //1、调用AMS的构造函数 mService = new ActivityManagerService(context); } @Override public void onStart() { //2、调用AMS的start函数 mService.start(); } public ActivityManagerService getService() { return mService; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
接下来我们分别看看AMS的构造函数和start函数。
1、AMS的构造函数
先来看看AMS的构造函数:
public ActivityManagerService(Context systemContext) { //AMS的运行上下文与SystemServer一致 mContext = systemContext; ............ //取出的是ActivityThread的静态变量sCurrentActivityThread //这意味着mSystemThread与SystemServer中的ActivityThread一致 mSystemThread = ActivityThread.currentActivityThread(); ............ mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); //处理AMS中消息的主力 mHandler = new MainHandler(mHandlerThread.getLooper()); //UiHandler对应于Android中的UiThread mUiHandler = new UiHandler(); if (sKillHandler == null) { sKillThread = new ServiceThread(TAG + ":kill", android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */); sKillThread.start(); //用于接收消息,杀死进程 sKillHandler = new KillHandler(sKillThread.getLooper()); } //创建两个BroadcastQueue,前台的超时时间为10s,后台的超时时间为60s mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; //创建变量,用于存储信息 mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this); mAppErrors = new AppErrors(mContext, this); //这一部分,分析BatteryStatsService时提过,进行BSS的初始化 File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); systemDir.mkdirs(); mBatteryStatsService = new BatteryStatsService(systemDir, mHandler); mBatteryStatsService.getActiveStatistics().readLocked(); mBatteryStatsService.scheduleWriteToDisk(); mOnBattery = DEBUG_POWER ? true : mBatteryStatsService.getActiveStatistics().getIsOnBattery(); mBatteryStatsService.getActiveStatistics().setCallback(this); //创建ProcessStatsService,感觉用于记录进程运行时的统计信息,例如内存使用情况,写入/proc/stat文件 mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats")); //启动Android的权限检查服务,并注册对应的回调接口 mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler); mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null, new IAppOpsCallback.Stub() { @Override public void opChanged(int op, int uid, String packageName) { if (op == AppOpsManager.OP_RUN_IN_BACKGROUND && packageName != null) { if (mAppOpsService.checkOperation(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { runInBackgroundDisabled(uid); } } } }); //用于定义ContentProvider访问指定Uri对应数据的权限,aosp中似乎没有这文件 mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); //创建多用户管理器 mUserController = new UserController(this); //获取OpenGL版本 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); ............ //资源配置信息置为默认值 mConfiguration.setToDefaults(); mConfiguration.setLocales(LocaleList.getDefault()); mConfigurationSeq = mConfiguration.seq = 1; //感觉用于记录进程的CPU使用情况 mProcessCpuTracker.init(); //解析/data/system/packages-compat.xml文件,该文件用于存储那些需要考虑屏幕尺寸的APK的一些信息 //当APK所运行的设备不满足要求时,AMS会根据xml设置的参数以采用屏幕兼容的方式运行该APK mCompatModePackages = new CompatModePackages(this, systemDir, mHandler); //用于根据规则过滤一些Intent mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler); //以下的类,似乎用于管理和监控AMS维护的Activity Task信息 //ActivityStackSupervisor是AMS中用来管理Activity启动和调度的核心类 mStackSupervisor = new ActivityStackSupervisor(this); mActivityStarter = new ActivityStarter(this, mStackSupervisor); mRecentTasks = new RecentTasks(this, mStackSupervisor); //创建线程用于统计进程的CPU使用情况 mProcessCpuThread = new Thread("CpuTracker") { @Override public void run() { while (true) { try { try { //计算更新信息的等待间隔 //同时利用wait等待计算出的间隔时间 ...... } catch(InterruptedException e) { } //更新CPU运行统计信息 updateCpuStatsNow(); } catch (Exception e) { .......... } } } }; //加入Watchdog的监控 Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
从代码来看,AMS的构造函数还是相对比较简单的,主要工作就是初始化一些变量。
大多数变量的用途,从命名上基本可以推测出来,实际的使用情况必须结合具体的场景才能进一步了解。
2、AMS的start函数
private void start() { //完成统计前的复位工作 Process.removeAllProcessGroups(); //开始监控进程的CPU使用情况 mProcessCpuThread.start(); //注册服务 mBatteryStatsService.publish(mContext); mAppOpsService.publish(mContext); Slog.d("AppOps", "AppOpsService published"); LocalServices.addService(ActivityManagerInternal.class, new LocalService());}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
AMS的start函数比较简单,主要是:
1、启动CPU监控线程。该线程将会开始统计不同进程使用CPU的情况。
2、发布一些服务,如BatteryStatsService、AppOpsService(权限管理相关)和本地实现的继承ActivityManagerInternal的服务。
至此AMS初始化相关的内容基本结束,从这些代码可以看出AMS涉及的类比较多,我们目前无法一一详述每个类的具体用途。
有机会遇到具体的场景时,再深入分析,此处有个大致印象即可。
四、将SystemServer纳入AMS的管理体系
1、setSystemProcess
AMS完成启动后,在SystemServer的startBootstrapServices函数中,
下一个与AMS相关的重要调用就是AMS.setSystemProcess了:
private void startBootstrapServices() { ........... // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); ...........}
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
我们跟进一下setSystemProcess函数:
public void setSystemProcess() { try { //以下是向ServiceManager注册几个服务 //AMS自己 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); //注册进程统计信息的服务 ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats); //用于打印内存信息用的 ServiceManager.addService("meminfo", new MemBinder(this)); //用于输出进程使用硬件渲染方面的信息 ServiceManager.addService("gfxinfo", new GraphicsBinder(this)); //用于输出数据库相关的信息 ServiceManager.addService("dbinfo", new DbBinder(this)); //MONITOR_CPU_USAGE默认为true if (MONITOR_CPU_USAGE) { //用于输出进程的CPU使用情况 ServiceManager.addService("cpuinfo", new CpuBinder(this)); } //注册权限管理服务 ServiceManager.addService("permission", new PermissionController(this)); //注册获取进程信息的服务 ServiceManager.addService("processinfo", new ProcessInfoService(this)); //1、向PKMS查询package名为“android”的应用的ApplicationInfo ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY); //2、调用installSystemApplicationInfo mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader()); //3、以下与AMS的进程管理有关 synchronized (this) { ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0); app.persistent = true; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); synchronized (mPidsSelfLocked) { mPidsSelfLocked.put(app.pid, app); } updateLruProcessLocked(app, false, null); updateOomAdjLocked(); } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( "Unable to find android system package", e); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
从上面的代码可以看出,AMS的setSystemProcess主要有四个主要的功能:
1、注册一些服务;
2、获取package名为“android”的应用的ApplicationInfo;
3、调用ActivityThread的installSystemApplicationInfo;
4、AMS进程管理相关的操作。
这四个主要的功能中,第一个比较简单,就是用Binder通信完成注册。
我们主要看看后三个功能对应的流程。
1.1 获取ApplicationInfo
如前所述,这部分相关的代码为:
..........ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);..........
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
1.1.1 获取PKMS服务代理
我们先看看mContext.getPackageManager()的操作过程。
我们已经知道mContext的实现类是ContextImpl,其中对应的代码如下:
@Overridepublic PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } //依赖于ActivityThread的getPackageManager函数 IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. //利用PKMS的代理对象,构建ApplicationPackageManager //该类继承PackageManager return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
跟进一下ActivityThread中的getPackageManager:
public static IPackageManager getPackageManager() { if (sPackageManager != null) { //Slog.v("PackageManager", "returning cur default = " + sPackageManager); return sPackageManager; } //依赖于Binder通信,获取到PKMS对应的BpBinder IBinder b = ServiceManager.getService("package"); ..................... //得到PKMS对应的Binder服务代理 sPackageManager = IPackageManager.Stub.asInterface(b); .................... return sPackageManager;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
从上面的代码我们可以看到,AMS获取PKMS用到了Binder通信。
实际上,PKMS由SystemServer创建,与AMS运行在同一个进程。
AMS完全可以不经过Context、ActivityThread、Binder来获取PKMS。
根据一些资料,推断出原生代码这么做的原因是:
SystemServer进程中的服务,也使用Android运行环境来交互,
保留了组件之间交互接口的统一,为未来的系统保留了可扩展性。
1.1.2 通过PKMS获取ApplicationInfo
得到PKMS的代理对象后,AMS调用PKMS的getApplicationInfo接口,获取package名为”android”的ApplicationInfo。
在AMS的setSystemProcess被调用前,PKMS已经启动了。
之前分析PKMS的博客中,我们已经提到,在PKMS的构造函数中,
它将解析手机中所有的AndroidManifest.xml,然后形成各种数据结构以维护应用的信息。
getApplicationInfo就是通过package名,从对应的数据结构中,取出对应的应用信息。
这部分内容主要就是查询数据结构的内容,不作深入分析。
1.2 installSystemApplicationInfo
得到framework-res.apk对应的ApplicationInfo后,需要将这部分ApplicationInfo保存到SystemServer对应的ActivityThread中。
这部分对应的代码为:
..............mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());..............
- 1
- 2
- 3
- 1
- 2
- 3
AMS中的mSystemThread就是SystemServer中创建出的ActivityThread。
因此我们跟进一下ActivityThread的installSystemApplicationInfo函数:
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { synchronized (this) { //调用SystemServer中创建出的ContextImpl的installSystemApplicationInfo函数 getSystemContext().installSystemApplicationInfo(info, classLoader); // give ourselves a default profiler //创建一个Profiler对象,用于性能统计 mProfiler = new Profiler(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
继续跟进ContextImpl的installSystemApplicationInfo函数:
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { //前面已经提到过mPackageInfo的类型为LoadedApk mPackageInfo.installSystemApplicationInfo(info, classLoader);}
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
随着流程进入到LoadedApk:
/*** Sets application info about the system package.*/void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { //这个接口仅供系统进程调用,故这里断言一下 assert info.packageName.equals("android"); mApplicationInfo = info; mClassLoader = classLoader;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
至此,我们知道了installSystemApplicationInfo的真相就是:
将“android”对应的ApplicationInfo(即framework-res.apk对应的ApplicationInfo),
加入到SystemServer之前调用createSystemContext时,创建出的LoadedApk中。
毕竟SystemServer创建System Context时,PKMS并没有完成对手机中文件的解析,初始的LoadedApk中并没有持有有效的ApplicationInfo。
在此基础上,AMS下一步的工作就呼之欲出了。
由于framework-res.apk运行在SystemServer进程中,而AMS是专门用于进程管理和调度的,
因此SystemServer进程也应该在AMS中有对应的管理结构。
于是,AMS的下一步工作就是将SystemServer的运行环境和一个进程管理结构对应起来,并进行统一的管理。
1.3 AMS进程管理注意到上面的ContentProvider注册到AMS后,进行了notifyAll的操作。
举例来说:进程A需要查询一个数据库,需要通过进程B中的某个ContentProvider来实施。
如果B还未启动,那么AMS就需要先启动B。在这段时间内,A需要等待B启动并注册对应的ContentProvider。
B一旦完成ContentProvider的注册,就需要告知A退出等待以继续后续的查询工作。
setSystemProcess函数中,进程管理相关的代码为:
.............synchronized (this) { //创建进程管理对应的结构ProcessRecord ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0); //由于此时创建的是SystemServer进程对应ProcessRecord //因此设定了一些特殊值 app.persistent = true; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; //将SystemServer对应的ApplicationThread保存到ProcessRecord中 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); synchronized (mPidsSelfLocked) { //按pid将ProcessRecord保存到mPidsSelfLocked中 mPidsSelfLocked.put(app.pid, app); } //updateLruProcessLocked来调整进程在mLruProcess列表的位置 //在这个列表中,最近活动过得进程总是位于前列,同时拥有Activity的进程位置总是前于只有Service的进程 updateLruProcessLocked(app, false, null); //更新进程对应的oom_adj值(oom_adj将决定进程是否被kill掉) updateOomAdjLocked();}...............
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
这里我们仅分析一下创建进程管理结构的函数newProcessRecordLocked。
updateLruProcessLocked和updateOomAdjLocked函数比较复杂,等对AMS有更多的了解后,再做分析。
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) { //进程的名称 String proc = customProcess != null ? customProcess : info.processName; //将用于创建该进程的电源统计项 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); final int userId = UserHandle.getUserId(info.uid); //isolated此时为false if (isolated) { .......... } //创建出对应的存储结构 final ProcessRecord r = new ProcessRecord(stats, info, proc, uid); //判断进程是否常驻 if (!mBooted && !mBooting && userId == UserHandle.USER_SYSTEM && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { r.persistent = true; } //按进程名将ProcessRecord存入到AMS的变量mProcessNames中 //该变量的类型为ProcessMap //结合前面的代码,我们知道AMS有两种方式可以取到ProcessRecord //一是根据进程名,二是根据进程名称 addProcessNameLocked(r); return r;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
跟进一下ProcessRecord的构造函数:
ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, String _processName, int _uid) { mBatteryStats = _batteryStats; //用于电量统计 info = _info; //保存ApplicationInfo ........... processName = _processName; //保存进程名 //一个进程能运行多个Package,pkgList用于保存package名 pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode)); //以下变量和进程调度优先级有关 maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = ProcessList.INVALID_ADJ; curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ; //决定进程是否常驻内存(即使被杀掉,系统也会重启它) persistent = false; removed = false; lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
总结
至此,我们对AMS的setSystemProcess函数分析告一段落。
从上面的代码可以看出,在这个函数中除了发布一些服务外,主要是:
将framework-res.apk的信息加入到SystemServer对应的LoadedApk中,同时构建SystemServer进程对应的ProcessRecord,
以将SystemServer进程纳入到AMS的管理中。
2、AMS的installSystemProviders
接下来AMS启动相关的操作,定义于SystemServer的startOtherServices函数中。
private void startOtherServices() { ........... mActivityManagerService.installSystemProviders(); ...........}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
我们跟进一下AMS的installSystemProviders函数:
public final void installSystemProviders() { List providers; synchronized (this) { //AMS根据进程名取出SystemServer对应的ProcessRecord ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID); //1、得到该ProcessRecord对应的ProviderInfo providers = generateApplicationProvidersLocked(app); //这里仅处理系统级的Provider if (providers != null) { for (int i=providers.size()-1; i>=0; i--) { ProviderInfo pi = (ProviderInfo)providers.get(i); if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Not installing system proc provider " + pi.name + ": not system .apk"); providers.remove(i); } } } } } if (providers != null) { //2、安装Provider mSystemThread.installSystemProviders(providers); } //创建ContentObserver监控Settings数据库中Secure、System和Global表的变化 mCoreSettingsObserver = new CoreSettingsObserver(this); //创建ContentObserver监控Settings数据库中字体大小的变化 mFontScaleSettingObserver = new FontScaleSettingObserver();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
从上面的代码可以看出,installSystemProviders主要是加载运行在SystemServer进程中的ContentProvider,即SettingsProvider.apk (定义于frameworks/base/packages/SettingsProvider)。
上面有两个比较重要的函数:
1、generateApplicationProvidersLocked返回一个进程对应的ProviderInfo List。
2、ActivityThread可以看做是进程的Android运行环境,因此它的installSystemProviders表示为对应进程安装ContentProvider。
当SettingsProvider被加载到SystemServer进程中运行后,AMS就注册了两个ContentObserver监控SettingsProvider中的字段变化。
AMS监控的字段影响范围比较广,例如字体发生变化时,很多应用的显示界面都需要做出调整。
这也许就是让AMS来负责监控这些字段的原因。
接下来,我们分别看看上述比较重要的两个函数。
2.1 generateApplicationProvidersLocked
private final List generateApplicationProvidersLocked(ProcessRecord app) { List providers = null; try { //利用PKMS根据进程名及权限,从数据结构中得到进程对应ProviderInfo providers = AppGlobals.getPackageManager() .queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS | MATCH_DEBUG_TRIAGED_MISSING) .getList(); } catch (RemoteException ex) { } ............. int userId = app.userId; if (providers != null) { int N = providers.size(); //写这行代码的人,一定是个极客!!!! //通常而言,我们逐渐向容器加入数据时,容器只有在数据超出当前存储空间时 //才会进行内存的重新分配(一般是乘2)和数据的拷贝 //因此若待加入数据总量很大,在逐步向容器加入数据的过程中,容器将会有多次重新分配和拷贝的过程 //或许整体的开销并不是很惊人,但事先将内存一次分配到位,体现了对极致的追求 (情不自禁的写了这段话。。。) app.pubProviders.ensureCapacity(N + app.pubProviders.size()); for (int i=0; i//判断Provider是否为单例的 boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); //这里应该是针对多用户的处理 //若一个Provider是单例的,但当前进程不属于默认用户,那么这个Provider将不被处理 //简单来说,就是两个用户都启动一个进程时(有了两个进程), //定义于进程Package中单例的Provider仅运行在默认用户启动的进程中 if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) { // This is a singleton provider, but a user besides the // default user is asking to initialize a process it runs // in... well, no, it doesn't actually run in this process, // it runs in the process of the default user. Get rid of it. providers.remove(i); N--; i--; continue; } //包名和类名组成ComponentName ComponentName comp = new ComponentName(cpi.packageName, cpi.name); //创建ContentProvider对应的ContentProviderRecord //加入到AMS的mProviderMap中 ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); if (cpr == null) { cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton); mProviderMap.putProviderByClass(comp, cpr); } ............ //将ContentProviderRecord保存在ProcessRecord中 app.pubProviders.put(cpi.name, cpr); if (!cpi.multiprocess || !"android".equals(cpi.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. //当ContentProvider仅属于当前进程时,还需要统计该Provider的运行信息 app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode, mProcessStats); } //通知PKMS记录该Provider对应包被使用的时间 notifyPackageUse(cpi.applicationInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER); } } return providers;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
整体来讲generateApplicationProvidersLocked函数的思想很简单,最主要的功能是:
从PKMS中得到应用对应的ContentProvider,然后利用应用信息和对应的ContentProvider组成ContentProviderRecord,
并按包名存储到AMS的mProviderMap中。
AMS保存ProviderInfo的原因是:它需要管理ContentProvider。
此外,我们看到ProcessRecord也保存了ProviderInfo,这是因为ContentProvider最终要落实到一个进程中。
这也是为了方便AMS的管理,毕竟一个进程退出时,AMS需要将其中运行的ContentProvider信息从系统中移除。
generateApplicationProvidersLocked中唯一稍微绕了点弯的地方是,针对多用户的情况,判断了ContentProvider是否为单例的。
就像我注释里写的,个人觉得在多用户的场景下,“同一个”进程变成了多个,分别运行在每个用户对应的空间中。
假设ContentProvider在对应的xml中定义了,运行在指定进程A中。
那么当多个用户都加载进程A时(此时进程名或许相似,但不是一个进程),
A进程中定义的ContentProvider将被加载多次,分别运行在各个用户的进程A中。
但是当一个ContentProvider是单例的,那么该ContentProvider仅会被加载在系统用户(类似于administrator)启动的进程中。
虽然目前多用户的场景比较少,ContentProvider到底运行在哪个进程中,可能也不是那么重要。
但本着学习的态度,我们还是看看isSingleton的实现:
boolean isSingleton(String componentProcessName, ApplicationInfo aInfo, String className, int flags) { boolean result = false; // For apps that don't have pre-defined UIDs, check for permission //非系统用户,就是多了个权限检查 //是否单例还是取决于ServiceInfo.FLAG_SINGLE_USER if (UserHandle.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) { if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { if (ActivityManager.checkUidPermission( INTERACT_ACROSS_USERS, aInfo.uid) != PackageManager.PERMISSION_GRANTED) { //无权限,则抛出异常 ............. } } // Permission passed result = true; } else if ("system".equals(componentProcessName)) { result = true; } else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { // Phone app and persistent apps are allowed to export singleuser providers. result = UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID) || (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0; } ............. return result;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
从上面的代码,我们知道了:
对于非系统用户而言,当Provider的flag包含ServiceInfo.FLAG_SINGLE_USER时,它是单例的;
对于系统用户而言,当Provider运行在系统进程中,或者 该Provider运行在(Phone进程或常驻进程)且(包含ServiceInfo.FLAG_SINGLE_USER)时,它是单例的。
至此,我们知道了generateApplicationProvidersLocked函数,主要就是用于得到和保存对应进程的ContentProvider信息。
2.2 installSystemProviders
得到运行在进程中的ContentProvider的信息后,当然要进行安装了。
对于运行在SystemServer中的ContentProvider,AMS将调用ActivityThread的installSystemProviders进行处理。
public final void installSystemProviders(List providers) { if (providers != null) { //对于SystemServer进程而言,mInitialApplication是framework-res.apk对应的Application installContentProviders(mInitialApplication, providers); }}private void installContentProviders( Context context, List providers) { final ArrayList results = new ArrayList(); for (ProviderInfo cpi : providers) { .............. //1、初始化并保存ContentProvider IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { //2、向AMS注册ContentProvider ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
installContentProviders是安装ContentProvider时的通用程序,主要包括两方面的工作:
1、调用installProvider得到IActivityManager.ContentProviderHolder对象,其间完成了对应ContentProvider的初始化等工作。
2、向AMS发布这个IActivityManager.ContentProviderHolder。
2.2.1 installProvider
private IActivityManager.ContentProviderHolder installProvider(Context context, IActivityManager.ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) { ContentProvider localProvider = null; IContentProvider provider; if (holder == null || holder.provider == null) { //此时holder==null, 进入这个分支 ............ Context c = null; ApplicationInfo ai = info.applicationInfo; //下面判断的作用是:为待安装的ContentProvider找到对应的Application //在AndroidManifest.xml中,ContentProvider是Application的子标签, //因此ContentProvider与Application有一种对应关系 //在本次的流程中,传入的Context是mInitialApplication,代表的是framework-res.apk //而Provider代表的是SettingsProvider, SettingsProvider.apk所对应的Application还未创建 if (context.getPackageName().equals(ai.packageName)) { c = context; } else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) { c = mInitialApplication; } else { try { //以下将创建一个Context,指向SettingsProvider.apk //ai.packageName为com.android.provider.settings //利用package对应的LoadedApk信息,创建ContextImpl //当前主线程如果加载过这个LoadedApk,将从存储变量中取出LoadedApk //否则将通过PKMS得到对应的ApplicationInfo,并以ApplicationInfo构建出LoadedApk,然后保存在存储变量中 c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { // Ignore } } .................. try { //除了ContextProvider与Application的对应关系外,必须先找到ContextProvider对应的Context的另一个原因是: //只有正确的Context才能加载对应APK的Java字节码,从而通过反射的方式创建出ContextProvider实例 //得到对应的ClassLoader final java.lang.ClassLoader cl = c.getClassLoader(); //反射创建实例 localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); //得到ContentProvider的mTransport对象 //表现类型为接口IContentProvider,实际为ContentProviderNative,即ContentProvider的Binder通信服务端 provider = localProvider.getIContentProvider(); .................. //初始化ContentProvider,内部会调用ContentProvder的onCreate函数 localProvider.attachInfo(c, info); } catch(java.lang.Exception e) { ............ } } else { provider = holder.provider; if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": " + info.name); } IActivityManager.ContentProviderHolder retHolder; synchronized (mProviderMap) { ............... //调用ContentProviderNative的asBinder IBinder jBinder = provider.asBinder(); if (localProvider != null) { ComponentName cname = new ComponentName(info.packageName, info.name); ProviderClientRecord pr = mLocalProvidersByName.get(cname); if (pr != null) { ............ } else { //创建ContentProviderHolder持有ContentProvider holder = new IActivityManager.ContentProviderHolder(info); holder.provider = provider; holder.noReleaseNeeded = true; //构造ProviderClientRecord,并按authority将ProviderClientRecord存入mProviderMap pr = installProviderAuthoritiesLocked(provider, localProvider, holder); mLocalProviders.put(jBinder, pr); mLocalProvidersByName.put(cname, pr); } retHolder = pr.mHolder; } else { ............... } } return retHolder;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
installProvider的代码较长,但实际思想很简单,就是环环相扣的三步:
1、创建出ContentProvider对应的ContextImpl(代表对应的运行环境);
2、利用ContextImpl得到对应的ClassLoader,完成ContentProvider的初始化和启动;
3、得到与ContentProvider通信的BpBinder,然后按名称和BpBinder,将ContentProvider保存到对应的存储结构中。
ActivityThread与ContentProvider的关系大概如上图所示。
ContentProvider本身只是一个容器,其内部持有的Transport类才能提供对跨进程调用的支持。
Transport类继承自ContentProviderNative类,作为ContentProvider的Binder通信服务端。
ContentProviderNative中定义了ContentProvderProxy类,将作为Binder通信的服务端代理。
如上代码所示,ActivityThread用mLocalProviders保存运行在本地的ContentProvider时,
使用的键值就是ContentProvider的Binder通信服务端。
2.2.2 publishContentProviders
ContentProvider初始化完成后,我们需要向AMS注册它。
如前所述,在ActivityThread的installContentProviders函数中,将通过下面这段代码进行注册:
..........ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results);.........
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
这段代码是注册ContentProvider的通用代码,因此即使我们现在的流程运行在AMS中,此处仍然将通过Binder通信进行调用。
ActivityManagerNative.getDefault()将得到ActivityManagerProxy对象,因此上面代码实际上调用的是ActivityManagerProxy.publishContentProviders:
//ActivityThread注册ContentProvider时,传入了自己的ApplicationThread,//当AMS与ActivityThread通信时,ApplicationThread作为Binder通信的服务端public void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeTypedList(providers); //消息打包完成后,发往服务端AMS mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在AMS父类AMN的onTransact函数中:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { ....... case PUBLISH_CONTENT_PROVIDERS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); //得到ApplicationThread的BpBinder IBinder b = data.readStrongBinder(); //得到ActivityThread中ApplicationThread的服务端代理 IApplicationThread app = ApplicationThreadNative.asInterface(b); //解析出消息 ArrayList<ContentProviderHolder> providers = data.createTypedArrayList(ContentProviderHolder.CREATOR); //AMN调用子类的函数 publishContentProviders(app, providers); reply.writeNoException(); return true; } ....... } .........}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
跟着流程,现在我们看看AMS中的publishContentProviders函数:
public final void publishContentProviders(IApplicationThread caller, List providers) { if (providers == null) { return; } ........... synchronized (this) { //找到调用者对应的ProcessRecord对象 final ProcessRecord r = getRecordForAppLocked(caller); ........... final int N = providers.size(); for (int i = 0; i < N; i++) { ContentProviderHolder src = providers.get(i); ............ //ProcessRecord的pubProviders中保存了ContentProviderRecord信息 //这是根据PKMS解析出的Package信息生成的 //此处主要判断将要发布的ContentProvider是否由该Pacakge声明 ContentProviderRecord dst = r.pubProviders.get(src.info.name); ............ if (dst != null) { ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); //按名称保存到mProviderMap mProviderMap.putProviderByClass(comp, dst); ............... String names[] = dst.info.authority.split(";"); for (int j = 0; j < names.length; j++) { //按authority保存到mProviderMap mProviderMap.putProviderByName(names[j], dst); } } //mLaunchingProviders保存处于启动状态的Provider int launchingCount = mLaunchingProviders.size(); int j; boolean wasInLaunchingProviders = false; for (j = 0; j < launchingCount; j++) { if (mLaunchingProviders.get(j) == dst) { //这个ContentProvider完成启动,从队列中移除 mLaunchingProviders.remove(j); wasInLaunchingProviders = true; j--; launchingCount--; } } if (wasInLaunchingProviders) { //取消启动超时的消息 mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r); } synchronized (dst) { dst.provider = src.provider; dst.proc = r; //通知等待那些等待ContentProvider所在进程启动的客户端进程 dst.notifyAll(); } //每发布一个ContentProvder,均调整对应进程的oom_adj updateOomAdjLocked(r); //判断,并在需要时更新ContentProvider相关的统计信息 maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } } ..........}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
publishContentProviders函数结束后,一个ContentProvider就算正式在系统中注册了。
在AMS的启动过程中,此处注册的是SettingsProvider。
此后,Settings数据库相关的操作均由它来管理。
注意到上面的ContentProvider注册到AMS后,进行了notifyAll的操作。
举例来说:进程A需要查询一个数据库,需要通过进程B中的某个ContentProvider来实施。
如果B还未启动,那么AMS就需要先启动B。在这段时间内,A需要等待B启动并注册对应的ContentProvider。
B一旦完成ContentProvider的注册,就需要告知A退出等待以继续后续的查询工作。
五、AMS的systemReady
接下来,我们看看AMS启动的最后一部分:systemReady。
该函数在SystemServer中startOtherServices的最后被调用:
private void startOtherServices() { ............ // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. mActivityManagerService.systemReady(new Runnable() { .............. });}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
我们分段看看AMS中systemReady的处理流程。
此处的分段并没有实际的意义,只是代码确实太长了,并且连续性不够,因此分开描述。
1 阶段一
public void systemReady(final Runnable goingCallback) { synchronized(this) { .......... //这一部分主要是调用一些关键服务SystemReady相关的函数, //进行一些等待AMS初始完,才能进行的工作 // Make sure we have the current profile info, since it is needed for security checks. mUserController.onSystemReady(); mRecentTasks.onSystemReadyLocked(); mAppOpsService.systemReady(); mSystemReady = true; } ArrayList procsToKill = null; synchronized(mPidsSelfLocked) { //mPidsSelfLocked中保存当前正在运行的所有进程的信息 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) { ProcessRecord proc = mPidsSelfLocked.valueAt(i); //在AMS启动完成前,如果没有FLAG_PERSISTENT标志的进程已经启动了, //就将这个进程加入到procsToKill中 if (!isAllowedWhileBooting(proc.info)){ if (procsToKill == null) { procsToKill = new ArrayList(); } procsToKill.add(proc); } } } synchronized(this) { //利用removeProcessLocked关闭procsToKill中的进程 if (procsToKill != null) { for (int i=procsToKill.size()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); Slog.i(TAG, "Removing system update proc: " + proc); removeProcessLocked(proc, true, false, "system update done"); } } // Now that we have cleaned up any update processes, we // are ready to start launching real processes and know that // we won't trample on them any more. //至此系统准备完毕 mProcessesReady = true; } ............ //根据数据库和资源文件,获取一些配置参数 retrieveSettings(); final int currentUserId; synchronized (this) { //得到当前的用户ID currentUserId = mUserController.getCurrentUserIdLocked(); //读取urigrants.xml,为其中定义的ContentProvider配置对指定Uri数据的访问/修改权限 //原生代码中,似乎没有urigrants.xml文件 //实际使用的grant-uri-permission是分布式定义的 readGrantedUriPermissionsLocked(); } ..........
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
这一部分的工作主要是调用一些关键服务的初始化函数,
然后杀死那些没有FLAG_PERSISTENT却在AMS启动完成前已经存在的进程,
同时获取一些配置参数。
需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀死的进程是Java进程。
2 阶段二
//1、调用参数传入的runnable对象,SystemServer中有具体的定义if (goingCallback != null) goingCallback.run();..............//调用所有系统服务的onStartUser接口mSystemServiceManager.startUser(currentUserId);.............synchronized (this) { // Only start up encryption-aware persistent apps; once user is // unlocked we'll come back around and start unaware apps 2、启动persistent为1的application所在的进程 startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE); // Start up initial activity. mBooting = true; // Enable home activity for system user, so that the system can always boot //当isSplitSystemUser返回true时,意味者system user和primary user是分离的 //这里应该是让system user也有启动home activity的权限吧 if (UserManager.isSplitSystemUser()) { ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } //3、启动Home startHomeActivityLocked(currentUserId, "systemReady"); try { //发送消息,触发处理Uid错误的Application if (AppGlobals.getPackageManager().hasSystemUidErrors()) { .......... mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget(); } } catch (RemoteException e) { } //发送一些广播信息 ............ //这里暂时先不深入,等进一步了解Activity的启动过程后,再做了解 mStackSupervisor.resumeFocusedStackTopActivityLocked(); ............}.............
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
从部分代码来看,主要的工作就是通知一些服务可以进行systemReady相关的工作,并进行启动服务或应用进程的工作。
2.1 调用回调接口
回调接口的具体内容定义与SystemServer.java中,其中会调用大量服务的onBootPhase函数、一些对象的systemReady函数或systemRunning函数。
此处,我们仅截取一些比较特别的内容:
public void run() { ............ try { //启动NativeCrashListener监听"/data/system/ndebugsocket"中的信息 //实际上是监听debuggerd传入的信息 mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } ............ try { //启动SystemUi startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } ............ //这个以前分析过,启动Watchdog Watchdog.getInstance().start(); ....................}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
回调接口中的内容较多,不做一一分析。
2.2 启动persistent标志的进程
我们看看startPersistentApps对应的内容:
private void startPersistentApps(int matchFlags) { ............. synchronized (this) { try { //从PKMS中得到persistent为1的ApplicationInfo final List apps = AppGlobals.getPackageManager() .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList(); for (ApplicationInfo app : apps) { //由于framework-res.apk已经由系统启动,所以此处不再启动它 if (!"android".equals(app.packageName)) { //addAppLocked中将启动application所在进程 addAppLocked(app, false, null /* ABI override */); } } } catch (RemoteException ex) { } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
跟进一下addAppLocked函数:
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, String abiOverride) { //以下是取出或构造出ApplicationInfo对应的ProcessRecord ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(info.processName, info.uid, true); } else { app = null; } if (app == null) { app = newProcessRecordLocked(info, null, isolated, 0); updateLruProcessLocked(app, false, null); updateOomAdjLocked(); } ........... // This package really, really can not be stopped. try { //通过PKMS将package对应数据结构的StoppedState置为fasle AppGlobals.getPackageManager().setPackageStoppedState( info.packageName, false, UserHandle.getUserId(app.uid)); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + info.packageName + ": " + e); } if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { app.persistent = true; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); //启动应用所在进程,将发送消息给zygote,后者fork出进程 startProcessLocked(app, "added application", app.processName, abiOverride, null /* entryPoint */, null /* entryPointArgs */); } return app;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
这里最终将通过startProcessLocked函数,启动实际的应用进程。
正如之前分析zygote进程时,提过的一样,zygote中的server socket将接收消息,然后为应用fork出进程。
2.3 启动Home Activity
看看启动Home Activity对应的startHomeActivityLocked函数:
boolean startHomeActivityLocked(int userId, String reason) { .............. Intent intent = getHomeIntent(); //根据intent中携带的ComponentName,利用PKMS得到ActivityInfo ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); //此时home对应进程应该还没启动,app为null ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); if (app == null || app.instrumentationClass == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); //启动home mActivityStarter.startHomeActivityLocked(intent, aInfo, reason); } } else { .......... } return true;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
这里暂时先不深究Home Activity启动的具体过程。
从手头的资料来看,当Home Activity启动后,
ActivityStackSupervisor中的activityIdleInternalLocked函数将被调用(具体调用过程,还需要研究):
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) { ........... if (isFocusedStack(r.task.stack) || fromTimeout) { booting = checkFinishBootingLocked(); } ............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在checkFinishBootingLocked函数中:
private boolean checkFinishBootingLocked() { //mService为AMS,mBooting变量在AMS回调SystemServer中定义的Runnable时,置为了true final boolean booting = mService.mBooting; boolean enableScreen = false; mService.mBooting = false; if (!mService.mBooted) { mService.mBooted = true; enableScreen = true; } if (booting || enableScreen) {、 //调用AMS的接口,发送消息 mService.postFinishBooting(booting, enableScreen); } return booting;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
最终,AMS的finishBooting函数将被调用:
final void finishBooting() { ......... //以下是注册广播接收器,用于处理需要重启的package IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); if (pkgs != null) { for (String pkg : pkgs) { synchronized (ActivityManagerService.this) { if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, 0, "query restart")) { setResultCode(Activity.RESULT_OK); return; } } } } } }, pkgFilter); ........... // Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED); //以下是启动那些等待启动的进程 synchronized (this) { // Ensure that any processes we had put on hold are now started // up. final int NP = mProcessesOnHold.size(); if (NP > 0) { ArrayList procs = new ArrayList(mProcessesOnHold); for (int ip=0; ip"on-hold", null); } } } } .............. if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { // Start looking for apps that are abusing wake locks. //每15min检查一次系统各应用进程使用电量的情况,如果某个进程使用WakeLock的时间过长 //AMS将关闭该进程 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); // Tell anyone interested that we are done booting! SystemProperties.set("sys.boot_completed", "1"); ................. //此处从代码来看发送的是ACTION_LOCKED_BOOT_COMPLETED广播 //在进行unlock相关的工作后,mUserController将调用finishUserUnlocking,发送SYSTEM_USER_UNLOCK_MSG消息给AMS //AMS收到消息后,调用mUserController的finishUserUnlocked函数,经过相应的处理后, //在mUserController的finishUserUnlockedCompleted中,最终将会发送ACTION_BOOT_COMPLETED广播 mUserController.sendBootCompletedLocked(.........); ................. }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
最终,当AMS启动Home Activity结束,并发送ACTION_BOOT_COMPLETED广播时,AMS的启动过程告一段落。
总结
对于整个AMS启动过程而言,博客中涉及的内容可能只是极小的一部分。
但即使我们尽可能的简化,整个过程的内容还是非常多。
大图链接
不过我们回头看看整个过程,还是能比较清晰地将AMS的启动过程分为四步,如上图所示:
1、创建出SystemServer进程的Android运行环境。
在这一部分,SystemServer进程主要创建出对应的ActivityThread和ContextImpl,构成Android运行环境。
AMS的后续工作依赖于SystemServer在此创建出的运行环境。
2、完成AMS的初始化和启动。
在这一部分,单纯地调用AMS的构造函数和start函数,完成AMS的一些初始化工作。
3、将SystemServer进程纳入到AMS的管理体系中。
AMS作为Java世界的进程管理和调度中心,要对所有Java进程一视同仁,因此SystemServer进程也必须被AMS管理。
在这个过程中,AMS加载了SystemServer中framework-res.apk的信息,并启动和注册了SettingsProvider.apk。
4、开始执行AMS启动完毕后才能进行的工作。
系统中的一些服务和进程,必须等待AMS完成启动后,才能展开后续工作。
在这一部分,AMS通过调用systemReady函数,通知系统中的其它服务和进程,可以进行对应工作了。
在这个过程中,值得我们关注的是:Home Activity被启动了。当该Activity被加载完成后,最终会触发ACTION_BOOT_COMPLETED广播。
更多相关文章
- Android电池驱动
- Android中启动其他Activity并返回结果
- Android(安卓)SurfaceFlinger 学习之路(五)----VSync 工作原理
- 2010.06.04日志:关于android正在运行程序的关闭问题
- android:imx8qm平台下spi_norflash启动kernel
- Android(安卓)8.1移植:针对某个APK做到wifi和gprs分别做到允许和
- Android判断app是不是第一次启动
- 浅析Android的RILD服务进程的消息循环
- # Android中Activity四种启动模式和taskAffinity属性详解 #(6原