...... [-> Activity.java] @Override publicvoidstartActivity(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); } }
ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { sourceRecord = mSupervisor.isInAnyStackLocked(resultTo); if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } }
finalint launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { // Transfer the result target from the source activity to the new // one being started, including any failures. if (requestCode >= 0) { SafeActivityOptions.abort(options); return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; } resultRecord = sourceRecord.resultTo; if (resultRecord != null && !resultRecord.isInStackLocked()) { resultRecord = null; } resultWho = sourceRecord.resultWho; requestCode = sourceRecord.requestCode; sourceRecord.resultTo = null; if (resultRecord != null) { resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode); } if (sourceRecord.launchedFromUid == callingUid) { callingPackage = sourceRecord.launchedFromPackage; } }
// Merge the two options bundles, while realCallerOptions takes precedence. ActivityOptions checkedOptions = options != null ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; if (allowPendingRemoteAnimationRegistryLookup) { checkedOptions = mService.getActivityStartController() .getPendingRemoteAnimationRegistry() .overrideOptionsIfNeeded(callingPackage, checkedOptions); } if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data // stripped off, since it can contain private information. Intent watchIntent = intent.cloneFilter(); abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } }
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage); ........ // If permissions need a review before any of the app components can run, we // launch the review activity and pass a pending intent to start the activity // we are to launching now after the review is completed. if (mService.mPermissionReviewRequired && aInfo != null) { if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingUid, userId, null, null, 0, new Intent[]{intent}, new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null);
finalint flags = intent.getFlags(); Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); newIntent.setFlags(flags | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); if (resultRecord != null) { newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true); } intent = newIntent;
// Should this be considered a new task? int result = START_SUCCESS; if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; String packageName= mService.mContext.getPackageName(); if (mPerf != null) { mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, packageName, -1, BoostFramework.Launch.BOOST_V1); } result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack); } elseif (mSourceRecord != null) { result = setTaskFromSourceRecord(); } elseif (mInTask != null) { result = setTaskFromInTask(); } else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask(); } if (result != START_SUCCESS) { return result; } ...... mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mService.mWindowManager.executeAppTransition(); } else { if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } } elseif (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTask()); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity + " in new task " + mStartActivity.getTask()); ------------------------------------------------------------------------------------------------ 此处对应Log:
[-> TaskRecord.java] voidaddTask(final TaskRecord task, finalboolean toTop, String reason){ addTask(task, toTop ? MAX_VALUE : 0, true/* schedulePictureInPictureModeChange */, reason); if (toTop) { // TODO: figure-out a way to remove this call. mWindowContainerController.positionChildAtTop(task.getWindowContainerController(), true/* includingParents */); } } voidaddTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, String reason){ // TODO: Is this remove really needed? Need to look into the call path for the other addTask mTaskHistory.remove(task); position = getAdjustedPositionForTask(task, position, null/* starting */); finalboolean toTop = position >= mTaskHistory.size(); final ActivityStack prevStack = preAddTask(task, reason, toTop); //将TaskRecord加入到mTaskHistory中 mTaskHistory.add(position, task); //设置对应的setStack task.setStack(this);
[-> TaskRecord.java] voidcreateWindowContainer(boolean onTop, boolean showForAllUsers){ if (mWindowContainerController != null) { thrownew IllegalArgumentException("Window container=" + mWindowContainerController + " already created for task=" + this); }
final Rect bounds = updateOverrideConfigurationFromLaunchBounds(); setWindowContainerController(new TaskWindowContainerController(taskId, this, getStack().getWindowContainerController(), userId, bounds, mResizeMode, mSupportsPictureInPicture, onTop, showForAllUsers, lastTaskDescription)); }
publicTaskWindowContainerController(int taskId, TaskWindowContainerListener listener, StackWindowController stackController, int userId, Rect bounds, int resizeMode, boolean supportsPictureInPicture, boolean toTop, boolean showForAllUsers, TaskDescription taskDescription){ this(taskId, listener, stackController, userId, bounds, resizeMode, supportsPictureInPicture, toTop, showForAllUsers, taskDescription, WindowManagerService.getInstance()); } [-> TaskWindowContainerController.java] publicTaskWindowContainerController(int taskId, TaskWindowContainerListener listener, StackWindowController stackController, int userId, Rect bounds, int resizeMode, boolean supportsPictureInPicture, boolean toTop, boolean showForAllUsers, TaskDescription taskDescription, WindowManagerService service){ super(listener, service); mTaskId = taskId; mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
synchronized(mWindowMap) { if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId + " stack=" + stackController + " bounds=" + bounds); //TaskStack,对应ActivityStack final TaskStack stack = stackController.mContainer; if (stack == null) { thrownew IllegalArgumentException("TaskWindowContainerController: invalid stack=" + stackController); } EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId); //根据AMS端的taskId创建WMS端的Task,对应AMS的TaskRecord final Task task = createTask(taskId, stack, userId, resizeMode, supportsPictureInPicture, taskDescription); finalint position = toTop ? POSITION_TOP : POSITION_BOTTOM; // We only want to move the parents to the parents if we are creating this task at the // top of its stack. stack.addTask(task, position, showForAllUsers, toTop /* moveParents */); } }
[-> G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\TaskStack.java] voidaddTask(Task task, int position, boolean showForAllUsers, boolean moveParents){ final TaskStack currentStack = task.mStack; // TODO: We pass stack to task's constructor, but we still need to call this method. // This doesn't make sense, mStack will already be set equal to "this" at this point. if (currentStack != null && currentStack.mStackId != mStackId) { thrownew IllegalStateException("Trying to add taskId=" + task.mTaskId + " to stackId=" + mStackId + ", but it is already attached to stackId=" + task.mStack.mStackId); }
// Move child to a proper position, as some restriction for position might apply. positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers); }
[-> ActivityStack.java] voidstartActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options){ TaskRecord rTask = r.getTask(); finalint taskId = rTask.taskId; // mLaunchTaskBehind tasks get placed at the back of the task stack. if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { insertTaskAtTop(rTask, r); } TaskRecord task = null; if (!newTask) { // If starting in an existing task, find where that is... boolean startIt = true; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { task = mTaskHistory.get(taskNdx); if (task.getTopActivity() == null) { // All activities in task are finishing. continue; } if (task == rTask) { if (!startIt) { if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " + task, new RuntimeException("here").fillInStackTrace()); r.createWindowContainer(); ActivityOptions.abort(options); return; } break; } elseif (task.numFullscreen > 0) { startIt = false; } } }
final TaskRecord activityTask = r.getTask(); if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { mStackSupervisor.mUserLeaving = false; if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, "startActivity() behind front, mUserLeaving=false"); }
task = activityTask; ----------------------------------------------------------------------------------------------- 此处对应Log: 04-16 13:08:36.765 I/ActivityStack( 1049): Adding activity ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} to stack to task TaskRecord{d697e21 #5 A=com.android.testred U=0 StackId=1 sz=1} 04-1613:08:36.765 I/ActivityStack( 1049): java.lang.RuntimeException: here 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStack.startActivityLocked(ActivityStack.java:2963) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1448) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:1204) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:872) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:548) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.startActivityMayWait(ActivityStarter.java:1103) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityStarter.execute(ActivityStarter.java:490) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:5182) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:5156) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerShellCommand.runStartActivity(ActivityManagerShellCommand.java:479) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerShellCommand.onCommand(ActivityManagerShellCommand.java:161) 04-1613:08:36.765 I/ActivityStack( 1049): at android.os.ShellCommand.exec(ShellCommand.java:103) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerService.onShellCommand(ActivityManagerService.java:16147) 04-1613:08:36.765 I/ActivityStack( 1049): at android.os.Binder.shellCommand(Binder.java:634) 04-1613:08:36.765 I/ActivityStack( 1049): at android.os.Binder.onTransact(Binder.java:532) 04-1613:08:36.765 I/ActivityStack( 1049): at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3592) 04-1613:08:36.765 I/ActivityStack( 1049): at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3340) 04-1613:08:36.765 I/ActivityStack( 1049): at android.os.Binder.execTransact(Binder.java:731) ----------------------------------------------------------------------------------------------- // Slot the activity into the history stack and proceed if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task, new RuntimeException("here").fillInStackTrace());
if (r.getWindowContainerController() == null) { r.createWindowContainer(); } //将TaskRecord设置为front task task.setFrontOfTask();
if (mActivityTrigger != null) { mActivityTrigger.activityStartTrigger(r.intent, r.info, r.appInfo, r.fullscreen); }
final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || !r.isState(RESUMED)) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } elseif (r.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); }
[->ActivityStack.java] @GuardedBy("mService") booleanresumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){ if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. returnfalse; }
boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivityLocked(true/* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); } } finally { mStackSupervisor.inResumeTopActivity = false; }
[->ActivityStack.java] @GuardedBy("mService") privatebooleanresumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){ ...... // Find the next top-most activity to resume in this stack that is not finishing and is // focusable. If it is not focusable, we will fall into the case below to resume the // top activity in the next focusable task. final ActivityRecord next = topRunningActivityLocked(true/* focusableOnly */);
finalboolean hasRunningActivity = next != null;
......
// The activity may be waiting for stop, but that is no longer // appropriate for it. mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next); next.launching = true;
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
if (mActivityTrigger != null) { mActivityTrigger.activityResumeTrigger(next.intent, next.info, next.appInfo, next.fullscreen); } ------------------------------------------------------------------------------ 对应Log: 04-1613:08:36.769 V/ActivityStack_Switch( 1049): Resuming ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} 04-1613:08:36.769 D/ActivityTrigger( 1049): activityResumeTrigger: Activity is not Triggerred in full screen ApplicationInfo{2bedb5d com.android.testred} ------------------------------------------------------------------------------ ......
// If the previous activity is translucent, force a visibility update of // the next activity, so that it's added to WM's opening app list, and // transition animation can be set up properly. // For example, pressing Home button with a translucent activity in focus. // Launcher is already visible in this case. If we don't add it to opening // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. finalboolean lastActivityTranslucent = lastStack != null && (lastStack.inMultiWindowMode() || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen));
// The contained logic must be synchronized, since we are both changing the visibility // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will // ultimately cause the client code to schedule a layout. Since layouts retrieve the // current {@link Configuration}, we must ensure that the below code updates it before // the layout can occur. synchronized(mWindowManager.getWindowManagerLock()) { // This activity is now becoming visible. if (!next.visible || next.stopped || lastActivityTranslucent) { next.setVisibility(true); }
// schedule launch ticks to collect information about slow apps. next.startLaunchTickingLocked();
// Have the window manager re-evaluate the orientation of // the screen based on the new activity order. boolean notUpdated = true;
if (mStackSupervisor.isFocusedStack(this)) { // We have special rotation behavior when here is some active activity that // requests specific orientation or Keyguard is locked. Make sure all activity // visibilities are set correctly as well as the transition is updated if needed // to get the correct rotation behavior. Otherwise the following call to update // the orientation may cause incorrect configurations delivered to client as a // result of invisible window resize. // TODO: Remove this once visibilities are set correctly immediately when // starting an activity. notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId, true/* markFrozenIfConfigChanged */, false/* deferResume */); }
if (notUpdated) { // The configuration update wasn't able to keep the existing // instance of the activity, and instead started a new one. // We should be all done, but let's just make sure our activity // is still at the top and schedule another run if something // weird happened. ActivityRecord nextNext = topRunningActivityLocked(); if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, "Activity config changed during resume: " + next + ", new next: " + nextNext); if (nextNext != next) { // Do over! mStackSupervisor.scheduleResumeTopActivities(); } if (!next.visible || next.stopped) { next.setVisibility(true); } next.completeResumeLocked(); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); returntrue; }
try { final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread, next.appToken); // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { finalint N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); transaction.addCallback(ActivityResultItem.obtain(a)); } }
if (next.newIntents != null) { transaction.addCallback(NewIntentItem.obtain(next.newIntents, false/* andPause */)); }
// Well the app will no longer be stopped. // Clear app token stopped state in window manager if needed. next.notifyAppResumed(next.stopped);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { // Whoops, need to restart this activity! if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " + lastState + ": " + next); next.setState(lastState, "resumeTopActivityInnerLocked");
// lastResumedActivity being non-null implies there is a lastStack present. if (lastResumedActivity != null) { lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); }
// From this point on, if something goes wrong there is no way // to recover the activity. try { next.completeResumeLocked(); } catch (Exception e) { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception", true); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); returntrue; } } else { // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { next.showStartingWindow(null/* prev */, false/* newTask */, false/* taskSwich */); } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); } if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next); mStackSupervisor.startSpecificActivityLocked(next, true, true); }
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); returntrue; }
mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately)); } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } } else { mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; }
// If we are not going to sleep, we want to ensure the device is // awake until the next activity is started. if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) { mStackSupervisor.acquireLaunchWakelock(); }
if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt // key dispatch; the same activity will pick it up again on wakeup. -------------------------------------------------------------------------------------------------- 对应Log: 04-1613:08:36.770 V/WindowManager( 1049): Pausing WindowToken AppWindowToken{483acfb token=Token{f984e8a ActivityRecord{5e34200 u0 com.android.launcher3/.Launcher t4}}} prev.pauseKeyDispatchingLocked(); -------------------------------------------------------------------------------------------------- if (!uiSleeping) { prev.pauseKeyDispatchingLocked(); } elseif (DEBUG_PAUSE) { Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off"); }
if (pauseImmediately) { // If the caller said they don't want to wait for the pause, then complete // the pause now. //完成Pause completePauseLocked(false, resuming); returnfalse;
} else { // This activity failed to schedule the // pause, so just treat it as being paused now. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next."); if (resuming == null) { mStackSupervisor.resumeFocusedStackTopActivityLocked(); } returnfalse; } }
voidsetState(ActivityState state, String reason){ if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState() + " to:" + state + " reason:" + reason); ...... mState = state;
final TaskRecord parent = getTask();
if (parent != null) { parent.onActivityStateChanged(this, state, reason); }
// The WindowManager interprets the app stopping signal as // an indication that the Surface will eventually be destroyed. // This however isn't necessarily true if we are going to sleep. if (state == STOPPING && !isSleeping()) { mWindowContainerController.notifyAppStopping(); } }
voidscheduleTransaction(ClientTransaction transaction)throws RemoteException { final IApplicationThread client = transaction.getClient(); transaction.schedule(); if (!(client instanceof Binder)) { // If client is not an instance of Binder - it's a remote call and at this point it is // safe to recycle the object. All objects used for local calls will be recycled after // the transaction is executed on client in ActivityThread. transaction.recycle(); } } G:\android9.0\frameworks\base\core\java\android\app\servertransaction\ClientTransaction.java /** Target client. */ private IApplicationThread mClient; publicvoidschedule()throws RemoteException { mClient.scheduleTransaction(this); }
G:\android9.0\frameworks\base\core\java\android\app\ActivityThread.java classHextendsHandler { ...... publicvoidhandleMessage(Message msg){ if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case EXIT_APPLICATION: if (mInitialApplication != null) { mInitialApplication.onTerminate(); } Looper.myLooper().quit(); break; ...... case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); if (isSystem()) { // Client transactions inside system process are recycled on the client side // instead of ClientLifecycleManager to avoid being cleared before this // message is handled. transaction.recycle(); } // TODO(lifecycler): Recycle locally scheduled transactions. break; case RELAUNCH_ACTIVITY: handleRelaunchActivityLocally((IBinder) msg.obj); break; } Object obj = msg.obj; if (obj instanceof SomeArgs) { ((SomeArgs) obj).recycle(); } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); } }
case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); if (isSystem()) { // Client transactions inside system process are recycled on the client side // instead of ClientLifecycleManager to avoid being cleared before this // message is handled. transaction.recycle(); } // TODO(lifecycler): Recycle locally scheduled transactions. break;
/** Transition to the final state if requested by the transaction. */ privatevoidexecuteLifecycleState(ClientTransaction transaction){ final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest(); if (lifecycleItem == null) { // No lifecycle request, return early. return; } log("Resolving lifecycle state: " + lifecycleItem);
final IBinder token = transaction.getActivityToken(); final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (r == null) { // Ignore requests for non-existent client records for now. return; }
// Cycle to the state right before the final requested state. cycleToPath(r, lifecycleItem.getTargetState(), true/* excludeLastState */);
// Execute the final transition with proper parameters. lifecycleItem.execute(mTransactionHandler, token, mPendingActions); lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions); }
voidstartSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig){ // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
getLaunchTimeTracker().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.longVersionCode, 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. }
@GuardedBy("this") 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) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); checkTime(startTime, "startProcess: after getProcessRecord");
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { ...... } else { if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid + "/" + info.processName); mAppErrors.resetProcessCrashTimeLocked(info); if (mAppErrors.isBadProcessLocked(info)) { EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, UserHandle.getUserId(info.uid), info.uid, info.processName); mAppErrors.clearBadProcessLocked(info); if (app != null) { app.bad = false; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; }
// We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName + " app=" + app + " knownToBeDead=" + knownToBeDead + " thread=" + (app != null ? app.thread : null) + " pid=" + (app != null ? app.pid : -1)); ....... ------------------------------------------------------------------------------- Line 1222: 04-1613:08:36.788 V/ActivityManagerService( 1049): Clearing bad process: 10088/com.android.testred Line 1223: 04-1613:08:36.788 V/ActivityManagerService_Processes( 1049): startProcess: name=com.android.testred app=null knownToBeDead=true thread=null pid=-1 ------------------------------------------------------------------------------- String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null;
if (app == null) { checkTime(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid); ...... app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; 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"); }
// Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. final String entryPoint = "android.app.ActivityThread";
publicstaticvoidmain(String argv[]){ ZygoteServer zygoteServer = new ZygoteServer();
// Mark zygote start. This ensures that thread creation will throw // an error. ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group. try { Os.setpgid(0, 0); } catch (ErrnoException ex) { thrownew RuntimeException("Failed to setpgid(0,0)", ex); }
final Runnable caller; try { // Report Zygote start time to tron unless it is a runtime restart if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.elapsedRealtime()); }
if (abiList == null) { thrownew RuntimeException("No ABI list supplied."); }
zygoteServer.registerServerSocketFromEnv(socketName); // In some configurations, we avoid preloading resources and classes eagerly. // In such cases, we will preload things prior to our first fork. if (!enableLazyPreload) { preload(bootTimingsTraceLog); } else { Zygote.resetNicePriority(); }
if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the // child (system_server) process. if (r != null) { r.run(); return; } }
// The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); }
// We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run(); } } G:\android9.0\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
Runnable runSelectLoop(String abiList){ ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// readArgumentList returns null only when it has reached EOF with no available // data to read. This will only happen when the remote socket has disconnected. if (args == null) { isEof = true; returnnull; }
if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); }
int[] fdsToIgnore = null;
if (parsedArgs.invokeWith != null) { try { FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC); childPipeFd = pipeFds[1]; serverPipeFd = pipeFds[0]; Os.fcntlInt(childPipeFd, F_SETFD, 0); fdsToIgnore = newint[]{childPipeFd.getInt$(), serverPipeFd.getInt$()}; } catch (ErrnoException errnoEx) { thrownew IllegalStateException("Unable to set up pipe for invoke-with", errnoEx); } }
/** * In order to avoid leaking descriptors to the Zygote child, * the native code must close the two Zygote socket descriptors * in the child process before it switches from Zygote-root to * the UID and privileges of the application being launched. * * In order to avoid "bad file descriptor" errors when the * two LocalSocket objects are closed, the Posix file * descriptors are released via a dup2() call which closes * the socket and substitutes an open descriptor to /dev/null. */
publicstaticintforkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir){ VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { Trace.setTracingEnabled(true, runtimeFlags);
// Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } VM_HOOKS.postForkCommon(); return pid; }
VM_HOOKS是Zygote对象的静态成员变量:VM_HOOKS = new ZygoteHooks();
// Grant CAP_WAKE_ALARM to the Bluetooth process. // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client. // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for // audio-related threads. // TODO: consider making such functionality an RPC to netd. if (multiuser_get_app_id(uid) == AID_BLUETOOTH) { capabilities |= (1LL << CAP_WAKE_ALARM); capabilities |= (1LL << CAP_NET_RAW); capabilities |= (1LL << CAP_NET_BIND_SERVICE); capabilities |= (1LL << CAP_SYS_NICE); }
// Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" bool gid_wakelock_found = false; if (gid == AID_WAKELOCK) { gid_wakelock_found = true; } elseif (gids != NULL) { jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO ar(env, gids); if (ar.get() == NULL) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int i = 0; i < gids_num; i++) { if (ar[i] == AID_WAKELOCK) { gid_wakelock_found = true; break; } } } if (gid_wakelock_found) { capabilities |= (1LL << CAP_BLOCK_SUSPEND); }
// If forking a child zygote process, that zygote will need to be able to change // the UID and GID of processes it forks, as well as drop those capabilities. if (is_child_zygote) { capabilities |= (1LL << CAP_SETUID); capabilities |= (1LL << CAP_SETGID); capabilities |= (1LL << CAP_SETPCAP); }
// Containers run without some capabilities, so drop any caps that are not // available. capabilities &= GetEffectiveCapabilityMask(env);
// Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); }
// Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close();
std::string error_msg;
// If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { fail_fn(error_msg); } if (gOpenFdTable == NULL) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { fail_fn(error_msg); } } elseif (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { fail_fn(error_msg); }
pid_t pid = fork();
if (pid == 0) { PreApplicationInit();
// Clean up any descriptors which must be closed immediately if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); }
// Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); }
// Keep capabilities across UID change, unless we're staying root. if (uid != 0) { if (!EnableKeepCapabilities(&error_msg)) { fail_fn(error_msg); } }
if (!SetInheritable(permittedCapabilities, &error_msg)) { fail_fn(error_msg); } if (!DropCapabilitiesBoundingSet(&error_msg)) { fail_fn(error_msg); }
bool use_native_bridge = !is_system_server && (instructionSet != NULL) && android::NativeBridgeAvailable(); if (use_native_bridge) { ScopedUtfChars isa_string(env, instructionSet); use_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); } if (use_native_bridge && dataDir == NULL) { // dataDir should never be null if we need to use a native bridge. // In general, dataDir will never be null for normal applications. It can only happen in // special cases (for isolated processes which are not associated with any app). These are // launched by the framework and should not be emulated anyway. use_native_bridge = false; ALOGW("Native bridge will not be used because dataDir == NULL."); }
if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) { ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno)); if (errno == ENOTCONN || errno == EROFS) { // When device is actively encrypting, we get ENOTCONN here // since FUSE was mounted before the framework restarted. // When encrypted device is booting, we get EROFS since // FUSE hasn't been created yet by init. // In either case, continue without external storage. } else { fail_fn(error_msg); } }
// If this zygote isn't root, it won't be able to create a process group, // since the directory is owned by root. if (!is_system_server && getuid() == 0) { int rc = createProcessGroup(uid, getpid()); if (rc != 0) { if (rc == -EROFS) { ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); } else { ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc)); } } }
std::string error_msg; if (!SetGids(env, javaGids, &error_msg)) { fail_fn(error_msg); }
if (!SetRLimits(env, javaRlimits, &error_msg)) { fail_fn(error_msg); }
int rc = setresgid(gid, gid, gid); if (rc == -1) { fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno))); }
// Must be called when the new process still has CAP_SYS_ADMIN, in this case, before changing // uid from 0, which clears capabilities. The other alternative is to call // prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see // b/71859146). As the result, privileged syscalls used below still need to be accessible in // app process. SetUpSeccompFilter(uid);
if (NeedsNoRandomizeWorkaround()) { // Work around ARM kernel ASLR lossage (http://b/5817320). int old_personality = personality(0xffffffff); int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE); if (new_personality == -1) { ALOGW("personality(%d) failed: %s", new_personality, strerror(errno)); } }
if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities, &error_msg)) { fail_fn(error_msg); }
if (!SetSchedulerPolicy(&error_msg)) { fail_fn(error_msg); }
// Make it easier to debug audit logs by setting the main thread's name to the // nice name rather than "app_process". if (se_name_c_str == NULL && is_system_server) { se_name_c_str = "system_server"; } if (se_name_c_str != NULL) { SetThreadName(se_name_c_str); }
delete se_info; delete se_name;
// Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). UnsetChldSignalHandler();
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, instructionSet); if (env->ExceptionCheck()) { fail_fn("Error calling post fork hooks."); } } elseif (pid > 0) { // the parent process
// We blocked SIGCHLD prior to a fork, we unblock it here. if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } } return pid; }
G:\android9.0\frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote){ /** * By the time we get here, the native code has closed the two actual Zygote * socket connections, and substituted /dev/null in their place. The LocalSocket * objects still need to be closed properly. */
if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); }
// End of the postFork event. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.remainingArgs);
// Should not get here. thrownew IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); } } }
5.3.2、ZygoteInit.zygoteInit()
1 2 3 4 5 6 7 8 9 10 11 12 13
G:\android9.0\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java publicstaticfinal Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader){ if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); }
protectedstatic Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader){ // If the application calls System.exit(), terminate the process // immediately without running any shutdown hooks. It is not possible to // shutdown an Android application gracefully. Among other things, the // Android runtime shutdown hooks close the Binder driver, which can cause // leftover running threads to crash before the process actually exits. nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit). Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main return findStaticMain(args.startClass, args.startArgs, classLoader); }
try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { thrownew RuntimeException( "Missing class when invoking static main " + className, ex); }
Method m; try { m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { thrownew RuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { thrownew RuntimeException( "Problem getting static main on " + className, ex); }
int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { thrownew 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. */ returnnew MethodAndArgsCaller(m, argv); }
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" long startSeq = 0; if (args != null) { for (int i = args.length - 1; i >= 0; --i) { if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) { startSeq = Long.parseLong( args[i].substring(PROC_START_SEQ_IDENT.length())); } } } ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq);
@GuardedBy("this") privatefinalbooleanattachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq){
// Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; long startTime = SystemClock.uptimeMillis(); if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; }
// It's possible that process called attachApplication before we got a chance to // update the internal state. if (app == null && startSeq > 0) { final ProcessRecord pending = mPendingStarts.get(startSeq); if (pending != null && pending.startUid == callingUid && handleProcessStartedLocked(pending, pid, pending.usingWrapper, startSeq, true)) { app = pending; } }
// If this application record is still attached to a previous // process, clean it up now. if (app.thread != null) { handleAppDiedLocked(app, true, true); }
// Tell the process all about itself.
if (DEBUG_ALL) Slog.v( TAG, "Binding process pid " + pid + " to record " + app); ------------------------------------ 对应Log: 04-1613:08:36.817 I/ActivityManagerService( 1049): Start proc 2602:com.android.testred/u0a88 for activity com.android.testred/.TestActivity 04-1613:08:36.837 V/ActivityManagerService( 1049): Binding process pid 2602 to record ProcessRecord{d768ca0 2602:com.android.testred/u0a88} ------------------------------------ final String processName = app.processName; try { AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; ------------------------------------ 对应Log: 04-1613:08:36.837 V/ActivityManagerService( 1049): New death recipient com.android.server.am.ActivityManagerService$AppDeathRecipient@53b14ff for thread android.os.BinderProxy@6c7d2cc ------------------------------------ } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); returnfalse; }
// We carefully use the same state that PackageManager uses for // filtering, since we use this flag to decide if we need to install // providers when user is unlocked later app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
// If the app is being launched for restore or full backup, set it up specially boolean isRestrictedBackupMode = false; if (mBackupTarget != null && mBackupAppName.equals(processName)) { isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID && ((mBackupTarget.backupMode == BackupRecord.RESTORE) || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL) || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL)); }
ProfilerInfo profilerInfo = null; String preBindAgent = null; if (mProfileApp != null && mProfileApp.equals(processName)) { mProfileProc = app; if (mProfilerInfo != null) { // Send a profiler info object to the app if either a file is given, or // an agent should be loaded at bind-time. boolean needsInfo = mProfilerInfo.profileFile != null || mProfilerInfo.attachAgentDuringBind; profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null; if (mProfilerInfo.agent != null) { preBindAgent = mProfilerInfo.agent; } } } elseif (app.instr != null && app.instr.mProfileFile != null) { profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false, null, false); } if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) { // We need to do a debuggable check here. See setAgentApp for why the check is // postponed to here. if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { String agent = mAppAgentMap.get(processName); // Do not overwrite already requested agent. if (profilerInfo == null) { profilerInfo = new ProfilerInfo(null, null, 0, false, false, mAppAgentMap.get(processName), true); } elseif (profilerInfo.agent == null) { profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true); } } }
// We deprecated Build.SERIAL and it is not accessible to // apps that target the v2 security sandbox and to apps that // target APIs higher than O MR1. Since access to the serial // is now behind a permission we push down the value. final String buildSerial = (appInfo.targetSandboxVersion < 2 && appInfo.targetSdkVersion < Build.VERSION_CODES.P) ? sTheRealBuildSerial : Build.UNKNOWN;
// Check if this is a secondary process that should be incorporated into some // currently active instrumentation. (Note we do this AFTER all of the profiling // stuff above because profiling can currently happen only in the primary // instrumentation process.) if (mActiveInstrumentation.size() > 0 && app.instr == null) { for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) { ActiveInstrumentation aInstr = mActiveInstrumentation.get(i); if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) { if (aInstr.mTargetProcesses.length == 0) { // This is the wildcard mode, where every process brought up for // the target instrumentation should be included. if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) { app.instr = aInstr; aInstr.mRunningProcesses.add(app); } } else { for (String proc : aInstr.mTargetProcesses) { if (proc.equals(app.processName)) { app.instr = aInstr; aInstr.mRunningProcesses.add(app); break; } } } } } }
// If we were asked to attach an agent on startup, do so now, before we're binding // application code. if (preBindAgent != null) { thread.attachAgent(preBindAgent); }
// Figure out whether the app needs to run in autofill compat mode. boolean isAutofillCompatEnabled = false; if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) { final AutofillManagerInternal afm = LocalServices.getService( AutofillManagerInternal.class); if (afm != null) { isAutofillCompatEnabled = afm.isCompatibilityModeRequested( app.info.packageName, app.info.versionCode, app.userId); } }
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(app); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } elseif (app.instr != null) { thread.bindApplication(processName, appInfo, providers, app.instr.mClass, profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } if (profilerInfo != null) { profilerInfo.closeFd(); profilerInfo = null; } checkTime(startTime, "attachApplicationLocked: immediately after bindApplication"); ------------------------ 对应Log: 04-1613:08:36.838 D/ActivityManagerService_LRU( 1049): Adding at 45 of LRU list: ProcessRecord{d768ca0 2602:com.android.testred/u0a88} ------------------------ updateLruProcessLocked(app, false, null); checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked"); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { // todo: Yikes! What should we do? For now we will try to // start another process, but that could easily get us in // an infinite loop of restarting processes... Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
// Remove this record from the list of starting applications. mPersistentStartingProcesses.remove(app); if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app); mProcessesOnHold.remove(app);
// See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } }
// Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked"); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } }
// Check if a next-broadcast receiver is in this process... if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked"); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e); badApp = true; } }
// Check whether the next backup agent is in this process... if (!badApp && mBackupTarget != null && mBackupTarget.app == app) { if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "New app is backup target, launching agent for " + app); notifyPackageUse(mBackupTarget.appInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_BACKUP); try { thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e); badApp = true; } }
if (badApp) { app.kill("error during init", true); handleAppDiedLocked(app, false, true); returnfalse; }
if (!didSomething) { updateOomAdjLocked(); checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked"); }
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java booleanattachApplicationLocked(ProcessRecord app)throws RemoteException { final String processName = app.processName; boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = display.getChildAt(stackNdx); if (!isFocusedStack(stack)) { continue; } stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); final ActivityRecord top = stack.topRunningActivityLocked(); finalint size = mTmpActivityList.size(); for (int i = 0; i < size; i++) { final ActivityRecord activity = mTmpActivityList.get(i); if (activity.app == null && app.uid == activity.info.applicationInfo.uid && processName.equals(activity.processName)) { try { if (realStartActivityLocked(activity, app, top == activity /* andResume */, true/* checkConfig */)) { didSomething = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + top.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } return didSomething; } voidensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows){ ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, true/* notifyClients */); }
/** * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) */ voidensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients){ getKeyguardController().beginActivityVisibilityUpdate(); try { // First the front stacks. In case any are not fullscreen and are in front of home. for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = display.getChildAt(stackNdx); stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, notifyClients); } } } finally { getKeyguardController().endActivityVisibilityUpdate(); } }
// If the top activity is not fullscreen, then we need to // make sure any activities under it are now visible. boolean aboveTop = top != null; finalboolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this) && (isInStackLocked(starting) == null); finalboolean isTopNotPinnedStack = isAttached() && getDisplay().isTopNotPinnedStack(this); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.finishing) { continue; } finalboolean isTop = r == top; if (aboveTop && !isTop) { continue; } aboveTop = false;
// Check whether activity should be visible without Keyguard influence finalboolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard( behindFullscreenActivity); r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
// Now check whether it's really visible depending on Keyguard state. finalboolean reallyVisible = checkKeyguardVisibility(r, visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); if (visibleIgnoringKeyguard) { behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible, behindFullscreenActivity, r); } if (reallyVisible) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r + " finishing=" + r.finishing + " state=" + r.getState()); // First: if this is not the current activity being started, make // sure it matches the current configuration. if (r != starting && notifyClients) { r.ensureActivityConfiguration(0/* globalChanges */, preserveWindows, true/* ignoreStopState */); }
if (r.app == null || r.app.thread == null) { if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, resumeNextActivity, r)) { if (activityNdx >= activities.size()) { // Record may be removed if its process needs to restart. activityNdx = activities.size() - 1; } else { resumeNextActivity = false; } } } elseif (r.visible) { // If this activity is already visible, then there is nothing to do here. if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r);
if (r.mClientVisibilityDeferred && notifyClients) { r.makeClientVisible(); }
//charlesvincent start if("com.android.testred".equals(r.packageName) || "com.android.testgreen".equals(r.packageName) || "com.android.testblue".equals(r.packageName)){ //do nothing }else{ makeInvisible(r); } //charlesvincent end } } finalint windowingMode = getWindowingMode(); if (windowingMode == WINDOWING_MODE_FREEFORM) { // The visibility of tasks and the activities they contain in freeform stack are // determined individually unlike other stacks where the visibility or fullscreen // status of an activity in a previous task affects other. behindFullscreenActivity = !stackShouldBeVisible; } elseif (isActivityTypeHome()) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task + " stackShouldBeVisible=" + stackShouldBeVisible + " behindFullscreenActivity=" + behindFullscreenActivity); // No other task in the home stack should be visible behind the home activity. // Home activities is usually a translucent activity with the wallpaper behind // them. However, when they don't have the wallpaper behind them, we want to // show activities in the next application stack behind them vs. another // task in the home stack like recents. behindFullscreenActivity = true; } }
if (mTranslucentActivityWaiting != null && mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { // Nothing is getting drawn or everything was already visible, don't wait for timeout. notifyActivityDrawnLocked(null); } } finally { mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate(); } }
if (!allPausedActivitiesComplete()) { // While there are activities pausing we skipping starting any new activities until // pauses are complete. NOTE: that we also do this for activities that are starting in // the paused state because they will first be resumed then paused on the client side. if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "realStartActivityLocked: Skipping start of r=" + r + " some activities pausing..."); returnfalse; }
final TaskRecord task = r.getTask(); final ActivityStack stack = task.getStack();
beginDeferResume();
try { r.startFreezingScreenLocked(app, 0);
// schedule launch ticks to collect information about slow apps. r.startLaunchTickingLocked();
r.setProcess(app);
if (getKeyguardController().isKeyguardLocked()) { r.notifyUnknownVisibilityLaunched(); }
// Have the window manager re-evaluate the orientation of the screen based on the new // activity order. Note that as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, because the activity is // not currently running so we are just restarting it anyway. if (checkConfig) { // Deferring resume here because we're going to launch new activity shortly. // We don't want to perform a redundant launch of the same record while ensuring // configurations and trying to resume top activity of focused stack. ensureVisibilityAndConfig(r, r.getDisplayId(), false/* markFrozenIfConfigChanged */, true/* deferResume */); }
if (r.getStack().checkKeyguardVisibility(r, true/* shouldBeVisible */, true/* isTop */)) { // We only set the visibility to true if the activity is allowed to be visible // based on // keyguard state. This avoids setting this into motion in window manager that is // later cancelled due to later calls to ensure visible activities that set // visibility back to false. r.setVisibility(true); ------------------------------ 对应Log:
try { if (app.thread == null) { thrownew RemoteException(); } List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { // We don't need to deliver new intents and/or set results if activity is going // to pause immediately after launch. results = r.results; newIntents = r.newIntents; } ------------------------------------------------ 对应Log: 04-1613:08:36.854 V/ActivityStackSupervisor_Switch( 1049): Launching: ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} icicle=null with results=null newIntents=null andResume=true ------------------------------------------------ if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId, System.identityHashCode(r), task.taskId, r.shortComponentName); if (r.isActivityTypeHome()) { // Home process is the root process of the task. mService.mHomeProcess = task.mActivities.get(0).app; } mService.notifyPackageUse(r.intent.getComponent().getPackageName(), PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY); r.sleeping = false; r.forceNewConfig = false; mService.getAppWarningsLocked().onStartActivity(r); mService.showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); ProfilerInfo profilerInfo = null; if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) { if (mService.mProfileProc == null || mService.mProfileProc == app) { mService.mProfileProc = app; ProfilerInfo profilerInfoSvc = mService.mProfilerInfo; if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) { if (profilerInfoSvc.profileFd != null) { try { profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup(); } catch (IOException e) { profilerInfoSvc.closeFd(); } }
profilerInfo = new ProfilerInfo(profilerInfoSvc); } } }
app.hasShownUi = true; app.pendingUiClean = true; app.forceProcessStateUpTo(mService.mTopProcessState); // Because we could be starting an Activity in the system process this may not go // across a Binder interface which would create a new Configuration. Consequently // we have to always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration( mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration()); r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.icicle);
// Create activity launch transaction. final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken); clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, mService.isNextTransitionForward(), profilerInfo));
// Set desired final state. // ResumeActivityItem final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem);
if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { // This may be a heavy-weight process! Note that the package // manager will ensure that only activity can run in the main // process of the .apk, which is the only thing that will be // considered heavy-weight. if (app.processName.equals(app.info.packageName)) { if (mService.mHeavyWeightProcess != null && mService.mHeavyWeightProcess != app) { Slog.w(TAG, "Starting new heavy weight process " + app + " when already running " + mService.mHeavyWeightProcess); } mService.mHeavyWeightProcess = app; Message msg = mService.mHandler.obtainMessage( ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG); msg.obj = r; mService.mHandler.sendMessage(msg); } }
} catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); returnfalse; }
// This is the first time we failed -- restart process and // retry. r.launchFailed = true; app.activities.remove(r); throw e; } } finally { endDeferResume(); }
r.launchFailed = false; if (stack.updateLRUListLocked(r)) { Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); }
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction, // so updating the state should be done accordingly. if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs // a resume. ---------------------------------------------- 对应Log: 04-1613:08:36.854 V/ActivityStack_States( 1049): Moving to RESUMED: ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} (starting new instance) callers=com.android.server.am.ActivityStackSupervisor.realStartActivityLocked:1609 com.android.server.am.ActivityStackSupervisor.attachApplicationLocked:996 com.android.server.am.ActivityManagerService.attachApplicationLocked:7977 com.android.server.am.ActivityManagerService.attachApplication:8045 android.app.IActivityManager$Stub.onTransact:198 04-1613:08:36.854 V/ActivityRecord_States( 1049): State movement: ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} from:INITIALIZING to:RESUMED reason:minimalResumeActivityLocked 04-1613:08:36.854 V/ActivityStack_Stack( 1049): set resumed activity to:ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} reason:minimalResumeActivityLocked 04-1613:08:36.855 D/ActivityStack_Stack( 1049): setResumedActivity stack:ActivityStack{1b7b488 stackId=1 type=standard mode=fullscreen visible=true translucent=true, 1 tasks} + from: null to:ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5} reason:minimalResumeActivityLocked - onActivityStateChanged ---------------------------------------------- stack.minimalResumeActivityLocked(r); ---------------------------------------------- 看下 stack.minimalResumeActivityLocked(r) 最终调用到android9.0/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
if (state == RESUMED) { if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason); setResumedActivity(record, reason + " - onActivityStateChanged"); //mWindowManager.setFocusedApp(r.appToken, true); ---------------------------------------------- 对应Log: 04-1613:08:36.855 V/WindowManager( 1049): Set focused app to: AppWindowToken{1579134 token=Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}} old focus=AppWindowToken{483acfb token=Token{f984e8a ActivityRecord{5e34200 u0 com.android.launcher3/.Launcher t4}}} moveFocusNow=true ---------------------------------------------- mService.setResumedActivityUncheckLocked(record, reason); //将TaskRecord加入到mRecentTasks mStackSupervisor.mRecentTasks.add(record.getTask()); } } ---------------------------------------------- } } else { // This activity is not starting in the resumed state... which should look like we asked // it to pause+stop (but remain visible), and it has done so and reported back the // current icicle and other state. if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r + " (starting in paused state)"); r.setState(PAUSED, "realStartActivityLocked"); }
// Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (isFocusedStack(stack)) { mService.getActivityStartController().startSetupActivity(); }
// Update any services we are bound to that might care about whether // their client may have activities. if (r.app != null) { mService.mServices.updateServiceConnectionActivitiesLocked(r.app); }
returntrue; }
1 2 3 4 5 6 7 8 9
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, mService.isNextTransitionForward(), profilerInfo));
[-> ActivityThread.java] @Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent){ // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true;
if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); }
// Make sure we are running with the most recent config. handleConfigurationChanged(null, null);
if (localLOGV) Slog.v( TAG, "Handling launch of " + r);
// Initialize before creating the activity if (!ThreadedRenderer.sRendererDisabled) { GraphicsEnvironment.earlyInitEGL(); } WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); if (!r.activity.mFinished && pendingActions != null) { pendingActions.setOldState(r.state); pendingActions.setRestoreInstanceState(true); pendingActions.setCallOnPostCreate(true); } } else { // If there was an error, for any reason, tell the activity manager to stop us. try { ActivityManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }
frameworks/base/core/java/android/app/Activity.java finalvoidperformResume(boolean followedByPause, String reason){ performRestart(true/* start */, reason); ... // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); ... }