首页 > 代码库 > 《深入理解Android2》读书笔记(四)
《深入理解Android2》读书笔记(四)
接上篇《深入理解Android2》读书笔记(三)
ActivityManagerService(AMS)
1.AMS由ActivityManagerNative(AMN)类派生,并实现Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。而AMN由Binder派生,实现了IActivityManager接口。
2.客户端使用ActivityManager类。由于AMS是系统核心服务,很多API不能开放供客户端使用,因此设计者没有让ActivityManager直接加入AMS家庭。ActivityManager类内部通过调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信。
public static final Context main(int factoryTest){ AThread thr = new AThread();//创建一个AThread线程对象 thr.start(); ActivityManagerService m = thr.mService; mSelf = m; //调用ActivityThread的systemMain函数 ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; //得到一个Context对象,注意调用的函数名为getSystemContext,何为System Context Context context = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; //ActivityStack是AMS中用来管理Activity的启动和调度的核心类,以后再分析它 m.mMainStack = new ActivityStack(m,context,true); //调用BSS的public函数,这个知识点我们在第5章介绍过了 m.mBatteryStatsService.publish(context); //另外一个service:UsageStatsService.读者阅读完本章后自行分析它 m.mUsageStatsService.publish(context); synchronized(thr){ thr.mReady = true; thr.notifyAll();//通知thr线程,本线程工作完成 } //调用AMS的startRunning函数 m.startRunning(null,null,null,null); return context; }
其中四个函数分别是
1.创建AThread线程。虽然AMS的main函数由ServerThread线程调用,但是AMS自己的工作并没有放在ServerThread中去做,而是新创建了一个线程,即AThread线程
2.ActivityThread.systemMain函数。初始化ActivityThread对象
3.ActivityThread.getSystemContext函数。用于获取一个Context对象,从函数名上看,该Context代表了System的上下文环境。
4.AMS的startRunning函数。
main函数中有一处等待(wait)、一处通知(notifyAll),因为
1.main函数首先需要等到AThread所在线程启动并完成一部分工作
2.AThread完成那一部分工作后,将等待main函数完成后续的工作
以上函数我在SDK23的版本并没有找到,权当记录了,下面来分析构造函数
public ActivityManagerService(Context systemContext) { mContext = systemContext; mFactoryTest = FactoryTest.getMode(); mSystemThread = ActivityThread.currentActivityThread(); Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); mHandler = new MainHandler(mHandlerThread.getLooper()); mUiHandler = new UiHandler(); 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); // TODO: Move creation of battery stats service outside of activity manager service. 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); mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats")); mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler); mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); // User 0 is the first and only user that runs at boot. mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true)); mUserLru.add(UserHandle.USER_OWNER); updateStartedUserArrayLocked(); GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations")); mConfiguration.setToDefaults(); mConfiguration.setLocale(Locale.getDefault()); mConfigurationSeq = mConfiguration.seq = 1; mProcessCpuTracker.init(); mCompatModePackages = new CompatModePackages(this, systemDir, mHandler); mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler); mRecentTasks = new RecentTasks(this); mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks); mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks); mProcessCpuThread = new Thread("CpuTracker") { @Override public void run() { while (true) { try { try { synchronized(this) { 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); } } } catch (InterruptedException e) { } updateCpuStatsNow(); } catch (Exception e) { Slog.e(TAG, "Unexpected exception collecting process stats", e); } } } }; Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler); }
1.创建BSS、USS、mProcessStats(ProcessStats类型)、mProcessStatsThread线程,这些都与系统运行状况统计相关
2.创建/data/system目录,为mCompatModePackages(CompatModePackages类型)和mConfiguration(Configuration类型)等成员变量赋值
ActivityThread
ActivityThread是Android Framework中一个非常重要的类,它代表一个应用进程的主线程(对于应用进程来说,ActivityThread的main函数确实是由该进程的主线程执行),其职责就是调度及执行在该线程中的四大组件。
应用进程指那些运行APK的进程,它们由Zyote派生(fork)而来,上面运行了dalvik虚拟机。与应用进程相对的就是系统进程(包括Zygote和system_server)。如果apk文件在/data/app目录下,则为应用apk
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()) { HardwareRenderer.disable(true); } else { HardwareRenderer.enableForegroundTrimming(); } ActivityThread thread = new ActivityThread(); thread.attach(true); return thread; }
通过ActivityThread可以把Android系统提供的组件之间的交互机制和交互接口(如利用Context提供的API)也拓展到system_server中使用。
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else { // Don‘t set application object here -- if the system crashes, // we can‘t display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { 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); } } // 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) { } }); }
attach函数中出现几个重要类型Instrumentation类、Application类及Context类,作用如下
1.Instrumentation是一个工具类,当它被启用时,系统先创建它,再通过它来创建其他组件,另外,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。
2.Application类保存了一个全局的application状态。Application由AndroidManifest.xml中的<applicaion>标签声明。在实际使用时需定义Applicaion的派生类(可以理解为一种容器,其内部包含四大组件。一个进程可以运行多个Application)
3.Context是一个接口,通过它可以获取并操作Application对应的资源、类,甚至包含于Application中的四大组件。
public ContextImpl getSystemContext() { synchronized (this) { if (mSystemContext == null) { mSystemContext = ContextImpl.createSystemContext(this); } return mSystemContext; } }
1.ApplicationContentResolver从ContentResolver派生,它主要用于和ContentProvider打交道。ContextImpl和ContextWrapper均从Context继承,而Application则从ContextWrapper派生
2.ContextImpl涉及的面最广,它通过mResources指向Resources,通过mPackageInfo指向LoadedApk,通过mMainThread指向ActivityThread,通过mContentResolver指向ApplicationContentResolver。
3.ActivityThread代表主线程,它通过mInstrumentation指向Instrumentation。另外,它还保存多个Application对象。
systemMain函数调用结束后,得到了:
1.得到了一个ActivityThread对象,它代表应用进程的主线程
2.得到了一个Context对象,它背后所指向的Application环境与framework-res.apk有关
systemMain函数的目的是为system_server进程搭建一个和应用进程一样的Android运行环境。
1.ContextWrapper是一个代理类,被代理的对象是另外一个Context,其实是ContextImpl,由ContextWrapper通过mBase成员变量指定。ContextWrapper其内部函数功能的实现最终都由mBase完成,这样设计的目的是想把ContextImpl隐藏起来。
2.Application从ContextWrapper派生,并实现了ComponentCallbacks2接口。Application中有一个LoadedApk类型的成员变量mLoadedApk。LoadedApk代表一个APK文件。由于一个AndroidManifest.xml文件只能声明一个Application标签,所以一个Application必然会和一个LoadedApk绑定。
3.Service从ContextWrapper派生,其中Service内部成员变量mApplication指向Application(在AndroidManifest.xml中,Service只能作为Application的子标签,所以在代码中Service必然会和一个Application绑定)。
4.ContextThemeWrapper重载了和Theme(主题)相关的两个函数。这些和界面有关,所以Activity作为Android系统中的UI容器,必然也会从ContextThemeWrapper派生。与Servcie一样,Activity内部也通过mApplication成员变量指向Application。
public void setSystemProcess() { try { 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)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(this)); } ServiceManager.addService("permission", new PermissionController(this)); ServiceManager.addService("processinfo", new ProcessInfoService(this)); ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS); mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader()); 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); } }
Context第一次执行init的目的仅仅是创建一个Android运行环境,而该Context并没有和实际的ApplicationInfo绑定。而第二次执行init前,先利用Context和PKMS交互得到一个实际ApplicationInfo,然后再通过init将此Context和ApplicationInfo绑定。
1.ApplicationThreadNative实现了IApplicationThread接口。从该接口定义的函数可知,AMS通过它可以和应用进程进行交互,例如,AMS启动一个Activity的时候会调用该接口的scheduleLaunchActivity函数
2.ActivityThread通过成员变量mAppThread指向它的内部类ApplicationThread,而ApplicationThread从ApplicationThreadNative派生
3.IApplicationThread的Binder服务端在应用进程中,因为AMS需要监听应用进程的死亡通知。
4.有了IApplicationThread接口,AMS就可以和应用进程交互了。
public final void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) { sendMessage( showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, token, 0, configChanges); }
当AMS想要停止(stop)一个Activity时,会调用对应进程IApplicationThread Binder客户端的scheduleStopActivity函数。该函数服务端实现的就是向ActivityThread所在线程发送一个消息。在应用进程中,ActivityThread运行在主线程中,所以这个消息最终在主线程被处理。Activity的onStop函数页将在主线程中被处理。
IApplication Thread仅仅是AMS和另外一个进程交互的接口,除此之外,AMS还需要更多的有关该进程的信息。在AMS中,进程的信息都保存在ProcessRecord数据结构中。
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); int uid = info.uid; if (isolated) { if (isolatedUid == 0) { 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; } } } else { // Special case for startIsolatedProcess (internal only), where // the uid of the isolated process is specified by the caller. uid = isolatedUid; } } final ProcessRecord r = new ProcessRecord(stats, info, proc, uid); if (!mBooted && !mBooting && userId == UserHandle.USER_OWNER && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { r.persistent = true; } addProcessNameLocked(r); return r; }
ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, String _processName, int _uid) { mBatteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid; uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode)); maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; persistent = false; removed = false; lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis(); }
ProcessRecord除保存和应用进程通信的IApplicationThread对象外,还保存了进程名、不同状态对应的Oom_adj值及一个ApplicationInfo。一个进程虽然可运行多个Application,但是ProcessRecord一般保存该进程中先运行的那个Application的ApplicationInfo。现在,创建了一个ProcessRecord对象,该对象对应的进程为system_server。
AMS的setSystemProcess的工作
1.注册AMS、meminfo、gfxinfo等服务到ServiceManager中
2.根据PKMS返回的ApplicationInfo初始化Android运行环境,并创建一个代表system_server进程的ProcessRecord,从此,system_server进程也并入AMS的管理范围内。
public final void installSystemProviders() { List<ProviderInfo> providers; synchronized (this) { ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID); providers = 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) { Slog.w(TAG, "Not installing system proc provider " + pi.name + ": not system .apk"); providers.remove(i); } } } } if (providers != null) { mSystemThread.installSystemProviders(providers); } mCoreSettingsObserver = new CoreSettingsObserver(this); //mUsageStatsService.monitorPackages(); }
private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) { List<ProviderInfo> providers = null; try { ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager(). queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS); providers = slice != null ? slice.getList() : null; } 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<N; i++) { ProviderInfo cpi = (ProviderInfo)providers.get(i); boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_OWNER) { // 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); 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, cpi.applicationInfo.versionCode, mProcessStats); } ensurePackageDexOpt(cpi.applicationInfo.packageName); } } return providers; }
public final void installSystemProviders() { List<ProviderInfo> providers; synchronized (this) { ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID); providers = 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) { Slog.w(TAG, "Not installing system proc provider " + pi.name + ": not system .apk"); providers.remove(i); } } } } if (providers != null) { mSystemThread.installSystemProviders(providers); } mCoreSettingsObserver = new CoreSettingsObserver(this); //mUsageStatsService.monitorPackages(); }
@Override public ParceledListSlice<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { ArrayList<ProviderInfo> finalList = null; // reader synchronized (mPackages) { final Iterator<PackageParser.Provider> 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 (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<ProviderInfo>(3); } ProviderInfo info = PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId); if (info != null) { finalList.add(info); } } } } if (finalList != null) { Collections.sort(finalList, mProviderInitOrderSorter); return new ParceledListSlice<ProviderInfo>(finalList); } return null; }
AMS保存ProviderInfo的原因是它要管理ContentProvider。ProcessRecord保存ProviderInfo的原因是ContentProvider最终要落实到一个进程中,其实也是为了方便AMS管理,例如该进程一旦退出,AMS需要把其中的ContentProvider信息从系统中去除。
AMS及ProcessRecord均使用了一个新的数据结构ContentProviderRecord来管理ContentProvider。
1.ContentProviderRecord从ContentProviderHolder派生,内部保存了ProviderInfo、该Provider所驻留的进程ProcessRecord,以及使用该ContentProvider的客户端进程ProcessRecord(即clients成员变量)
2.AMS的mProviderByClass成员变量及ProcessRecord的pubProviders成员变量均以ComponentName为key来保存对应的ContentProviderRecrod对象。
public final void installSystemProviders(List<ProviderInfo> providers) { if (providers != null) { installContentProviders(mInitialApplication, providers); } }
private void installContentProviders( Context context, List<ProviderInfo> providers) { final ArrayList<IActivityManager.ContentProviderHolder> results = new ArrayList<IActivityManager.ContentProviderHolder>(); for (ProviderInfo cpi : providers) { if (DEBUG_PROVIDER) { StringBuilder buf = new StringBuilder(128); buf.append("Pub "); buf.append(cpi.authority); buf.append(": "); buf.append(cpi.name); Log.i(TAG, buf.toString()); } IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { } }
installContentProviders实际上是标准的ContentProvider安装时调用的程序。安装ContentProvider包括两方面的工作
1.先在ActivityThread中通过installProvider得到一个ContentProvider实例
2.向AMS发布这个ContentProvider实例。如此这般,一个APK中声明的ContentProvider才能发挥其该有的作用。
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) { if (DEBUG_PROVIDER || noisy) { Slog.d(TAG, "Loading provider " + info.authority + ": " + info.name); } Context c = null; ApplicationInfo ai = info.applicationInfo; if (context.getPackageName().equals(ai.packageName)) { c = context; } else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) { c = mInitialApplication; } else { try { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { // Ignore } } if (c == null) { Slog.w(TAG, "Unable to get context for package " + ai.packageName + " while loading content provider " + info.name); return null; } try { final java.lang.ClassLoader cl = c.getClassLoader(); localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); if (provider == null) { Slog.e(TAG, "Failed to instantiate class " + info.name + " from sourceDir " + info.applicationInfo.sourceDir); return null; } if (DEBUG_PROVIDER) Slog.v( TAG, "Instantiating local provider " + info.name); // XXX Need to create the correct context for this provider. localProvider.attachInfo(c, info); } catch (java.lang.Exception e) { if (!mInstrumentation.onException(null, e)) { throw new RuntimeException( "Unable to get provider " + info.name + ": " + e.toString(), e); } return null; } } else { provider = holder.provider; if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": " + info.name); } IActivityManager.ContentProviderHolder retHolder; synchronized (mProviderMap) { if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider + " / " + info.name); IBinder jBinder = provider.asBinder(); if (localProvider != null) { ComponentName cname = new ComponentName(info.packageName, info.name); ProviderClientRecord pr = mLocalProvidersByName.get(cname); if (pr != null) { if (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, " + "using existing local provider"); } provider = pr.mProvider; } else { holder = new IActivityManager.ContentProviderHolder(info); holder.provider = provider; holder.noReleaseNeeded = true; pr = installProviderAuthoritiesLocked(provider, localProvider, holder); mLocalProviders.put(jBinder, pr); mLocalProvidersByName.put(cname, pr); } retHolder = pr.mHolder; } else { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { if (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, updating ref count"); } // We need to transfer our new reference to the existing // ref count, releasing the old one... but only if // release is needed (that is, it is not running in the // system process). if (!noReleaseNeeded) { incProviderRefLocked(prc, stable); try { ActivityManagerNative.getDefault().removeContentProvider( holder.connection, stable); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { ProviderClientRecord client = installProviderAuthoritiesLocked( provider, localProvider, holder); if (noReleaseNeeded) { prc = new ProviderRefCount(holder, client, 1000, 1000); } else { prc = stable ? new ProviderRefCount(holder, client, 1, 0) : new ProviderRefCount(holder, client, 0, 1); } mProviderRefCountMap.put(jBinder, prc); } retHolder = prc.holder; } } return retHolder; }
1.ContentProvider类本身只是一个容器,而跨进程调用的支持是通过内部类Transport实现。Transport从ContentProviderNative派生,而ContentProvider的成员变量mTransport指向Transport对象。ContentProvider的getIContentProvider函数即返回mTransport成员变量
2.ContentProviderNative从Binder派生,并实现了IContentProvider接口。其内部类ContentProviderProxy是供客户端使用的
3.ProviderClientRecord是ActivityThread提供的用于保存ContentProvider信息的一个数据结构。它的mLocalProvider用于保存ContentProvider对象,mProvider用于保存IContentProvider对象。另外一个成员mName用于保持该ContentProvider的一个authority。注意,ContentProvider可以定义多个authority,就好像一个网站有多个域名一样。
public final void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) { if (providers == null) { return; } enforceNotIsolatedCaller("publishContentProviders"); synchronized (this) { final ProcessRecord r = getRecordForAppLocked(caller); if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid); if (r == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when publishing content providers"); } final long origId = Binder.clearCallingIdentity(); final int N = providers.size(); for (int i=0; i<N; i++) { ContentProviderHolder src = providers.get(i); if (src =http://www.mamicode.com/= null || src.info == null || src.provider == null) { continue; } ContentProviderRecord dst = r.pubProviders.get(src.info.name); if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid); if (dst != null) { ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); mProviderMap.putProviderByClass(comp, dst); String names[] = dst.info.authority.split(";"); for (int j = 0; j < names.length; j++) { mProviderMap.putProviderByName(names[j], dst); } int NL = mLaunchingProviders.size(); int j; for (j=0; j<NL; j++) { if (mLaunchingProviders.get(j) == dst) { mLaunchingProviders.remove(j); j--; NL--; } } synchronized (dst) { dst.provider = src.provider; dst.proc = r; dst.notifyAll(); } updateOomAdjLocked(r); maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } } Binder.restoreCallingIdentity(origId); } }
瀑布lishContentProviders的工作流程
1.先根据调用者的PID找到对应的ProcessRecord对象
2.该ProcessRecord的pubProviders中保存了ContentProviderRecord信息。该信息由前面介绍的AMS的generateApplicationProvidersLocked函数根据Package本身的信息生成。此处将判断要发布的ContentProvider是否由该Package声明
3.如果判断返回成功,则将该ContentProvider及其对应的authority加到mProvidersByName中。注意,AMS中还有一个mProvidersByClass变量,该变量以ContentProvider的ComponentName为key,即系统提供两种方式找到某一个ContentProvider,一种是通过authority,另一种方式就是指明ComponentName。
4.mLaunchProviders和最后的notifyAll函数用于通知那些等待ContentProvider所在进程启动的客户端进程。例如,进程A要查询一个数据库,需要通过进程B中的某个ContentProvider来实施。如果B还未启动,那么AMS就需要先启动B。在这段时间内,A需要等待B启动并注册对应的ContentProvider。B一旦完成注册,就需要告知A退出等待以继续后续的查询工作。
public void systemReady(final Runnable goingCallback) { synchronized(this) { if (mSystemReady) { // If we‘re done calling all the receivers, run the next "boot phase" passed in // by the SystemServer if (goingCallback != null) { goingCallback.run(); } return; } mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); // Make sure we have the current profile info, since it is needed for // security checks. updateCurrentProfileIdsLocked(); mRecentTasks.clear(); mRecentTasks.addAll(mTaskPersister.restoreTasksLocked()); mRecentTasks.cleanupLocked(UserHandle.USER_ALL); mTaskPersister.startPersisting(); // Check to see if there are any update receivers to run. if (!mDidUpdate) { if (mWaitingUpdate) { return; } final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>(); mWaitingUpdate = deliverPreBootCompleted(new Runnable() { public void run() { synchronized (ActivityManagerService.this) { mDidUpdate = true; } showBootMessage(mContext.getText( R.string.android_upgrading_complete), false); writeLastDonePreBootReceivers(doneReceivers); systemReady(goingCallback); } }, doneReceivers, UserHandle.USER_OWNER); if (mWaitingUpdate) { return; } mDidUpdate = true; } mAppOpsService.systemReady(); mSystemReady = true; } ArrayList<ProcessRecord> 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<ProcessRecord>(); } 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(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"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis()); synchronized(this) { // Make sure we have no pre-ready processes sitting around. if (mFactoryTest == FactoryTest.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); mUiHandler.sendMessage(msg); } } } retrieveSettings(); loadResourcesOnSystemReady(); synchronized (this) { readGrantedUriPermissionsLocked(); } if (goingCallback != null) goingCallback.run(); mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, Integer.toString(mCurrentUserId), mCurrentUserId); mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(mCurrentUserId), mCurrentUserId); mSystemServiceManager.startUser(mCurrentUserId); synchronized (this) { if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { try { List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); if (apps != null) { int N = apps.size(); int i; for (i=0; i<N; i++) { ApplicationInfo info = (ApplicationInfo)apps.get(i); if (info != null && !info.packageName.equals("android")) { addAppLocked(info, false, null /* ABI override */); } } } } catch (RemoteException ex) { // pm is in same process, this will never happen. } } // Start up initial activity. mBooting = true; startHomeActivityLocked(mCurrentUserId, "systemReady"); try { if (AppGlobals.getPackageManager().hasSystemUidErrors()) { Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + " data partition or your device will be unstable."); mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); } } catch (RemoteException e) { } if (!Build.isBuildConsistent()) { Slog.e(TAG, "Build fingerprint is not consistent, warning user"); mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); } 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, null, 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, new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } catch (Throwable t) { Slog.wtf(TAG, "Failed sending first user broadcasts", t); } finally { Binder.restoreCallingIdentity(ident); } mStackSupervisor.resumeTopActivitiesLocked(); sendUserSwitchBroadcastsLocked(-1, mCurrentUserId); } }
systemReady三阶段的工作
1.第一阶段:发送并处理与PRE_BOOT_COMPLETED广播相关的事情
2.第二阶段:(1)杀死那些在AMS还未启动完毕就先启动的应用进程。注意,这些进程一定是APK所在的java进程,因为只有应用进程才会向AMS注册,而一般Native(例如mediaserver)进程是不会向AMS注册的
(2)从Setting数据库获取配置信息,目前只取4个配置参数,分别是debug_app(设置需要debug的app的名称)、wait_for_debugger(如果为1,则等待调试器,否则正常启动debug_app)、always_finish_activities(当一个activity不再有地方使用时,是否立即对它执行destroy)、font_scale(用于控制字体放大倍数,这是android4.0新增的功能)。以上配置项由Setting数据库的system表提供
3.第三阶段:(1)调用systemReady设置的回调对象goingCallback的run函数
(2)启动那些声明了persistent的APK
(3)启动桌面
启动Home桌面
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (mStackSupervisor.inResumeTopActivity) { // Don‘t even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; mService.updateSleepIfNeededLocked(); } result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result; }
boolean startHomeActivityLocked(int userId, String reason) { if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) { // We are running in factory test mode, but unable to find // the factory test app, so just sit around displaying the // error message and don‘t try to start anything. return false; } Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don‘t do this if the home app is currently being // instrumented. aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); if (app == null || app.instrumentationClass == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mStackSupervisor.startHomeActivity(intent, aInfo, reason); } } return true; }
AMS总结
1.main函数:创建AMS实例,其中最重要的工作是创建android运行环境,得到一个ActivityThread和Context对象
2.AMS的setSystemProcess函数:该函数注册AMS和meminfo等服务到ServiceManager中,另外,它为system_server创建了一个ProcessRecord对象。由于AMS是Java世界的进程管理及调度中心,要做到对java进程一视同仁,尽管system_server贵为系统进程,此时也不得不将其并入AMS的管理范围内
3.AMS的installSystemProviders函数:为system_server加载SettingProvider
4.AMS的systemReady函数:做系统启动完毕前最后一些扫尾工作。该函数调用完毕后,Home Activity将呈现在用户面前
@Override public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { enforceNotIsolatedCaller("startActivityAndWait"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivityAndWait", null); WaitResult res = new WaitResult(); // TODO: Switch to user app stacks here. mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, res, null, options, false, userId, null, null); return res; }
《深入理解Android2》读书笔记(四)