簡書 編程之樂
轉載請注明原創出處,謝謝!
根據上篇文章- Launcher源碼淺析,我們知道點擊Launcher某個圖標后,會調用Launcher的startActivitySafely方法。
如下:
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
Bundle optsBundle = useLaunchAnimation ? getActivityLaunchOptions(v) : null;
// Prepare intent
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
intent.setSourceBounds(getViewBounds(v));
}
try {
// ================== begin ======================
startActivity(intent, optsBundle);
return true;
} catch (ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
return false;
}
Launcher最終調用了父類 Activity 的startActivity(Intent intent, @Nullable Bundle options)方法,startActivity又調用了startActivityForResult。
在startActivityForResult方法內,會調用Instrumentation的execStartActivity方法。
注: 這里的mInstrumentation是Launcher里面的。
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}
startActivityForResult里面調用了mInstrumentation.execStartActivity方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) { ... }
其中有個參數是mMainThread.getApplicationThread(),mMainThread是Activity類的成員變量(ActivityThread類型),mMainThread.getApplicationThread()獲取的是ApplicationThread類型,ApplicationThread則是ActivityThread的內部類,可以看出ApplicationThread是一個Binder對象。
為了后面研究的方便,有必要提前說明下即將出現的這幾個類的關系,它們分別是
- IApplicationThread
- ApplicationThread
- ApplicationThreadNative
- ApplicationThreadProxy
如果你查看過AIDL生成的文件,那么這幾個類就比較容易理解了,IApplicationThread相當于AIDL接口
class ApplicationThread extends ApplicationThreadNative {
// 因為ApplicationThreadNative繼承 Binder,且ApplicationThreadNative是抽象類,所以ApplicationThread才是真正的Binder實現。
}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
// Activity中常用到的那個獲取接口的方法如:ServiceConnection中 IMedia iMedia = IMedia.Stub.asInterface(binder);
static public IApplicationThread asInterface(IBinder obj) {
// 內部代理類
return new ApplicationThreadProxy(obj);
}
看下這個AIDL接口的部分定義,其中后面要用到。
public interface IApplicationThread extends IInterface {
void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, boolean dontReport) throws RemoteException;
void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)
throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
boolean notResumed, Configuration config) throws RemoteException;
void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
int resultCode, String data, Bundle extras, boolean sync,
int sendingUser, int processState) throws RemoteException;
void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,
IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) throws RemoteException;
注意
mMainThread在Launcher中,且mMainThread變量也是在Activity.attach()中綁定的。
目前我們使用到的某些變量如(mMainThread,mInstrumentation)都是Launcher中已經初始化好的,但我們現在分析的是Launcher啟動第三方Activity而不是Launcher本身,后面我們會再次遇到這些變量,這些變量的初始化和綁定過程會出現在新Activity的創建中,目前先不要對這些變量的由來疑惑!
Instrumentation 儀表盤
這個也是非常重要的一個類,大致對這個類有些了解,否則后面很難理解。
mInstrumentation是Activity的一個成員變量,且mInstrumentation是在Activity的 attach(xxx)方法里面賦值的,這個方法非常重要,里面還有mWindow = new PhoneWindow(this, window, activityConfigCallback);
等操作。后面會分析到此方法。
Instrumentation 儀表盤,命名就好像管理生命周期一樣,事實也差不多如此。
看下Instrumentation 的主要方法:
execStartActivity
callApplicationOnCreate
newActivity
callActivityOnCreate
callActivityOnDestroy
callActivityOnRestoreInstanceState
callActivityOnPostCreate
callActivityOnNewIntent
callActivityOnStart
callActivityOnRestart
callActivityOnResume
callActivityOnStop
callActivityOnSaveInstanceState
callActivityOnPause
callActivityOnUserLeaving
mInstrumentation.execStartActivity內部調用了ActivityManagerNative.getDefault().startActivity()方法。
如下:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// ...
IApplicationThread whoThread = (IApplicationThread) contextThread;
try {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
ActivityManagerNative.getDefault()是個什么東西,這就是前面為什么要提一下ApplicationThread的原因了,形式幾乎一樣。
同樣看下面幾個類:
- IActivityManager
- ActivityManagerService(AMS)
- ActivityManagerNative
- ActivityManagerProxy
和前面完全對應,AMS閃亮登場。
很明顯,AMS是真正Binder的實現類。
為了體現AMS的重要性和更好理解Binder,這里的主要部分的代碼多貼一些,我們發現和ApplicationThread形式幾乎一模一樣,而且IActivityManager就是AIDL的接口,而ActivityManagerNative 繼承自Binder 且是抽象的,真正的實現是AMS,那么AMS類在哪里呢?
ActivityManagerNative 有一個靜態的getDefault方法,根據類加載機制 ,類在調用static方法時候才會初始化,此時返回gDefault.get(); Singleton是Android的一個單例封裝類工具類,第一次調用get方法時候會通過create方法初始化AMS對象。
這個單例寫法很有意思,又GET一個技能。
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
IBinder b = ServiceManager.getService("activity");
這個Binder對象就是ActivityManagerService。
在線 ActivityManagerService.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
public IBinder asBinder() {
return this;
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
class ActivityManagerProxy implements IActivityManager {
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}
public IBinder asBinder()
{
return mRemote;
}
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
// ..............
// ..............
//
}
簡單看下 IActivityManager 接口的部分聲明:
public interface IActivityManager extends IInterface {
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int flags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
int userId) throws RemoteException;
public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options,
int userId) throws RemoteException;
public int startActivityWithConfig(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, Configuration newConfig,
Bundle options, int userId) throws RemoteException;
public int startActivityIntentSender(IApplicationThread caller,
IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues, Bundle options) throws RemoteException;
public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
Intent intent, String resolvedType, IVoiceInteractionSession session,
IVoiceInteractor interactor, int flags, ProfilerInfo profilerInfo, Bundle options,
int userId) throws RemoteException;
public boolean startNextMatchingActivity(IBinder callingActivity,
Intent intent, Bundle options) throws RemoteException;
public int startActivityFromRecents(int taskId, Bundle options)
throws RemoteException;
public boolean finishActivity(IBinder token, int code, Intent data, int finishTask)
throws RemoteException;
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
public boolean finishActivityAffinity(IBinder token) throws RemoteException;
public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException;
public boolean releaseActivityInstance(IBinder token) throws RemoteException;
public void releaseSomeActivities(IApplicationThread app) throws RemoteException;
public boolean willActivityBeVisible(IBinder token) throws RemoteException;
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter,
String requiredPermission, int userId) throws RemoteException;
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
public int broadcastIntent(IApplicationThread caller, Intent intent,
String resolvedType, IIntentReceiver resultTo, int resultCode,
String resultData, Bundle map, String[] requiredPermissions,
int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException;
public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
boolean abortBroadcast, int flags) throws RemoteException;
public void attachApplication(IApplicationThread app) throws RemoteException;
public void activityResumed(IBinder token) throws RemoteException;
我們接著上一步ActivityManagerNative.getDefault().startActivity()即
AMS(ActivityManagerService).startActivity();
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
AMS的startActivity方法調用了startActivityAsUser。
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
下面是一系列的調用關系
1. AMS.startActivityAsUser-> ActivityStarter.startActivityMayWait
2. ActivityStarter.startActivityMayWait -> ActivityStarter.startActivityLocked
3. ActivityStarter.startActivityLocked -> ActivityStarter.doPendingActivityLaunchesLocked
4. ActivityStarter.doPendingActivityLaunchesLocked -> ActivityStarter.startActivityUnchecked
5. ActivityStarter.startActivityUnchecked -> mSupervisor(ActivityStackSupervisor).resumeFocusedStackTopActivityLocked();
6. ActivityStackSupervisor.resumeFocusedStackTopActivityLocked->.targetStack(ActivityStack).resumeTopActivityUncheckedLocked
7. ActivityStack.resumeTopActivityUncheckedLocked -> ActivityStack.resumeTopActivityInnerLocked
8. ActivityStack.resumeTopActivityInnerLocked -> mStackSupervisor(ActivityStackSupervisor).startSpecificActivityLocked
9. ActivityStackSupervisor.startSpecificActivityLocked -> ActivityStackSupervisor.realStartActivityLocked
這段調用過程真是非常復雜,幾乎每個類或方法都是千百行,繞的我快暈了。
這些流程,會挑選著代碼講解,如果每個流程一下子把代碼貼出來,幾乎都會被搞瘋。
先看下最后一步:ActivityStackSupervisor.startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.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(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// mService是AMS
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
tips:
在 AMS中,每一個 Activity 組件都有一個用戶 ID 和一個進程名稱,其中,用戶 ID 是在安裝該 Activity 組件時由 PackageManagerService 分配的,而進程名稱則是由該 Activity 組件的 android:process屬性來決定的。
ActivityManagerService 在啟動一個 Activity 組件時,首先會以它的用戶 ID 和進程名稱來檢查系統中是否存在一個對應的應用程序進程。如果存在,就會直接通知這個應用程序進程將 Activity 組件啟動起來;否則,就會先以這個用戶 ID 和進程名稱來創建一個應用程序進程,然后在通知這個應用程序進程將該 Activity 組件啟動起來。
根據上面if語句的判斷:
(1). if (app != null && app.thread != null) { }
如果app已經啟動,則通過realStartActivityLocked()啟動Activity。
(2). 如果app還未啟動,則通過AMS創建應用進程。
上述代碼第一次啟動必定先運行(2)
查看ActivityManagerService類的 startProcessLocked()方法,注意startProcessLocked方法有多個重載
下面的方法調用app = newProcessRecordLocked,
最后又調用了另一個重載方法startProcessLocked。
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
if (!isolated) { // 傳入的 isolated 參數為 false ,if 成立,并不是隔離的進程
// 根據進程名稱和用戶 ID 得到應用程序進程,由于不存在,則為 null 。
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");
// 省略部分代碼
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}
// 當進程已經被分配的 PID 時,
if (app != null && app.pid > 0) {
}
// 應用程序進程不存在,創建新的進程
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
// 創建應用程序進程
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
}
app.crashHandler = crashHandler;
checkTime(startTime, "startProcess: done creating new process record");
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}
// 創建應用程序進程后,最終調用 startProcessLocked 方法
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
}
上面的startProcessLocked方法最后調用了下面這個startProcessLocked。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
// ................ 省略
checkTime(startTime, "startProcess: starting to update cpu stats");
updateCpuStats();
checkTime(startTime, "startProcess: done updating cpu stats");
try {
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
checkTime(startTime, "startProcess: done updating pids map");
} catch (RuntimeException e) {
}
}
可以看到上面調用了Process.start方法啟動一個進程。其中有這么一小段代碼,如下:
if (entryPoint == null) {
entryPoint = "android.app.ActivityThread";
}
Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName,....);
Process.start()方法的第一個參數是 entryPoint 指明入口類是ActivityThread(雖然名字是XXThread,但其實是個普通類),而Java的入口一般都是main方法,那么ActivityThread 的 main 方法將在這里啟動。
ActivityThread.main方法并不復雜,來看下它大致干些什么。
public final class ActivityThread {
final Looper mLooper = Looper.myLooper();
final H mH = new H();
final ApplicationThread mAppThread = new ApplicationThread();
private static volatile ActivityThread sCurrentActivityThread;
Instrumentation mInstrumentation;
static volatile Handler sMainThreadHandler;
public static void main(String[] args) {
// 初始化主線程的消息隊列
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 開啟消息循環
Looper.loop();
}
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) { // 是否為系統進程
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
}
} else {
// 省略系統進程代碼
}
// 省略 ViewRootImpl 相關代碼
}
}
// AMS的 attachApplication方法
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
- Looper.prepareMainLooper();準備循環主線程。
- 創建一個 ActivityThread 對象并attach();
最終sCurrentActivityThread = this; // 當前靜態sCurrentActivityThread
AMS.attachApplication(mAppThread);// mAppThread是ApplicationThread - 調用Looper.loop();使主線程中消息循環
AMS.attachApplication(mAppThread);中又調用了AMS的attachApplicationLocked,查看該方法:
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
ProcessRecord app;
// 移除超時消息,應用程序在規定時間內完成了啟動。
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
try{
// 序號1. ************************** IPC 調用 ActivityThread,綁定并創建Application **************************
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
}catch(Exception e){
//
}
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
// 序號2. ************************** 調度 Activity **************************
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
// Find any services that should be running in this process...
// 序號3 ************************** 調度 Service **************************
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
// 序號4 ************************** 調度 Broadcast **************************
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
badApp = true;
}
}
}
這個地方代碼很多,需要特別注意:
下面把這幾個步驟分為幾個序號:
- thread.bindApplication啟動Application
- 啟動Activity
- 啟動Service
- 啟動Broadcast
每個序號里面都執行跳轉多次,一個序號一個序號來說,否則容易犯迷糊。
AMS.attachApplication(mAppThread) 序號一
先看 thread.bindApplication,這是一個IPC通信,thread是IApplicationThread 接口,最終調用的方法是服務端真正的Binder對象即 ApplicationThread.bindApplication()
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
// delete the fucking code ...................
sendMessage(H.BIND_APPLICATION, data);
}
可以看到該方法發送一條H.BIND_APPLICATION消息交給handler處理。
我們看下這個Handler,在ActivityThread的內部。
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
} break;
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
break;
case RELAUNCH_ACTIVITY: {
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
} break;
case PAUSE_ACTIVITY: {
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
maybeSnapshot();
} break;
case PAUSE_ACTIVITY_FINISHING: {
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
} break;
// .................. delete
}
根據消息case BIND_APPLICATION:
將執行ActivityThread.handleBindApplication(data);方法。
private void handleBindApplication(AppBindData data) {
// 設置進程名
Process.setArgV0(data.processName);
// 創建 Android 運行環境 ContextImpl .
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
// 初始化 Intrumentation 對象
if (data.instrumentationName != null) {
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
}
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);
} else {
mInstrumentation = new Instrumentation();
}
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
// 創建 Application 對象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
}
try {
// 執行 Application 的 onCreate 方法
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
} finally {
}
}
AMS.attachApplication(mAppThread) 序號二
序號二調用了mStackSupervisor(ActivityStackSupervisor).attachApplicationLocked(app)方法:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
該方法遍歷 ActivityStack 和 TaskRecord,找到位于 Activity 堆棧頂端的一個 ActivityRecord 對象 hr,接著檢查這個 Activity 組件的用戶 ID 和 進程名是否與 ProcessRecord 對象 app 所描述的應用程序的用戶 ID 和進程名一致,如果一致,則調用 StackSupervisor.realStartActivityLocked方法來請求該應用程序進程啟動一個 Activity 組件。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
// .... 刪 刪 刪 刪 刪 刪 刪 刪 fuck
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}
StackSupervisor.realStartActivityLocked方法內部調用了app.thread.scheduleLaunchActivity()方法,其中thread是ApplicationThread類型,binder對象。
ApplicationThread.scheduleLaunchActivity方法如下:
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
// .......... delete code
sendMessage(H.LAUNCH_ACTIVITY, r);
}
scheduleLaunchActivity里面同樣是發送了一條handler消息。
根據上面handleMessage處理的消息類型,將執行
ActivityThread.handleLaunchActivity()方法。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
}
}
分別調用:
- performLaunchActivity將 Activity 組件啟動起來
- handleResumeActivity方法將 Activity 組件的狀態設置為 Resumed。
下面只講Activity a = performLaunchActivity(r, customIntent);
就可以了,handleResumeActivity設置Resumed就沒有什么必要說了。
ActivityThread.performLaunchActivity是個重重重要的方法 ,我們最前面提到某些 重要角色對象 的設置都是在這個方法里面初始化的。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 獲取ActivityInfo信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
// 獲取要啟動的Activity的組件信息
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
// 根據相關信息構建組件對象
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
// 通過反射 新建一個 Activity 對象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
// 這個地方我稍有疑惑,因為根據前面的邏輯 BIND_APPLICATION消息[app == null情況下]->handleApplication()中
// 已經使用LoadedApk.makeApplication()生成一個Application對象了,這里在case LAUNCHER_ACTIVITY又調用一遍。
// 不過LoadedApk.makeApplication有判斷null處理,所以只會返回一個Application對象啦!
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
// 創建 Activity的 ContextImpl ,作為 Activity 的運行上下文環境
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
// 構造Configuration對象
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
// ============= Window對象
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// ******** 重要 : activity.attach(),我最前面提到的這個方法,把上面這些重要對象都設置為activity的成員變量。********
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
// 設置主題
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
// 根據是否需要持久化調用此方法通知Activity已被創建和啟動
// 回調 Activity 的 onCreate 函數
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
// 回調 Activity 的 onStart 函數
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
// Activity 的 onRestoreInstanceState 函數
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
// 返回創建并初始化過的activity對象
return activity;
}
終于講完了序號1和序號2,這里的序號1和序號2指的是下圖這幾個步驟的前2個:
講了這么多,AMS.attachApplication這個方法還沒執行完,我了個去,累死了!寫的最累的一篇博客了。
時序圖實在懶得畫了,畫這個圖估計也夠嗆,這篇文章篇幅雖然和其他分析AMS的文章比起來算是短些了,因為很多文章幾乎把源碼全部都貼上了,我看著都暈,單單
AMS.startActivityAsUser->ActivityStackSupervisor.realStartActivityLocked
那9步就夠你貼上十幾頁了,那一部分確實跳來跳去搞得人眼花繚亂,而且每段代碼都是千百行,但是最重要的確是最后那兩步,所以我把該省略的跳轉代碼都省掉了,如果具體研究某個步驟就比較容易了,有興趣的可以查找9步中的某一段代碼進行具體分析。花了整整3天時間,如果你喜歡,請點一個贊!nnd......Fuck the code!!!
小結
從上面的執行流程:我們發現Application會創建一個appContext,一個Activity會創建一個Context,(一個Service也會創建一個Context),那么一個應用中 Context的總數 = Activity對象數 + Service對象數 + 1個Application對象
。四大組件中的BroadcastReciver和ContentProvider的Context都是直接或間接來自于 Application,Activity,Service。
最后找來自己參考過的一種博主畫的圖,和我的流程差不多,盜圖一張!
相關補充說明
ActivityStack :Android 中的 Activity 組件堆棧信息,也就是 Task。
ActivityStackSupervisor:管理ActivityStack的類。
參考
Android開發藝術探索
Android源碼設計模式
Android 7.0 源碼
Activity啟動過程分析(從Launcher啟動)
Android 6.0 Launcher 啟動 Activity 過程源碼分析(二)