前言:之前 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());
ddm是Dalvik Debug Monitor缩写,
具体干嘛的不清楚,谁指点一下哦?
(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虽然是临时的,但是目的却很关键。
继续看,context是通过ContextImpl.createSystemContext(this);来创建的:
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的时候定义好了的。
讲完了Resources.getSystem,再来看一下context.init函数:
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。