老罗的Android系统源码分析讲的很不错,网上有很不同层面多源码分析。了解细节,还是自己看源码最直接。个人并没有透彻的研究过Android系统,这一系列的博客就当是读Android源码笔记了。有不对的地方还请多指教。
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
public void startActivityForResult(Intent intent, int requestCode, 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;
}
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
最终都是调用Instrumentation的execStartActivity()方法
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= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "startActivity", null);
return mMainStack.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}
mMainStack用来描述一个Activity组件栈
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
调用startActivityLocked这个方法继续
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
callingPackage, startFlags, options, componentSpecified, null);
if (mConfigWillChange && mMainStack) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Updating to new configuration after starting activity.");
mService.updateConfigurationLocked(config, null, false, false);
}
Binder.restoreCallingIdentity(origId);
startActivityLocked中更新了ActivityRecord,调用startActivityUncheckedLocked进一步启动目标Acitivy
if (mMainStack) {
if (mResumedActivity == null
|| mResumedActivity.info.applicationInfo.uid != callingUid) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
PendingActivityLaunch pal = new PendingActivityLaunch();
pal.r = r;
pal.sourceRecord = sourceRecord;
pal.startFlags = startFlags;
mService.mPendingActivityLaunches.add(pal);
mDismissKeyguardOnNextActivity = false;
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
// This is the second allowed switch since we stopped switches,
// so now just generally allow switches. Use case: user presses
// home (switches disabled, switch to home, mDidAppSwitch now true);
// user taps a home icon (coming from home so allowed, we hit here
// and now allow anyone to switch again).
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
mService.doPendingActivityLaunchesLocked(false);
}
err = startActivityUncheckedLocked(r, sourceRecord,
startFlags, true, options);
startActivityUncheckedLocked根据不同的启动模式,会有不同的逻辑处理。
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
startActivityLocked方法更新了历史栈,
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
final int NH = mHistory.size();
int addPos = -1;
if (!newTask) {
// If starting in an existing task, find where that is...
boolean startIt = true;
for (int i = NH-1; i >= 0; i--) {
ActivityRecord p = mHistory.get(i);
if (p.finishing) {
continue;
}
if (p.task == r.task) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
addPos = i+1;
if (!startIt) {
if (DEBUG_ADD_REMOVE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
here);
}
mHistory.add(addPos, r);
r.putInHistory();
mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
}
if (p.fullscreen) {
startIt = false;
}
}
}
// Place a new activity at top of stack, so it is next to interact
// with the user.
if (addPos < 0) {
addPos = NH;
}
// If we are not placing the new activity frontmost, we do not want
// to deliver the onUserLeaving callback to the actual frontmost
// activity
if (addPos < NH) {
mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
}
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
}
mHistory.add(addPos, r);
r.putInHistory();
r.frontOfTask = newTask;
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: starting " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mService.mWindowManager.prepareAppTransition(
AppTransition.TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
mService.mWindowManager.prepareAppTransition(newTask
? AppTransition.TRANSIT_TASK_OPEN
: AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
r.updateOptionsLocked(options);
mService.mWindowManager.addAppToken(
addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
// to reset it to make sure we apply affinities to move any
// existing activities from other tasks in to it.
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags()
&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
}
if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
ActivityRecord prev = mResumedActivity;
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
if (prev.task != r.task) prev = null;
// (2) The current activity is already displayed.
else if (prev.nowVisible) prev = null;
}
mService.mWindowManager.setAppStartingWindow(
r.appToken, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
r.labelRes, r.icon, r.windowFlags,
prev != null ? prev.appToken : null, showStartingIcon);
}
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
ActivityOptions.abort(options);
}
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
if (doResume) {
resumeTopActivityLocked(null);
}
}
如果要启动的Activity的组件的next等于被激活的Activity,并且状态等于Rsumed,那么直接返回,因为说明要启动的Activity已经成功激活。
// We need to start pausing the current activity so the top one
// can be resumed...
if (mResumedActivity != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
// No reason to do full oom adj update here; we'll let that
// happen whenever it needs to later.
mService.updateLruProcessLocked(next.app, false);
}
startPausingLocked(userLeaving, false);
return true;
}
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags);
if (mMainStack) {
mService.updateUsageStats(prev, false);
}
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
}
schedulePauseActivity的具体实现在ApplicationThreadProxy类中
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(finished ? 1 : 0);
data.writeInt(userLeaving ? 1 :0);
data.writeInt(configChanges);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
通过内部的binder代理对象向应用所在进程发送一个类型为SCHEDULE_PAUSE_ACTIVITY_TRANSACTION的请求。调用ApplicaionThread的schedulePauseActivity方法
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
queueOrSendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0),
configChanges);
}
此时的finished为false,userLeaving为true,
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
handler收到PAUSE_ACTIVITY之后执行了handlePauseActivity方法
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb());
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
}
}
}
先说performPauseActivity再说activityPaused
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState) : null;
}
try {
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
state = new Bundle();
state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
}
// Now we are idle.
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName());
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
}
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
final void performPause() {
mFragments.dispatchPause();
mCalled = false;
onPause();
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
mResumed = false;
}
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
getApplication().dispatchActivityPaused(this);
mCalled = true;
}
/* package */ void dispatchActivityPaused(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i
到这里,前一个Activiy进入了onActivityPaused状态。
public void activityPaused(IBinder token) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
通过binder对象向ActivityManagerService发送了类型为ACTIVITY_PAUSED_TRANSACTION的进程通信请求。
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
mMainStack.activityPaused(token, false);
Binder.restoreCallingIdentity(origId);
}
又到了ActivityStack中
final void activityPaused(IBinder token, boolean timeout) {
if (DEBUG_PAUSE) Slog.v(
TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
ActivityRecord r = null;
synchronized (mService) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
r = mHistory.get(index);
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
r.state = ActivityState.PAUSED;
completePauseLocked();
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
r.userId, System.identityHashCode(r), r.shortComponentName,
mPausingActivity != null
? mPausingActivity.shortComponentName : "(none)");
}
}
}
}
然后通过resumeTopActivityLocked启动栈顶的Activity
{
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
mService.mWindowManager.setAppStartingWindow(
next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
next.labelRes, next.icon, next.windowFlags,
null, true);
}
if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
}
startSpecificActivityLocked(next, true, true);
}
startSpecificActivityLocked首先会以用户ID和进程名来检查系统中是否存在一个对应的应用程序,如果存在,会直接通知这个应用程序进程将该Acitivy启动起来,否则会先创建对应的应用进程,然后再启动Activity组件
private final 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);
if (r.launchTime == 0) {
r.launchTime = SystemClock.uptimeMillis();
if (mInitialStartTime == 0) {
mInitialStartTime = r.launchTime;
}
} else if (mInitialStartTime == 0) {
mInitialStartTime = SystemClock.uptimeMillis();
}
if (app != null && app.thread != null) {
try {
app.addPackage(r.info.packageName);
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.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false);
}
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null);
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
if (bs.isOnBattery()) {
app.batteryStats.incStartsLocked();
}
}
ActivityThread中创建进程
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0("");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
进程创建过程中,首先调用Looper的PrepareMainLooper来创建主线程中的消息循环,然后创建了ActivityThread对象,调用attach方法,向ActivityManager发送启动完成通知,最后启动主线程中的消息循环。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
}
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
调用attachApplicationLocked之后,进程相关信息创建并且关联完毕。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
通过Binder,最终调用了ActivityThread的scheduleLaunchActivity方法,
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List pendingResults,
List pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
if (r.profileFd != null) {
mProfiler.setProfiler(r.profileFile, r.profileFd);
mProfiler.startProfiling();
mProfiler.autoStopProfiler = r.autoStopProfiler;
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
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);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out
// paused, because it needs to be visible but isn't in the
// foreground. We accomplish this by going through the
// normal startup (because activities expect to go through
// onResume() the first time they run, before their window
// is displayed), and then pausing it. However, in this case
// we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just
// retain the current state it has.
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
// when pausing, so we can not have them save their state
// when restarting from a paused state. For HC and later,
// we want to (and can) let the state be saved as the normal
// part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} 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);
} catch (RemoteException ex) {
// Ignore
}
}
}
组件启动过程是在performLaunchActivity这个方法中
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
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;
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.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
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);
}
}
return activity;
}