Framework代碼雖然沒有讀過,但是相關的文章看過很多,各方大牛閱讀的姿勢也了解了不少,可到自己開始學習時還是有無從下手的感覺。
Binder應該是看過的博客中提到最多次的概念了,然而現在我除了知道它是用來搞進程間通訊的之外,其它的就一無所知了,也不知道它對開發一個App有什么樣的作用,想從它下手是不可能了。想來想去,還是對App最為熟悉,所以就先搞清楚一個APP從啟動到運行的整個流程吧。
Android系統開機解鎖后,就會進入桌面,不過這個桌面也是一個APP,它的名字叫Launcher,我們的應用就是通過點擊這里的一個圖標打開的。它的源碼位于/packages/apps/目錄,這里存放的是一些系統應用,像電話、短信等。以下是這個目錄的截圖:
可以看到其中Launcher程序有兩個:Launcher2和Launcher3,前者是從Android2.2開始使用的,直到Android4.4之后換成了后者。Launcher的具體實現并不是關注的重點,我們只是想知道從這里是如何啟動其他APP的。通過其AndroidManifest.xml可以找到它的主頁面是com.android.launcher3.Launcher,這是一個Activity,我在這里找到了點擊應用圖標打開APP的入口代碼:
/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
return;
}
...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {
...
} else if (v == mAllAppsButton) {
...
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {
...
}
}
這里Launcher#startAppShortcutOrInfoActivity(View)就是我們要找的代碼,它的主要實現如下:
void startAppShortcutOrInfoActivity(View v) {
Object tag = v.getTag();
final ShortcutInfo shortcut;
final Intent intent;
if (tag instanceof ShortcutInfo) {
shortcut = (ShortcutInfo) tag;
intent = shortcut.intent;
...
} else if (tag instanceof AppInfo) {
shortcut = null;
intent = ((AppInfo) tag).intent;
} else {
throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
}
boolean success = startActivitySafely(v, intent, tag);
mStats.recordLaunch(v, intent, shortcut);
...
}
首先通過Tag獲取到了Intent,然后調用了Launcher#startActivitySafely(View, Intent, Object)方法,如下所示:
public boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
...
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
...
}
return success;
}
繼續跳轉到Launcher#startActivity(View, Intent, Object),它主要處理了一下啟動的動畫,以及對用戶的管理,代碼如下:
private boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
...
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
UserManagerCompat userManager = UserManagerCompat.getInstance(this);
UserHandleCompat user = null;
if (intent.hasExtra(AppInfo.EXTRA_PROFILE)) {
long serialNumber = intent.getLongExtra(AppInfo.EXTRA_PROFILE, -1);
user = userManager.getUserForSerialNumber(serialNumber);
}
...
// 如果user為空,或者user是Launcher所在的用戶
if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);
} else {
// TODO Component can be null when shortcuts are supported for secondary user
launcherApps.startActivityForProfile(intent.getComponent(), user,
intent.getSourceBounds(), optsBundle);
}
return true;
} catch (SecurityException e) {
...
}
return false;
}
這里給Intent增加了一個Intent.FLAG_ACTIVITY_NEW_TASK的flag,然后調用了Activity#startActivity(Intent, Bundle)方法,這時我們就脫離了Launcher進入了Framework層面。代碼如下:
/frameworks/base/core/java/android/app/Activity.java
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
這里if-else最終都會調用Activity#startActivityForResult(Intent, int, Bundle),代碼如下:
/**
* Launch an activity for which you would like a result when it finished.
* When this activity exits, your
* onActivityResult() method will be called with the given requestCode.
* Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
*
* <p>Note that this method should only be used with Intent protocols
* that are defined to return a result. In other protocols (such as
* {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
* not get the result when you expect. For example, if the activity you
* are launching uses the singleTask launch mode, it will not run in your
* task and thus you will immediately receive a cancel result.
*
* <p>As a special case, if you call startActivityForResult() with a requestCode
* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
* activity, then your window will not be displayed until a result is
* returned back from the started activity. This is to avoid visible
* flickering when redirecting to another activity.
*
* ...
*/
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
...
}
}
這里看到一個叫做mInstrumentation的成員變量,并調用了它的execStartActivity方法,還有一個mMainThread變量,這應該就是APP的主線程,這兩個變量在哪里實例化的呢?我在Activity里找到了如下方法:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
...
mMainThread = aThread;
mInstrumentation = instr;
...
}
可以看到,這幾個變量是傳進來的,但是在Activity中沒有任何地方調用到這段代碼,所以它的實例化一定是在別的類中完成的。這里就先留下一個懸念,我們還是應該先順著代碼去研究,跳來跳去不一會兒就糊涂了,我相信在后續一定會找到答案。
Activity#startActivityForResult(Intent, int, Bundle)返回了一個Instrumentation.ActivityResult實例,并調用了ActivityThread#sendActivityResult方法,不過這里沒有要獲取返回值,所以這句代碼應該不會執行,我們以后再分析它。現在,我們先看這個Instrumentation#execStartActivity做了什么,在Instrumentation類中,這個函數有兩個,其中一個在注釋中說了是用來讓Fragment調用的,這里不要跟錯了。正確跳轉的代碼如下:
/frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
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;
}
這里的mActivityMonitors變量是在Instrumentation中維護的一個列表,就是來記錄的,如果之前請求過,就會被記錄到這里,如果monitor阻塞了,也就是想打開的Activity無法啟動,就會直接返回。真正的啟動在下邊的try-catch中,這里先看下這個ActivityManagerNative#getDefault()又是什么:
/frameworks/base/core/java/android/app/ActivityManagerNative.java
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
...
IActivityManager am = asInterface(b);
...
return am;
}
};
這里看到了IBinder,這么快就遇到了Binder,剛剛還說對它毫無所知呢。繼續跟進:
/frameworks/base/core/java/android/os/ServiceManager.java
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
可以看到這個ServiceManager和我們寫xxxManager一樣,就是方便調用和管理實例的,這個sServiceManager的實例化又是通過ServiceManagerNative完成,這里asInterface的參數通過BinderInternal.getContextObject()給出,它是一個native方法,代碼如下:
/frameworks/base/core/java/com/android/internal/os/BinderInternal.java
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
不過這里代碼就走到Native了,我們還是先停下,Native的代碼后續再研究,它的作用是用來獲取Service的。看下這個ServiceManagerNative#asInterface(IBinder)方法:
/frameworks/base/core/java/android/os/ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj)
{
...
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);
也就是說,這里獲取到的對象是ServiceManagerProxy,然后調用了它的ServiceManagerProxy#getService方法,代碼如下:
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
這里mRemote是Native傳過來的,我們暫時不跟蹤,經調試后發現這里獲取到的IBinder實例是BinderProxy。也就是說通過ServiceManager.getService("activity")得到的就是BinderProxy,然后回到ActivityManagerNative#gDetault繼續向下看,看到調用了ActivityManagerNative#asInterface方法,實現如下:
/frameworks/base/core/java/android/app/ActivityManagerNative.java
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);
}
和在ServiceManagerNative里的方法類似,這里返回了一個ServiceManagerProxy實例,也就是說通過ActivityManagerNative#getDefault()獲取到的實例就是ActivityManagerProxy,而它的mRemote是BinderProxy。
由此可見,作為客戶端的我們,要與作為服務端的ActivityManagerService通信,都是通過Proxy代理完成的,真正的數據處理在Native層。接下來看它的ActivityManagerProxy#startActivity方法:
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;
}
首先通過Parcel封裝了一些數據,然后通過mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)方法將數據發送出去,這個mRemote就是BinderProxy了,代碼如下:
/frameworks/base/core/java/android/os/Binder.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
return transactNative(code, data, reply, flags);
}
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
這里又到了Native層,在Java層已經無法繼續調試了,不過最終會調用到ActivityManagerService#onTransact,代碼如下:
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
if (code == SYSPROPS_TRANSACTION) {
...
}
try {
return super.onTransact(code, data, reply, flags);
} catch (RuntimeException e) {
// The activity manager only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
Slog.wtf(TAG, "Activity Manager Crash", e);
}
throw e;
}
}
發現這里處理的code值和之前傳入的START_ACTIVITY_TRANSACTION并不一致,這一過程交給了父類ActivityManagerNative完成,代碼如下:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
...
}
return super.onTransact(code, data, reply, flags);
}
ActivityManagerNative的這個方法非常長,有接近3000行代碼,全部是case XXX。稍微吐槽一下哈,寫這么多case不累嗎?接下來調用了ActivityManagerService#startActivity方法,代碼如下:
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
// 確保用戶沒有被隔離
enforceNotIsolatedCaller("startActivity");
// 拿到用戶的userId
userId = 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);
}
mActivityStarter是在ActivityManagerService實例化時就被初始化了,這里調用了它的startActivityMayWait方法,代碼如下:
/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
synchronized (mService) {
...
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
...
return res;
}
}
下面又走到了startActivityLocked,代碼如下:
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
...
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
...
try {
mService.mWindowManager.deferSurfaceLayout();
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
從Activity一直傳過來的IApplicationThread實例現在轉換到了ActivityRecord實例里,接下來是startActivityUnchecked,代碼如下:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
...
// 處理和ActivityStack相關的操作
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
...
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
...
} else {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
...
return START_SUCCESS;
}
mSupervisor是在ActivityStarter實例化時傳入進來的,實例化是在ActivityManagerService中完成。繼續跟蹤代碼:
/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...
return false;
}
接下來終于是啟動Activity了,代碼如下:
/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
try {
...
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// We need to start pausing the current activity so the top one can be resumed...
final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
// 在這里,把所有其他的Activity都Pause掉
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
...
// 進程已經被創建會走這里
if (next.app != null && next.app.thread != null) {
...
} else {
// Whoops, need to restart this activity!
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
這里看到啟動新Activity前,會先將原有的Activity pause掉,這樣做可以釋放很多資源。啟動Activity的工作交給了mStackSupervisor來處理,如下所示:
/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
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);
// 只有app已經創建好之后才會走這個if
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);
}
//啟動Activity,注意return,將不會執行最后一句
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.
}
// APP還未創建才會走到這里,通過AMS開啟進程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
這里如果APP已經創建好會直接走realStartActivityLocked方法,不過開啟進程之后應該也會走這個方法,這里先看下是如何開啟進程的:
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
這里startProcessLocked調用了多次重載方法,最終會走到這里,如下所示:
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
boolean isActivityProcess = (entryPoint == null);
...
// 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!");
...
}
可以看到是通過Process#start方法創建了需要的進程,該方法如下所示:
/frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
...
}
}
這里看到了Zygote的身影,這個單詞的意思是受精卵,我們的APP進程都是通過它孵化而來的,接下來的代碼如下:
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
...
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
傳遞了一堆參數,然后通過Socket與Zygote通信,代碼如下:
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
通過Socket,等待Zygote孵化完畢后,返回進程的pid,我們看看Zygote這邊做了什么,發送的Socket連接請求會在ZygoteInit中接收,在上方代碼的注釋里有說明,以下是ZygoteInit的main方法:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
try {
...
registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
...
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
...
}
}
Socket連接就是在runSelectLoop中完成的,代碼如下:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
...
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
當有一個連接時,就會執行else語句,調用ZygoteConnection#runOnce()方法,代碼如下:
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
...
int pid = -1;
...
try {
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (ErrnoException ex) {
...
}
...
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
...
}
}
這里當返回pid為0時,表示是在孵化出來的進程中,然后會執行handleChildProc,我們先看Zygote孵化相關的代碼,如下所示:
/frameworks/base/core/java/com/android/internal/os/Zygote.java
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
...
return pid;
}
這里nativeForkAndSpecialize就是在底層進行真正的孵化操作,因為暫時不追蹤Native代碼,這里到此先停止。接下來看這ZygoteConnection#handleChildProc做了什么,代碼如下:
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
...
closeSocket();
ZygoteInit.closeServerSocket();
...
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
接下來調用到了RuntimeInit#zygoteInit方法,代碼如下:
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
nativeZygoteInit(); // native
applicationInit(targetSdkVersion, argv, classLoader);
}
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
...
}
...
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
下面就是調用main方法了,代碼如下:
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
...
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
...
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
這里注釋說會在ZygoteInit#main()方法中捕獲異常,代碼如下:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
try {
...
registerZygoteSocket(socketName);
...
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
...
}
}
這個方法是在前面先調用的,所以如果拋出MethodAndArgsCaller異常,就會在這里被catch,然后執行它的run方法,代碼如下:
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
...
}
}
至此,要執行的main方法就被invoke成功了。那這個main方法是哪個類的呢?我們需要反向查看之前的代碼,在RuntimeInit#invokeStaticMain方法中傳入的第一個參數就是className,而這個參數是通過args.startClass獲取的,相應的代碼在RuntimeInit#applicationInit中。這個args是把傳進來的String[] argv轉成了Arguments變量,我們看下這個Arguments,它是RuntimeInit的內部類,代碼如下:
Arguments(String args[]) throws IllegalArgumentException {
parseArgs(args);
}
/**
* Parses the commandline arguments intended for the Runtime.
*/
private void parseArgs(String args[])
throws IllegalArgumentException {
int curArg = 0;
for (; curArg < args.length; curArg++) {
String arg = args[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
}
}
if (curArg == args.length) {
throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
}
startClass = args[curArg++];
startArgs = new String[args.length - curArg];
System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
}
可以看到startClass是args里最后一個值。那么這個args又是從哪里來的呢?還記得在Process#startViaZygote方法里,創建了一堆參數嗎?當時沒有細細研究,現在回過頭來看,在賦值了一些--xxx的字段之后,最后還添加了一個值,代碼如下:
/frameworks/base/core/java/android/os/Process.java
argsForZygote.add(processClass);
這個processClass就是我們要找的值了,但是它也是從前面傳過來的,調用的地方在Process#start方法里,這個值依然作為參數傳遞了過來。然后回到了Process#start的調用處,在ActivityManagerService#startProcessLocked方法里找到了下面關鍵一句話:
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
終于找到了根源,也就是說Zygote孵化完成之后,會invoke ActivityThread#main方法。接下來進程創建完畢,就該是我們APP的初始化了,下一篇文章再來分析。