android AMS
跟着
邓凡平
大神的博客走一遍加深理解。
AMS是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度
及应用进程的管理和调度
等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要。
ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback
- 客户端使用
ActivityManager
类。由于AMS是系统核心服务,很多API不能开放供客户端使用,所以设计者没有让ActivityManager直接加入AMS家族。在ActivityManager
类内部通过调用AMN的getDefault
函数得到一个ActivityManagerProxy
对象,通过它可与AMS通信。
1.ActivityManagerService启动
AMS由SystemServer的ServerThread线程创建,提取它的调用轨迹,代码如下:
//path:SystemServer.java::initAndLoop()//1.Boolean:factoryTest SystemProperties.get("ro.factorytest");是否厂测Context context=ActivityManagerService.main(factoryTest);//2.setSystemProcess:这样SystemServer进程可加到AMS中,并被它管理ActivityManagerService.setSystemProcess();//3.installSystemProviders:将SettingsProvider放到SystemServer进程中来运行ActivityManagerService.installSystemProviders();//4.在内部保存WindowManagerService(以后简称WMS)ActivityManagerService.self().setWindowManager(wm);//5.AMS是系统的核心,只有它准备好后,才能调用其他服务的systemReady,少量之前那完成。 ActivityManagerService.self().systemReady(new Runnable() { public void run() { Slog.i(TAG, "Making services ready"); ActivityManagerService.self().startObservingNativeCrashes(); // 如此,状态栏就准备好了 //SystemUIService由SystemUi.apk提供,它实现了系统的状态栏。 if (!headless) startSystemUi(contextF); if (mountServiceF != null) mountServiceF.systemReady(); if (batteryF != null) batteryF.systemReady(); if (networkManagementF != null) networkManagementF.systemReady(); if (networkStatsF != null) networkStatsF.systemReady(); if (networkPolicyF != null) networkPolicyF.systemReady(); if (connectivityF != null) connectivityF.systemReady(); if (dockF != null) dockF.systemReady(); if (usbF != null) usbF.systemReady(); if (twilightF != null) twilightF.systemReady(); if (uiModeF != null) uiModeF.systemReady(); if (recognitionF != null) recognitionF.systemReady(); Watchdog.getInstance().start(); // TODO:It is now okay to let the various system services start their third party code... if (appWidgetF != null) appWidgetF.systemRunning(safeMode); if (wallpaperF != null) wallpaperF.systemRunning(); if (immF != null) immF.systemRunning(statusBarF); if (locationF != null) locationF.systemRunning(); if (countryDetectorF != null) countryDetectorF.systemRunning(); if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning(); if (commonTimeMgmtServiceF != null) commonTimeMgmtServiceF.systemRunning(); ... // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!");
将分析除了4外的掉用。
1.1 ActivityManagerService.main
AMS的main函数将返回一个Context类型的对象,该对象在SystemServer中被其他服务大量使用。Context,顾名思义,代表了一种上下文环境,有了这个环境,我们就可以做很多事情(例如获取该环境中的资源、Java类信息等)。
//ActivityManagerService.javapublic static final Context main(int factoryTest) { //线程中完成: //1.ActivityManagerService m = new ActivityManagerService(); //mService = m;通知实例好了,则thr.mService!=null AThread thr = new AThread(); thr.start(); while (thr.mService == null) thr.wait();//收到通知,继续 ActivityManagerService m = thr.mService; mSelf = m; //2.ActivityThread它代表一个应用进程的主线程,其职责就是调度及执行在该线程中运行的四大组件。 ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; //3.接口获取并操作Application对应的资源、类,甚至包含于Application中的四大组件。 Context context = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface()); //AMS中用来管理Activity的启动和调度的核心类 m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); m.mAppOpsService.publish(context); thr.mReady = true; thr.notifyAll(); //4.启动startRunning函数 m.startRunning(null, null, null, null); return context;}
在main函数中,完成mSystemThread
等全局变量填充和调用了startRunning
函数.。主要分析·ActivityManagerService`构造函数。
和几个全局变量。
1.1.1 ActivityManagerService构造函数
AMS的构造函数的代码如下:
private ActivityManagerService() {//创建广播队列(前台和后台队列)mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false);mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue;//service和provider mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this);//创建/data/system/ File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); systemDir.mkdirs(); // 电源服务一些信息/data/system/batterystats.bin mBatteryStatsService = new BatteryStatsService(new File( systemDir, "batterystats.bin").toString()); mBatteryStatsService.getActiveStatistics().readLocked(); mBatteryStatsService.getActiveStatistics().writeAsyncLocked(); mOnBattery = DEBUG_POWER ? true : mBatteryStatsService.getActiveStatistics().getIsOnBattery(); mBatteryStatsService.getActiveStatistics().setCallback(this);//进程状态 /data/system/procstates mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats")); //使用状态 /data/system/usagestatsmUsageStatsService = new UsageStatsService(new File(systemDir, "usagestats").toString());// Ops状态 /data/system/appops.xml mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"));// Uri授权记录 /data/system/urigrants.xml mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0")); // User 0 is the first and only user that runs at boot. mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true)); mUserLru.add(Integer.valueOf(0)); updateStartedUserArrayLocked(); GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED);//mConfiguration类型为Configuration,用于描述资源文件的配置属性,//例如字体、语言等。后文再讨论这方面的内容 mConfiguration.setToDefaults(); mConfiguration.setLocale(Locale.getDefault()); mConfigurationSeq = mConfiguration.seq = 1; mProcessCpuTracker.init(); mCompatModePackages = new CompatModePackages(this, systemDir); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); mProcessCpuThread = new Thread("CpuTracker"){ @Override public void run() { while (true) { final long now = SystemClock.uptimeMillis(); long nextCpuDelay =(mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now; long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now; //Slog.i(TAG, "Cpu delay=" + nextCpuDelay // + ", write delay=" + nextWriteDelay); if (nextWriteDelay < nextCpuDelay) { nextCpuDelay = nextWriteDelay; } if (nextCpuDelay > 0) { mProcessCpuMutexFree.set(true); this.wait(nextCpuDelay); } updateCpuStatsNow(); } } }; mProcessCpuThread.start();}
构造函数完成了:
- 建立了
mFgBroadcastQueue
和mBgBroadcastQueue
两个广播队列。 - 建立
/data/system/
目录下一些信息,如:/data/system/procstates
等 - 一些配置信息初始化:字体,语言,等
- 启动线程,cpu一些使用情况。
1.1.2 ActivityThread.systemMain函数
注意:应用进程指那些运行APK的进程,它们由Zyote 派生(fork)而来,上面运行了dalvik虚拟机。与应用进程相对的就是系统进程(包括Zygote和SystemServer)。
“应用进程和系统进程”与“应用APK和系统APK”的概念区分开来。APK的判别依赖其文件所在位置(如果apk文件在/data/app目录下,则为应用APK)。
public static ActivityThread systemMain() { //禁止硬件加速 HardwareRenderer.disable(true); ActivityThread thread = new ActivityThread(); thread.attach(true); return thread;}
前面所说的ActivityThread代表应用进程(其上运行了APK)的主线程,而SystemServer并非一个应用进程,那么为什么此处也需要ActivityThread呢?
- 还记得在PackageManagerService分析中提到的framework-res.apk吗?这个APK除了包含资源文件外,还包含一些Activity(如关机对话框),这些Activity实际上运行在SystemServer进程中。从这个角度看,SystemServer是一个特殊的应用进程。
- 另外,通过ActivityThread可以把Android系统提供的组件之间的交互机制和交互接口(如利用Context提供的API)也拓展到SystemServer中使用。
//system=trueprivate void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) {//应用进程处理流程 ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("" ,UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } } 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看到systemserver进程名为system_process android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try {//Activity几员大将出场 mInstrumentation = new Instrumentation(); ContextImpl context = new ContextImpl(); context.init(getSystemContext().mPackageInfo, null, this); Application app = Instrumentation.newApplication(Application.class, context); //一个进程支持多个应用 mAllApplications.add(app); mInitialApplication = app; app.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); //监听配置改变,如语言切换时,需要调用。 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { synchronized (mResourcesManager) { // We need to apply this change to the resources // immediately, because upon returning the view // hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { // This actually changed the resources! Tell // everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(newConfig)) { mPendingConfiguration = newConfig; sendMessage(H.CONFIGURATION_CHANGED, newConfig); } } } } @Override public void onLowMemory() { } @Override public void onTrimMemory(int level) { } });}
Activity几员大将出场:
Instrumentation
:一个工具类。当它被启用时,系统先创建它,再通过它来创建其他组件。系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。Application
:保存了一个全局的application状态。Application由AndroidManifest.xml中的标签声明。在实际使用时需定义Application的派生类。Application是Android中的一个概念,可理解为一种容器,它内部包含四大组件。另外,一个进程可以运行多个Application。
Context
是一个接口,通过它可以获取并操作Application
对应的资源、类,甚至包含于Application中的四大组件。Context是一个抽象类,而由AMS创建的将是它的子类ContextImpl。
1.1.3 at.getSystemContext()函数
public ContextImpl getSystemContext() { synchronized (this) { if (mSystemContext == null) { ContextImpl context = ContextImpl.createSystemContext(this); //LoadedApk代表一个加载到系统中的APK LoadedApk info = new LoadedApk(this, "android", context, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO); context.init(info, null, this); //初始化资源信息 context.getResources().updateConfiguration (mResourcesManager.getConfiguration(), getDisplayMetricsLocked(Display.DEFAULT_DISPLAY)); mSystemContext = context; //Slog.i(TAG, "Created system resources " + context.getResources() // + ": " + context.getResources().getConfiguration()); } } return mSystemContext;}
为什么函数名是getSystemContext
呢?
初始化
ContextImp
时使用了一个LoadedApk对象,package
名为android
,,其实就是framework-res.apk,为了加载该APK。
上述类中关系图:先来看派生关系, ApplicationContentResolver从ConentResolver派生,它主要用于和ContentProvider打交道。ContextImpl和ContextWrapper均从Context继承,而Application则从ContextWrapper派生。
- 从社会关系角度看,ContextImpl交际面最广。它通过mResources指向Resources,mPackageInfo指向LoadedApk,mMainThread指向ActivityThread,mContentResolver指向ApplicationContentResolver。
对Context进行再议:
由图可知:
ContextWrapper
是一个代理类,被代理的对象是另外一个Context
。被代理的类其实是ContextImpl
,由ContextWrapper
通过mBase成员变量指定。其内部函数功能的实现最终都由mBase完成。这样设计的目的是想把ContextImpl隐藏起来。Application
从ContextWrapper
派生,并实现了ComponentCallbacks2
接口。Application中有一个LoadedApk
类型的成员变量mLoadedApk
。LoadedApk代表一个APK文件。由于一个AndroidManifest.xml
文件只能声明一个Application标签
,所以一个Application必然会和一个LoadedApk绑定。Service
从ContextWrapper
派生,其中Service内部成员变量mApplication
指向Application(在AndroidManifest.xml
中,Service只能作为Application
的子标签,所以在代码中Service
必然会和一个Application
绑定)。ContextThemeWrapper
重载了和Theme
(主题)相关的两个函数。这些和界面有关,所以Activity
作为Android系统中的UI容器,必然也会从ContextThemeWrapper
派生。与Service
一样,Activity内部也通过mApplication
成员变量指向Application
。
systemMain函数总结
调用systemMain函数结束后,我们得到了什么?
- 得到一个ActivityThread对象,它代表应用进程的主线程。
- 得到一个Context对象,它背后所指向的Application环境与framework-res.apk有关。
systemMain函数将为SystemServer进程搭建一个和应用进程一样的Android运行环境。这句话涉及两个概念。
- 进程:来源于操作系统,是在OS中看到的运行体。我们编写的代码一定要运行在一个进程中。
- Android运行环境:Android努力构筑了一个自己的运行环境。在这个环境中,进程的概念被模糊化了。组件的运行及它们之间的交互均在该环境中实现。
Android运行环境是构建在进程之上的。在应用程序中,一般只和Android运行环境交互。基于同样的道理,SystemServer希望它内部的那些Service也通过Android运行环境交互,因此也需为它创建一个运行环境。由于SystemServer的特殊性,此处调用了systemMain函数,而普通的应用进程将在主线程中调用ActivityThread的main函数来创建Android运行环境。
另外,ActivityThread虽然本意是代表进程的主线程,但是作为一个Java类,它的实例到底由什么线程创建,恐怕不是ActivityThread自己能做主的,所以在SystemServer中可以发现,ActivityThread对象由其他线程创建,而在应用进程中,ActivityThread将由主线程来创建。
1.1.4 m.startRunning函数
public final void startRunning(String pkg, String cls, String action, String data) {synchronized(this) { if (mStartRunning) { return; } mStartRunning = true; //mTopComponent最终赋值为null mTopComponent = pkg != null && cls != null ? new ComponentName(pkg, cls) : null; //mTopAction= Intent.ACTION_MAIN mTopAction = action != null ? action : Intent.ACTION_MAIN; mTopData = data;//mTopData最终为null if (!mSystemReady) { return; } } //这个函数很重要,可惜不在本次startRunning中调用 systemReady(null);}
1.2 ActivityManagerService.setSystemProcess函数
public static void setSystemProcess() { try { ActivityManagerService m = mSelf; //向ServiceManager注册几个服务 ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true); ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats); ServiceManager.addService("meminfo", new MemBinder(m)); ServiceManager.addService("gfxinfo", new GraphicsBinder(m));//显示加速方面的信息(Applications Graphics Acceleration Info), dumpsys gfxinfo ServiceManager.addService("dbinfo", new DbBinder(m)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(m)); } //向SM注册权限管理服务PermissionController ServiceManager.addService("permission", new PermissionController(m)); //虽然PKMS和AMS同属一个进程,但是二者交互仍然借助Context 其实,此处完全可以直接调用PKMS的函数。为什么要费如此周折呢 ApplicationInfo info = mSelf.mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS); //1.installSystemApplicationInfo mSystemThread.installSystemApplicationInfo(info); synchronized (mSelf) {//2.此处涉及AMS对进程的管理,processName=system ProcessRecord app = mSelf.newProcessRecordLocked(info, info.processName, false); //这里标识出systemProcess app.persistent = true;//设置该值为true app.pid = MY_PID;//设置pid为SystemServer的进程号 app.maxAdj = ProcessList.SYSTEM_ADJ;//设置最大OOM_Adj,系统进程默认值为-16 app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats); //3.保存该ProcessRecord对象 mSelf.mProcessNames.put(app.processName, app.uid, app); synchronized (mSelf.mPidsSelfLocked) { mSelf.mPidsSelfLocked.put(app.pid, app); } //根据系统当前状态,调整进程的调度优先级和OOM_Adj,后续将详细分析该函数 mSelf.updateLruProcessLocked(app, false, null); mSelf.updateOomAdjLocked(); } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( "Unable to find android system package", e); }}
在以上代码中列出了一个重要说明和两个关键点。
- AMS向PKMS查询名为“android”的ApplicationInfo。此处AMS和PKMS的交互是通过Context来完成的,查看这一系列函数调用的代码,最终发现AMS将通过Binder发送请求给PKMS来完成查询功能。AMS和PKMS同属一个进程,它们完全可以不通过Context来交互。此处为何要如此大费周章呢?原因很简单,Android希望SystemServer中的服务也通过Android运行环境来交互。这更多是从设计上来考虑的,比如组件之间交互接口的统一及未来系统的可扩展性。
1.2.1 mSystemThread.installSystemApplicationInfo分析
AMS通过Context查询PKMS中一个名为“android”的package得来,只有framework-res.apk声明其package名为“android”。
public void installSystemApplicationInfo(ApplicationInfo info) { synchronized (this) { //返回的ContextImpl对象即之前在AMS的main函数一节中创建的那个对象 ContextImpl context = getSystemContext(); //又调用init初始化该Context,是不是重复调用init了? context.init(new LoadedApk(this, "android", context, info, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this); // give ourselves a default profiler //创建一个Profiler对象,用于性能统计 mProfiler = new Profiler(); }}
又调用init初始化该Context,是不是重复调用init了?
- 第一次执行init时,在LoadedApk构造函数中第四个表示ApplicationInfo的参数为null。第二次执行init时,LoadedApk构造函数的第四个参数不为空,即该参数将真正指向一个实际的ApplicationInfo,该ApplicationInfo来源于framework-res.apk。
- Context第一次执行init的目的仅仅是为了创建一个Android运行环境,而该Context并没有和实际的ApplicationInfo绑定。而第二次执行init前,先利用Context和PKMS交互得到一个实际的ApplicationInfo,然后再通过init将此Context和ApplicationInfo绑定。
- framework-res.apk(包括后面将介绍的SettingsProvider.apk)运行在SystemServer中。和其他所有apk一样,它的运行需要一个正确初始化的Android运行环境。需要绑定ApplicationInfo。
1.2.2 mSelf.newProcessRecordLocked
函数
AMS和应用进程交互,如启动其他进程的Activity,由于该Activity在另一个进程中,需要跨进程通信,通过Binder
完成。Android提供了IApplicationThread接口,该接口定义了AMS和应用进程之间交互函数。
public interface IApplicationThread extends IInterface { void schedulePauseActivity; void scheduleStopActivity; void scheduleWindowVisibility; void scheduleSleeping; void scheduleResumeActivity void scheduleLaunchActivity void scheduleReceiver void scheduleCreateService void scheduleRegisteredReceiver void scheduleLowMemory() void setProcessState}
newProcessRecordLocked函数
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated) { String proc = customProcess != null ? customProcess : info.processName; BatteryStatsImpl.Uid.Proc ps = null; //BSImpl将为该进程创建一个耗电量统计项 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); int uid = info.uid; if (isolated) { int userId = UserHandle.getUserId(uid); int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1; while (true) { if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) { mNextIsolatedProcessUid = Process.FIRST_ISOLATED_UID; } uid = UserHandle.getUid(userId, mNextIsolatedProcessUid); mNextIsolatedProcessUid++; if (mIsolatedProcesses.indexOfKey(uid) < 0) { // No process for this uid, use it. break; } stepsLeft--; if (stepsLeft <= 0) { return null; } } } //创建一个ProcessRecord对象,用于和其他进程通信的thread作为第一个参数 return new ProcessRecord(stats, info, proc, uid);}
ProcessRecord构造函数初始化一些成员变量:
ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, String _processName, int _uid) { mBatteryStats = _batteryStats; //用于电量统计 info = _info;//保存ApplicationInfo isolated = _info.uid != _uid; uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; //保存进程名 pkgList.put(_info.packageName, null);//一个进程能运行多个Package,pkgList用于保存package名 //下面这些xxxAdj成员变量和进程调度优先级及OOM_adj有关。 maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; //用于控制该进程是否常驻内存(即使被杀掉,系统也会重启它),只有重要的进程才会有此待遇 persistent = false; removed = false; lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();}
AMS的setSystemProcess总结
现在来总结回顾setSystemProcess的工作:
- 注册AMS、meminfo、gfxinfo等服务到ServiceManager中。
- 根据PKMS返回的ApplicationInfo初始化Android运行环境,并创建一个代表SystemServer进程的ProcessRecord,从此,SystemServer进程也并入AMS的管理范围内。
1.3 ActivityManagerService.installSystemProviders函数
该Provider
在SettingsProvider.apk中,installSystemProviders
就会加载该APK
并把SettingsProvider
放到SystemServer
进程中来运行。此时的SystemServer已经加载了framework-res.apk,现在又要加载另外一个APK文件,这就是多个APK运行在同一进程的典型案例。另外,通过installSystemProviders函数还能见识ContentProvider的安装过程,下面就来分析它。
public static final void installSystemProviders() { List providers; synchronized (mSelf) { /*从mProcessNames找到进程名为“system”且uid为SYSTEM_UID的ProcessRecord,返回值就是前面在installSystemApplication中创建的那个ProcessRecord,它代表SystemServer进程 */ ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID); //1.关键调用,见下文分析 providers = mSelf.generateApplicationProvidersLocked(app); 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) { //将非系统APK(即未设ApplicationInfo.FLAG_SYSTEM标志)提供的Provider从providers列表中去掉 Slog.w(TAG, "Not installing system proc provider " + pi.name + ": not system .apk"); providers.remove(i); } } } } if (providers != null) { //2.为SystemServer进程安装Provider mSystemThread.installSystemProviders(providers); } //监视Settings数据库中Secure表的变化,目前只关注long_press_timeout配置的变化 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf); mSelf.mUsageStatsService.monitorPackages();}
在代码中列出了两个关键调用,分别是:
- 调用generateApplicationProvidersLocked函数,该函数返回一个ProviderInfo List。
- 调用ActivityThread的installSystemProviders函数。ActivityThread可以看做是进程的Android运行环境,那么installSystemProviders表示为该进程安装ContentProvider。
注意此处不再区分系统进程还是应用进程。由于只和ActivityThread交互,因此它运行在什么进程无关紧要。
AMS的 generateApplicationProvidersLocked
函数分析
private final List generateApplicationProvidersLocked(ProcessRecord app) { List providers = null; try { //1.向PKMS查询满足要求的ProviderInfo,最重要的查询条件包括:进程名和进程uid providers = AppGlobals.getPackageManager(). queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS); } catch (RemoteException ex) { } if (DEBUG_MU) Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid); int userId = app.userId; if (providers != null) { int N = providers.size(); app.pubProviders.ensureCapacity(N + app.pubProviders.size()); for (int i=0; i//2.AMS对ContentProvider的管理,见下文解释 ProviderInfo cpi = (ProviderInfo)providers.get(i); boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); if (singleton && UserHandle.getUserId(app.uid) != 0) { // 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 comp = new ComponentName(cpi.packageName, cpi.name); //ContentProvider在AMS中用ContentProviderRecord来表示 ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); if (cpr == null) { cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton); mProviderMap.putProviderByClass(comp, cpr); } if (DEBUG_MU) Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid); 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. app.addPackage(cpi.applicationInfo.packageName, mProcessStats); } ensurePackageDexOpt(cpi.applicationInfo.packageName); } } return providers;}
由以上代码可知:generateApplicationProvidersLocked先从PKMS那里查询满足条件的ProviderInfo信息,而后将它们分别保存到AMS和ProcessRecord中对应的数据结构中。
先看查询函数queryContentProviders。
public List queryContentProviders(String processName, int uid, int flags) { ArrayList finalList = null; // reader synchronized (mPackages) { final Iterator i = mProviders.mProviders.values().iterator(); final int userId = processName != null ? UserHandle.getUserId(uid) : UserHandle.getCallingUserId(); while (i.hasNext()) { final PackageParser.Provider p = i.next(); PackageSetting ps = mSettings.mPackages.get(p.owner.packageName); // 下面的if语句将从这些Provider中搜索本例设置的processName为“system”,uid为SYSTEM_UID,flags为FLAG_SYSTEM的Provider if (ps != null && p.info.authority != null && (processName == null || (p.info.processName.equals(processName) && UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) && mSettings.isEnabledLPr(p.info, flags, userId) && (!mSafeMode || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) { if (finalList == null) { finalList = new ArrayList(3); } ProviderInfo info = PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId); if (info != null) { finalList.add(info); } } } } //由PackageParser.Provider得到ProviderInfo,并添加到finalList中 if (finalList != null) { //最终结果按provider的initOrder排序,该值用于表示初始化ContentProvider的顺序 Collections.sort(finalList, mProviderInitOrderSorter); } return finalList;}
queryContentProviders函数很简单,就是从PKMS那里查找满足条件的Provider,然后生成AMS使用的ProviderInfo信息。为何偏偏能找到SettingsProvider呢?来看它的AndroidManifest.xml
文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.providers.settings" coreApp="true" android:sharedUserId="android.uid.system"> <application android:allowClearUserData="false" android:label="@string/app_label" android:process="system" android:backupAgent="SettingsBackupAgent" android:killAfterRestore="false" android:icon="@mipmap/ic_launcher_settings"> <provider android:name="SettingsProvider" android:authorities="settings" android:multiprocess="false" android:exported="true" android:writePermission="android.permission.WRITE_SETTINGS" android:initOrder="100" /> application>manifest>
SettingsProvider设置了其uid为“android.uid.system”,同时在application中设置了process名为“system”。而在framework-res.apk中也做了相同的设置。所以,现在可以确认SettingsProvider将和framework-res.apk运行在同一个进程,即SystemServer中。
提示从运行效率角度来说,这样做也是合情合理的。因为SystemServer的很多Service都依赖Settings数据库,把它们放在同一个进程中,可以降低由于进程间通信带来的效率损失。
1.4 ASM的systemReady分析
AMS的systemReady代码较多,会做什么,将会分为三个阶段。
systemReady第一阶段
public void systemReady(final Runnable goingCallback) {synchronized(this) {if (mSystemReady) {//SystemReady,则直接执行线程 if (goingCallback != null) goingCallback.run(); return;}if(SystemProperties.get("persist.sys.qb.enable","false").equals("true")){ reloadConfiguration();}// Check to see if there are any update receivers to run.是否有升级动作if (!mDidUpdate) { if (mWaitingUpdate) { return; } //准备PRE_BOOT_COMPLETED广播 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); List ris = null; try { // //向PKMS查询该广播的接收者 ris = AppGlobals.getPackageManager().queryIntentReceivers( intent, null, 0, 0); } catch (RemoteException e) { } if (ris != null) { for (int i=ris.size()-1; i>=0; i--) { if ((ris.get(i).activityInfo.applicationInfo.flags &ApplicationInfo.FLAG_SYSTEM) == 0) { ris.remove(i); } }//从返回的结果中删除那些非系统APK的广播接收者 //读取/data/system/called_pre_boots.dat文件,这里存储了上次启动时候已经 //接收并处理PRE_BOOT_COMPLETED广播的组件。鉴于该广播的特殊性,系统希望 //该广播仅被这些接收者处理一次 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE); ArrayList lastDoneReceivers = readLastDonePreBootReceivers(); final ArrayList doneReceivers = new ArrayList(); for (int i=0; inew ComponentName(ai.packageName, ai.name); if (lastDoneReceivers.contains(comp)) { ris.remove(i); i--; }//从PKMS返回的接收者中删除那些已经处理过该广播的对象 } final int[] users = getUsersLocked(); for (int i=0; inew ComponentName(ai.packageName, ai.name); doneReceivers.add(comp); intent.setComponent(comp); for (int j=0; jnull; //为最后一个广播接收者注册一个回调通知,当该接收者处理完广播后,将调用该回调 if (i == ris.size()-1 && j == users.length-1) { finisher = new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { // The raw IIntentReceiver interface is called // with the AM lock held, so redispatch to // execute our code without the lock. mHandler.post(new Runnable() { public void run() { synchronized (ActivityManagerService.this) { mDidUpdate = true; }//保存那些处理过该广播的接收者信息 writeLastDonePreBootReceivers(doneReceivers); showBootMessage(mContext.getText( R.string.android_upgrading_complete), false); systemReady(goingCallback); } }); } }; } Slog.i(TAG, "Sending system update to " + intent.getComponent() + " for user " + users[j]); + broadcastIntentLocked(null, null, intent, null, finisher, 0, null, null, null, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, users[j]); if (finisher != null) { mWaitingUpdate = true; } } } } if (mWaitingUpdate) { return; } mDidUpdate = true;}//调用AppOpsService.systemReady()mAppOpsService.systemReady();mSystemReady = true;if (!mStartRunning) { return;}
systemReady第一阶段的工作并不轻松,其主要职责是发送并处理与PRE_BOOT_COMPLETED广播相关的事情。目前代码中还没有接收该广播的地方,不过从代码中的注释中可猜测到,该广播接收者的工作似乎和系统升级有关。
systemReady第二阶段的工作
ArrayList procsToKill = null; synchronized(mPidsSelfLocked) { for (int i=mPidsSelfLocked.size()-1; i>=0; i--) { ProcessRecord proc = mPidsSelfLocked.valueAt(i); if (!isAllowedWhileBooting(proc.info)){ if (procsToKill == null) { procsToKill = new ArrayList(); } procsToKill.add(proc); } } } synchronized(this) { 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 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; } Slog.i(TAG, "System now ready"); if(checkQbVersion()) { Slog.i("Qb","System now ready"); getQbAndroidManager(); mQbFlag = mQbAndroidManager.checkFlag(); } EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis()); synchronized(this) { // Make sure we have no pre-ready processes sitting around. //和工厂测试有关,不对此进行讨论 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { ResolveInfo ri = mContext.getPackageManager() .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST), STOCK_PM_FLAGS); CharSequence errorMsg = null; if (ri != null) { ActivityInfo ai = ri.activityInfo; ApplicationInfo app = ai.applicationInfo; if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { mTopAction = Intent.ACTION_FACTORY_TEST; mTopData = null; mTopComponent = new ComponentName(app.packageName, ai.name); } else { errorMsg = mContext.getResources().getText( com.android.internal.R.string.factorytest_not_system); } } else { errorMsg = mContext.getResources().getText( com.android.internal.R.string.factorytest_no_action); } if (errorMsg != null) { mTopAction = null; mTopData = null; mTopComponent = null; Message msg = Message.obtain(); msg.what = SHOW_FACTORY_ERROR_MSG; msg.getData().putCharSequence("msg", errorMsg); mHandler.sendMessage(msg); } } }//查询Settings数据,获取一些配置参数 retrieveSettings();
systemReady第二阶段的工作包括:
- 杀死那些竟然在AMS还未启动完毕就先启动的应用进程。注意,这些应用进程一定是APK所在的Java进程,因为只有应用进程才会向AMS注册,而一般Native(例如mediaserver)进程是不会向AMS注册的。
systemReady第三阶段的工作
synchronized (this) { readGrantedUriPermissionsLocked();}//调用systemReady传入的参数,它是一个Runnable对象,下节将分析此函数if (goingCallback != null) goingCallback.run();synchronized (this) { if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { //从PKMS中查询那些persistent为1的ApplicationInfo List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); if (apps != null) { int N = apps.size(); int i; for (i=0; i//由于framework-res.apk已经由系统启动,所以这里需要把它去除 //framework-res.apk的packageName为"android" if (info != null && !info.packageName.equals("android")) { addAppLocked(info, false);//启动该Application所在的进程 } } } } catch (RemoteException ex) { // pm is in same process, this will never happen. } } // Start up initial activity.设置mBooting=true mBooting = true; try { if (AppGlobals.getPackageManager().hasSystemUidErrors()) { Message msg = Message.obtain(); msg.what = SHOW_UID_ERROR_MSG; mHandler.sendMessage(msg);//处理那些Uid有错误的Application } } catch (RemoteException e) { } long ident = Binder.clearCallingIdentity(); try { Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId); intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId); broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, 0, null, null, android.Manifest.permission.INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } finally { Binder.restoreCallingIdentity(ident); } //启动全系统第一个Activity,即Home mStackSupervisor.resumeTopActivitiesLocked(); sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);}
systemReady第三阶段的工作有3项:
- 调用systemReady设置的回调对象goingCallback的run函数。
- 启动那些声明了persistent的APK。
- 启动桌面。在Home启动成功后,AMS才发送ACTION_BOOT_COMPLETED广播。
更多相关文章
- android 电容屏(三):驱动调试之驱动程序分析篇
- Android,采用AIDL编写接口实现IPC 入门
- Android调用本机程序执行文件的方法
- Android面经总结
- Android(安卓)Wi-Fi Ethernet新IP获取机制—IpManager(Android(
- Android中Hook Instrumentation 的实现
- Android(安卓)4.4KitKat AudioRecord 流程分析
- Android(安卓)启动流程梳理
- Android(安卓)webkit 事件传递流程详解