文章出处:http://blog.csdn.net/shift_wwx
前言:之前 android SystemServer详解分析了一下systemserver的启动过程,虽然分析下来很多繁琐,可是systemserver却是android启动的第一步,很多service都是在这个进程中启动,这些才是组成android的关键,AMS可以说是android应用的最关键的一个service,传说中的android四大组件就是用它来控制的。我根据源码做一些分析,不足应该很多,希望大神能多指点。
AMS最开始涉及到是在systemserver中:
context = ActivityManagerService.main(factoryTest);
public static final Context main(int factoryTest) { AThread thr = new AThread();//创建一个Looper,实例化AMS thr.start(); synchronized (thr) { while (thr.mService == null) {//等待AMS实例化完成 try { thr.wait(); } catch (InterruptedException e) { } } } ActivityManagerService m = thr.mService;//mSelf就是实例化的AMS mSelf = m; ActivityThread at = ActivityThread.systemMain();//实例化ActivityThread mSystemThread = at; Context context = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface()); m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);//activity堆栈管理类 m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); m.mAppOpsService.publish(context); synchronized (thr) {//mSelf初始化成功后,就可以让AThread中Looper loop起来 thr.mReady = true; thr.notifyAll(); } m.startRunning(null, null, null, null);//调用startRuuning return context; }注意code中的注释。
1)AThread
static class AThread extends Thread { ActivityManagerService mService; Looper mLooper; boolean mReady = false; public AThread() { super("ActivityManager"); } @Override public void run() { Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); ActivityManagerService m = new ActivityManagerService(); synchronized (this) { mService = m; mLooper = Looper.myLooper(); Watchdog.getInstance().addThread(new Handler(mLooper), getName()); notifyAll(); } synchronized (this) { while (!mReady) { try { wait(); } catch (InterruptedException e) { } } } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper"); } Looper.loop(); } }
这个是AMS中的static class,为AMS创建了一个thread,区别去system_server进程的main thread,然后为AMS创建一个Looper,然后调用Looper.loop(); 另一个目的是实例化一个AMS。
private ActivityManagerService() { Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this); File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); systemDir.mkdirs(); ...... }构造函数就不详细的列出来,可以看一下AMS.java的source code。
一些变量需要注意,mBroadcastQueues(mFgBroadcastQueue、mBgBroadcastQueue)、mServices、mProviderMap四大组件三个在这里出现了,另外一个后期介绍。另外还有其他变量,mBatteryStatsService、mProcessStats、mUsageStatsService、mAppOpsService、mGrantFile、mStartedUsers、mCompatModePackages、mProcessCpuThread等等。
从code看,是在/data/system/下,创建了一些文件来管理android系统一些状态,例如batterystats.bin就是电池状态,接着procstats管理进程的,appops.xml就是app 权限相关的等等,后期会做详细的分析。
2)通过上面分析AThread后mSelf = m;
mSelf是static类型的,下面要讲到的mSystemThread也是static。
3)ActivityThread.systemMain()
public static ActivityThread systemMain() { HardwareRenderer.disable(true);//初始化hardwareRenderer ActivityThread thread = new ActivityThread();//引入ResourceManager thread.attach(true); return thread; }
主要是ActivityThread.attach():
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()); IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } } 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 = 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) { } }); }(1)android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId());
(2)Instrumentation类
(3)context
context第一次真正出现应该就是这里了:
ContextImpl context = new ContextImpl(); context.init(getSystemContext().mPackageInfo, null, this);
虽然这里的context只是函数内局部变量,可是真正做的事情却很多。
先来看getSystemContext():
public ContextImpl getSystemContext() { synchronized (this) { if (mSystemContext == null) { ContextImpl context = ContextImpl.createSystemContext(this); LoadedApk info = new LoadedApk(this, "android", context, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO); context.init(info, null, this); context.getResources().updateConfiguration(mResourcesManager.getConfiguration(), mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY)); mSystemContext = context; //Slog.i(TAG, "Created system resources " + context.getResources() // + ": " + context.getResources().getConfiguration()); } } return mSystemContext; }这里主要的目的是创建mSystemContext:
static ContextImpl mSystemContext = null;这可是系统一直用到的,所以上面提到的context虽然是临时的,但是目的却很关键。
static ContextImpl createSystemContext(ActivityThread mainThread) { final ContextImpl context = new ContextImpl(); context.init(Resources.getSystem(), mainThread, Process.myUserHandle()); return context; }需要说明一下Resources.getSytem():
public static Resources getSystem() { synchronized (sSync) { Resources ret = mSystem; if (ret == null) { ret = new Resources(); mSystem = ret; } return ret; } }还记得 android zygote之启动过程分析中提到的zygoteInit.main?其中有个preload();而随后 android 系统资源的加载和获取解析了过程,其中最关键的就是:
mResources = Resources.getSystem();而这个mSystem是个static,所以这里ret在zygote的时候就注定了以后不会再为null了。包括Resources的构造函数中的mAssets也是static类型,这也是再zygote的时候定义好了的。
final void init(Resources resources, ActivityThread mainThread, UserHandle user) { mPackageInfo = null; mBasePackageName = null; mOpPackageName = null; mResources = resources; mMainThread = mainThread; mContentResolver = new ApplicationContentResolver(this, mainThread, user); mUser = user; }作为systemcontext,这个时候mPackageInfo 等还是null,返回ActivityThread中继续看一下getSystemContext,讲完了createSystemContext,继续看一下一直会看到的packageInfo,这个对象的类型是LoadedApk:
LoadedApk info = new LoadedApk(this, "android", context, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);LoadedApk是加载apk的相关类,详细的code不贴了,可以看到LoadedApk有两个构造函数,一个是针对普通apk的, 另一个是针对systemcontext的。这里的构造函数目的是创建了ApplicationInfo,还有就是mClassLoader、mResources等,不过注意mApplicationInfo.packageName、mPackageName都是等于“android”。注意这个LoadedApk构造函数,包括这个“android”等会有介绍到。
LoadedApk创建玩之后会再一次调用context.init:
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) { init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle()); } final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread, Resources container, String basePackageName, UserHandle user) { mPackageInfo = packageInfo; if (basePackageName != null) { mBasePackageName = mOpPackageName = basePackageName; } else { mBasePackageName = packageInfo.mPackageName; ApplicationInfo ainfo = packageInfo.getApplicationInfo(); if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) { // Special case: system components allow themselves to be loaded in to other // processes. For purposes of app ops, we must then consider the context as // belonging to the package of this process, not the system itself, otherwise // the package+uid verifications in app ops will fail. mOpPackageName = ActivityThread.currentPackageName(); } else { mOpPackageName = mBasePackageName; } } mResources = mPackageInfo.getResources(mainThread); mResourcesManager = ResourcesManager.getInstance(); CompatibilityInfo compatInfo = container == null ? null : container.getCompatibilityInfo(); if (mResources != null && ((compatInfo != null && compatInfo.applicationScale != mResources.getCompatibilityInfo().applicationScale) || activityToken != null)) { if (DEBUG) { Log.d(TAG, "loaded context has different scaling. Using container's" + " compatiblity info:" + container.getDisplayMetrics()); } if (compatInfo == null) { compatInfo = packageInfo.getCompatibilityInfo(); } mDisplayAdjustments.setCompatibilityInfo(compatInfo); mDisplayAdjustments.setActivityToken(activityToken); mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(), Display.DEFAULT_DISPLAY, null, compatInfo, activityToken); } else { mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo()); mDisplayAdjustments.setActivityToken(activityToken); } mMainThread = mainThread; mActivityToken = activityToken; mContentResolver = new ApplicationContentResolver(this, mainThread, user); mUser = user; }这里应该是进一步的初始化mSystemContext了,之前的init说过,mPackageInfo等都是null,这里就详细的赋值了。mPackageInfo就是之前创建的LoadedApk,mBasePackageName、mOpPackageName都是之前创建LoadedApk传进来的“android”,mResources、mResourcesManager不用多说了,之前都介绍过了。
到这里这个ActivityThread 中这个static mSystemContext就完全创建ok了。
回到最开始,这里context是真正第一次出现,这里发现context.init跟getSystemContext中的context.init重复了,不知道google当初是怎么想的。
(4)创建application对象app
Application app = Instrumentation.newApplication(Application.class, context); mAllApplications.add(app); mInitialApplication = app; app.onCreate();
这里具体的没有明白?
刚开始我也不太清楚,整个过程到底是干什么?显示实例化一个局部的context变量,而不是全局的,利用这个context只是做一个init,在init的时候会传入LoadedApk,这个应该是apk的所有相关信息的集合,为什么会在这里体现出来,而且LoadedApk构造的时候传入了一个package name是android,直到我看到一个东西,才完全明白这个ActivityThread 中attach函数的真正目的:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android" coreApp="true" android:sharedUserId="android.uid.system" android:sharedUserLabel="@string/android_system_label">上面这段code是AndroidManifest.xml中部分,package name是 ---> android,这下就解释通了。这里创建的Application 就是这个应用了,可以看出一个ActivityThread可以运行多个application,这里的application指的是android,而且,这个android 应用被设置为mInitialApplication。
在回头看一下LoadedApk的构造函数:
public LoadedApk(ActivityThread activityThread, String name, Context systemContext, ApplicationInfo info, CompatibilityInfo compatInfo) { mActivityThread = activityThread; mApplicationInfo = info != null ? info : new ApplicationInfo(); mApplicationInfo.packageName = name; mPackageName = name; mAppDir = null; mResDir = null; mSharedLibraries = null; mDataDir = null; mDataDirFile = null; mLibDir = null; mBaseClassLoader = null; mSecurityViolation = false; mIncludeCode = true; mClassLoader = systemContext.getClassLoader(); mResources = systemContext.getResources(); mDisplayAdjustments.setCompatibilityInfo(compatInfo); }就是创建了android 这个application,实例化了一个ApplicationInfo,指定了mApplicationInfo.packageName,mPackageName都为android。最关键的是mClassLoader、mResources、mDisplayAdjustments。
说了半天这个android应用,也提出了他的AndroidManifest.xml,那么这个android应用到底是什么呢?bingo,就是framework-res.apk。
(5)DropBox.setReporter(new DropBoxReporter());
(6)ViewRootImpl.addConfigCallback(new ComponentCallbacks2(){});
向ViewRootImpl注册一个callback用于接收ConfigurationChanged事件(例如横竖屏切换、输入法弹出等),我们将在介绍WindowsManager的时候来分析如果dispatch这些事件到具体的activity当中。
4)通过ActivityThread分析后mSystemThread = at;这里的mSystemThread同mSelf,都是static
5)初始化AMS的mContext、mFactoryTest、mIntentFirewall、mStackSupervisor
Context context = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface()); m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); m.mAppOpsService.publish(context);
主要创建IntentFirewall,而IntentFirewall从/data/system/ifw/ifw.xml or /data/secure/system/ifw/ifw.xml读取出来activity,broadcast,service,并时刻监听着文件是否改变 ,而IntentFirewallInterface则是看是否是ActivityManagerService的进程id。而下面BatteryStatsService,UsageStatsService,AppOpsService.则是把服务注册掉binder manager。
6)m.startRunning(null, null, null, null);
public final void startRunning(String pkg, String cls, String action, String data) { synchronized(this) { if (mStartRunning) { return; } mStartRunning = true; mTopComponent = pkg != null && cls != null ? new ComponentName(pkg, cls) : null; mTopAction = action != null ? action : Intent.ACTION_MAIN; mTopData = data; if (!mSystemReady) { return; } } systemReady(null); }
因为进入startRunning时mStartRunning和mSystemReady都为false,所以这里只是设置mStartRunning为true,mTopComponent为null,mTopAction为Intent.ACTION_MAIN,mTopData为null就直接返回。
到这里ActivityManagerService.main就全部解析完成。
总结一下:
main中的AThread中创建了一个looper,然后实例化了一个AMS,也就是mSelf;接着实例化了一个static 的ActivityThread,也就是mSystemThread,在ActivityThread中实例化了Application,即framework-res.apk;接着就是一些设置,如mContext、mFactoryTest、mIntentFirewall、mStackSupervisor、mBatteryStatsService、mUsageStatsService、mAppOpsService;startRunning。