frameworks/base/services/core/java/com/android/server/SystemServiceManager.java public <T extends SystemService> T startService(Class<T> serviceClass){ try { final String name = serviceClass.getName(); Slog.i(TAG, "Starting " + name); Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
// Create the service. if (!SystemService.class.isAssignableFrom(serviceClass)) { thrownew RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName()); } final T service; try { Constructor<T> constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext); //通过反射的方式创建service } catch (InstantiationException ex) { thrownew RuntimeException("Failed to create service " + name + ": service could not be instantiated", ex); } catch (IllegalAccessException ex) { thrownew RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (NoSuchMethodException ex) { thrownew RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (InvocationTargetException ex) { thrownew RuntimeException("Failed to create service " + name + ": service constructor threw an exception", ex); }
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public ActivityTaskManagerService mActivityTaskManager;//声明mActivityTaskManager来管理ActivityStack
/** * The back history of all previous (and possibly still * running) activities. It contains #TaskRecord objects. */ privatefinal ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
/** * List of running activities, sorted by recent usage. * The first entry in the list is the least recently used. * It contains HistoryRecord objects. */ privatefinal ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
/** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. */ ActivityRecord mPausingActivity = null;
/** * This is the last activity that we put into the paused state. This is * used to determine if we need to do an activity transition while sleeping, * when we normally hold the top activity paused. */ ActivityRecord mLastPausedActivity = null;
/** * Activities that specify No History must be removed once the user navigates away from them. * If the device goes to sleep with such an activity in the paused state then we save it here * and finish it later if another activity replaces it on wakeup. */ ActivityRecord mLastNoHistoryActivity = null;
/** * Current activity that is resumed, or null if there is none. */ ActivityRecord mResumedActivity = null;
publicvoidstartActivity(Intent intent, @Nullable Bundle options){ if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN) && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) { if (TextUtils.equals(getPackageName(), intent.resolveActivity(getPackageManager()).getPackageName())) { // Apply Autofill restore mechanism on the started activity by startActivity() final IBinder token = mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); // Remove restore ability from current activity mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY); // Put restore token intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true); } } 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); } }
publicvoidstartActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options){ if (mParent == null) { //第一次启动会执行该分支的代码 options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; }
cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { 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); } } }
privateintexecuteRequest(Request request){ ...... //首先要确定调用者必须存在,否则返回START_PERMISSION_DENIED WindowProcessController callerApp = null; if (caller != null) { callerApp = mService.getProcessController(caller); if (callerApp != null) { callingPid = callerApp.getPid(); callingUid = callerApp.mInfo.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); err = ActivityManager.START_PERMISSION_DENIED; } } ...... //FLAG_ACTIVITY_FORWARD_RESULT具有跨越式传递作用,针对此情况改变调用者 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) { // The new activity is being launched from the same uid as the previous activity // in the flow, and asking to forward its result back to the previous. In this // case the activity is serving as a trampoline between the two, so we also want // to update its launchedFromPackage to be the same as the previous activity. // Note that this is safe, since we know these two packages come from the same // uid; the caller could just as well have supplied that same package name itself // . This specifially deals with the case of an intent picker/chooser being // launched in the app flow to redirect to an activity picked by the user, where // we want the final activity to consider it to have been launched by the // previous app activity. callingPackage = sourceRecord.launchedFromPackage; callingFeatureId = sourceRecord.launchedFromFeatureId; } }
//新建一个ActivityRecord,记录当前的判断结果,接下来调用startActivityUnchecked final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, callingFeatureId, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); mLastStartActivityRecord = r;
// If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid) && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) { mFrozeTaskList = true; mSupervisor.mRecentTasks.setFreezeTaskListReordering(); }
// Compute if there is an existing task that should be used for. final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask(); finalboolean newTask = targetTask == null; mTargetTask = targetTask;
computeLaunchParams(r, sourceRecord, targetTask);
// Check if starting activity on given task or on a new task is allowed. int startResult = isAllowedToStart(r, newTask, targetTask); if (startResult != START_SUCCESS) { return startResult; }
final ActivityRecord targetTaskTop = newTask ? null : targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null) { // Recycle the target task for this launch. startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } else { mAddingToTask = true; }
// If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack(); if (topStack != null) { startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants); if (startResult != START_SUCCESS) { return startResult; } }
if (!mAvoidMoveToFront && mDoResume) { mTargetStack.getStack().moveToFront("reuseOrNewTask", targetTask); if (mOptions != null) { if (mOptions.getTaskAlwaysOnTop()) { mTargetStack.setAlwaysOnTop(true); } } if (!mTargetStack.isTopStackInDisplayArea() && mService.mInternal.isDreaming()) { // Launching underneath dream activity (fullscreen, always-on-top). Run the launch- // -behind transition so the Activity gets created and starts in visible state. mLaunchTaskBehind = true; r.mLaunchTaskBehind = true; } }
mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants, mStartActivity.getUriPermissionsLocked()); if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) { // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs final PackageManagerInternal pmInternal = mService.getPackageManagerInternalLocked(); finalint resultToUid = pmInternal.getPackageUidInternal( mStartActivity.resultTo.info.packageName, 0, mStartActivity.mUserId); pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/, resultToUid /*visible*/, true/*direct*/); } if (newTask) { EventLogTags.writeWmCreateTask(mStartActivity.mUserId, mStartActivity.getTask().mTaskId); } mStartActivity.logStartActivity( EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());
mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(), newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isTopActivityFocusable() || (topTaskActivity != null && topTaskActivity.isTaskOverlay() && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. // Passing {@code null} as the start parameter ensures all activities are made // visible. mTargetStack.ensureActivitiesVisible(null/* starting */, 0/* configChanges */, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityInner"); } mRootWindowContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions); } } mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
// Update the recent tasks list immediately when the activity starts mSupervisor.mRecentTasks.add(mStartActivity.getTask()); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);
if (!mStackSupervisor.readyToResume()) { returnfalse; }
boolean result = false; if (targetStack != null && (targetStack.isTopStackInDisplayArea() || getTopDisplayFocusedStack() == targetStack)) { result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); }
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { boolean resumedOnDisplay = false; final DisplayContent display = getChildAt(displayNdx); for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) { final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx); for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final ActivityStack stack = taskDisplayArea.getStackAt(sNdx); final ActivityRecord topRunningActivity = stack.topRunningActivity(); if (!stack.isFocusableAndVisible() || topRunningActivity == null) { continue; } if (stack == targetStack) { // Simply update the result for targetStack because the targetStack had // already resumed in above. We don't want to resume it again, especially in // some cases, it would cause a second launch failure if app process was // dead. resumedOnDisplay |= result; continue; } if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront // operation, but only consider the top task and stack on that display. stack.executeAppTransition(targetOptions); } else { resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target); } } } if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home // activity is started and resumed, and no recursion occurs. final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } elseif (targetStack == null) { result |= resumeHomeActivity(null/* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } }
@GuardedBy("mService") booleanresumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){ if (mInResumeTopActivity) { // Don't even start recursing. returnfalse; }
boolean result = false; try { // Protect against recursion. mInResumeTopActivity = 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 = topRunningActivity(true/* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); } } finally { mInResumeTopActivity = false; }
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(); } }
/** Prepare and schedule transaction for execution. */ voidscheduleTransaction(ClientTransaction transaction){ transaction.preExecute(this); sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); }
还是回到ActivityThread
1 2 3 4 5 6 7 8 9 10 11
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;
mTransactionExecutor.execute(transaction)
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this)
publicvoidexecute(ClientTransaction transaction){ if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
final IBinder token = transaction.getActivityToken(); if (token != null) { final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed = mTransactionHandler.getActivitiesToBeDestroyed(); final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token); if (destroyItem != null) { if (transaction.getLifecycleStateRequest() == destroyItem) { // It is going to execute the transaction that will destroy activity with the // token, so the corresponding to-be-destroyed record can be removed. activitiesToBeDestroyed.remove(token); } if (mTransactionHandler.getActivityClient(token) == null) { // The activity has not been created but has been requested to destroy, so all // transactions for the token are just like being cancelled. Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n" + transactionToString(transaction, mTransactionHandler)); return; } } }
if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
/** Cycle through all states requested by callbacks and execute them at proper times. */ @VisibleForTesting publicvoidexecuteCallbacks(ClientTransaction transaction){ final List<ClientTransactionItem> callbacks = transaction.getCallbacks(); if (callbacks == null || callbacks.isEmpty()) { // No callbacks to execute, return early. return; } if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");
final IBinder token = transaction.getActivityToken(); ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
// In case when post-execution state of the last callback matches the final state requested // for the activity in this transaction, we won't do the last transition here and do it when // moving to final state instead (because it may contain additional parameters from server). final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest(); finalint finalState = finalStateRequest != null ? finalStateRequest.getTargetState() : UNDEFINED; // Index of the last callback that requests some post-execution state. finalint lastCallbackRequestingState = lastCallbackRequestingState(transaction);
finalint size = callbacks.size(); for (int i = 0; i < size; ++i) { final ClientTransactionItem item = callbacks.get(i); if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item); finalint postExecutionState = item.getPostExecutionState(); finalint closestPreExecutionState = mHelper.getClosestPreExecutionState(r, item.getPostExecutionState()); if (closestPreExecutionState != UNDEFINED) { cycleToPath(r, closestPreExecutionState, transaction); } //********************************* item.execute(mTransactionHandler, token, mPendingActions); item.postExecute(mTransactionHandler, token, mPendingActions); if (r == null) { // Launch activity request will create an activity record. r = mTransactionHandler.getActivityClient(token); }
if (postExecutionState != UNDEFINED && r != null) { // Skip the very last transition and perform it by explicit state request instead. finalboolean shouldExcludeLastTransition = i == lastCallbackRequestingState && finalState == postExecutionState; cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction); } } }
/** * Extended implementation of activity launch. Used when server requests a launch or relaunch. */ @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 && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { HardwareRenderer.preload(); } WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process. GraphicsEnvironment.hintActivityLaunch();
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 { ActivityTaskManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }
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) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; }
// Activity resources must be initialized with the same loaders as the // application context. appContext.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); }
activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { thrownew SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; mLastReportedWindowingMode.put(activity.getActivityToken(), config.windowConfiguration.getWindowingMode()); } r.setState(ON_CREATE);
// updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. synchronized (mResourcesManager) { mActivities.put(r.token, r); }