Activity 的启动分析 ( 9.0 )

2023-10-30

Activity 的启动系统已经做了很多的封装,使得我们在开发的时候不用去关注底层的东西,需要一句代码就可以搞定拉起一个Activity

Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);

用过上面的代码就可以启动一个Acitivty,Activity的启动有很多的重载,但是最终跟踪源码都可以看到调用了一个方法,那么我们来看下startActivityForResult做了什么事情:

public void startActivityForResult(@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);
		}
	}
}

在上面的代码中需要注意的是 

mMainThread.getApplicationThread()

这块代码的返回值是一个ApplicationThread 类型的值,mMainThread 是 ThreadActivity类型,ApplicationThread 则是其一个内部类。通过后面的分析,这两个类在 Activity 的启动过程中发挥着很重要的作用。

接着  Instrumentation 的 execStartActivity 方法启动了activity,返回值是一个ActivityResult ,起始可以看出来就是在这里启动了这个Activity. then:

public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
	IApplicationThread whoThread = (IApplicationThread) contextThread;
	Uri referrer = target != null ? target.onProvideReferrer() : null;
	if (referrer != null) {
		intent.putExtra(Intent.EXTRA_REFERRER, referrer);
	}
	if (mActivityMonitors != null) {
		synchronized (mSync) {
			final int N = mActivityMonitors.size();
			for (int i=0; i<N; i++) {
				final ActivityMonitor am = mActivityMonitors.get(i);
				ActivityResult result = null;
				if (am.ignoreMatchingSpecificIntents()) {
					result = am.onStartActivity(intent);
				}
				if (result != null) {
					am.mHits++;
					return result;
				} else if (am.match(who, null, intent)) {
					am.mHits++;
					if (am.isBlocking()) {
						return requestCode >= 0 ? am.getResult() : null;
					}
					break;
				}
			}
		}
	}
	try {
		intent.migrateExtraStreamToClipData();
		intent.prepareToLeaveProcess(who);
		int result = ActivityManager.getService()
			.startActivity(whoThread, who.getBasePackageName(), intent,
					intent.resolveTypeIfNeeded(who.getContentResolver()),
					token, target != null ? target.mEmbeddedID : null,
					requestCode, 0, null, options);
		checkStartActivityResult(result, intent);
	} catch (RemoteException e) {
		throw new RuntimeException("Failure from system", e);
	}
	return null;
}
从上面的代码中可以看出,是
try {
	intent.migrateExtraStreamToClipData();
	intent.prepareToLeaveProcess(who);
	int result = ActivityManager.getService()
		.startActivity(whoThread, who.getBasePackageName(), intent,
				intent.resolveTypeIfNeeded(who.getContentResolver()),
				token, target != null ? target.mEmbeddedID : null,
				requestCode, 0, null, options);
	checkStartActivityResult(result, intent);
} catch (RemoteException e) {
	throw new RuntimeException("Failure from system", e);
}

 启动了activity。那么这个startActivity是谁来实现的呢?getService() 方法的返回值是什么呢?来看

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
		new Singleton<IActivityManager>() {
			@Override
			protected IActivityManager create() {
				final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
				final IActivityManager am = IActivityManager.Stub.asInterface(b);
				return am;
			}
		};

返回值竟然是一个 IActivityManager 的东西,一个Binder对象,由于ActivityManager.getService()是一个IActivityManager类型的Binder对象,因此它的具体实现是(ActivityManagerService)AMS,可以发现在ActivityManagerNative中,AMS这个Binder对象采用单例模式对外提供,Singleton是一个单例的封装类。

继续查看create方法的具体实现,

IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE) 

获取一个关联了系统服务ActivityManagerService 的 Binder 对象;

IActivityManager.Stub.asInterface(b)

返回一个IActivityManager的代理对象,基于Binder机制,通过调用代理对象的方法,使得系统服务ActivityManagerService对应的方法被调用。可以猜测ActivityManagerService肯定继承了IActivityManager.Stub,事实也确实如此

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

了解下这个Singleton 的源码

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

第一次调用他的get方法时,她会通过create方法来初始化AMS这个Binder对象,在后续的调用中则直接返回创建的对象。所以 startActivity 的过程就交给了 AMS 来完成了

接着checkStratActivityResult 来做了些什么:

 /** @hide */
public static void checkStartActivityResult(int res, Object intent) {
	if (!ActivityManager.isStartResultFatalError(res)) {
		return;
	}

	switch (res) {
		case ActivityManager.START_INTENT_NOT_RESOLVED:
		case ActivityManager.START_CLASS_NOT_FOUND:
			if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
				throw new ActivityNotFoundException(
						"Unable to find explicit activity class "
						+ ((Intent)intent).getComponent().toShortString()
						+ "; have you declared this activity in your AndroidManifest.xml?");
			throw new ActivityNotFoundException(
					"No Activity found to handle " + intent);
		case ActivityManager.START_PERMISSION_DENIED:
			throw new SecurityException("Not allowed to start activity "
					+ intent);
		case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
			throw new AndroidRuntimeException(
					"FORWARD_RESULT_FLAG used while also requesting a result");
		case ActivityManager.START_NOT_ACTIVITY:
			throw new IllegalArgumentException(
					"PendingIntent is not an activity");
		case ActivityManager.START_NOT_VOICE_COMPATIBLE:
			throw new SecurityException(
					"Starting under voice control not allowed for: " + intent);
		case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
			throw new IllegalStateException(
					"Session calling startVoiceActivity does not match active session");
		case ActivityManager.START_VOICE_HIDDEN_SESSION:
			throw new IllegalStateException(
					"Cannot start voice activity on a hidden session");
		case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
			throw new IllegalStateException(
					"Session calling startAssistantActivity does not match active session");
		case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
			throw new IllegalStateException(
					"Cannot start assistant activity on a hidden session");
		case ActivityManager.START_CANCELED:
			throw new AndroidRuntimeException("Activity could not be started for "
					+ intent);
		default:
			throw new AndroidRuntimeException("Unknown error code "
					+ res + " when starting " + intent);
	}
}

哦哦哦,我经常忘记在清单文件中配置Activity 就是这里报出来的。。 

OK,接着深入,来看AMS 中 是怎么实现的 startActivity 的

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }

在代码最后这个启动的锅还在往下甩。。甩到了最后一行代码,那就来看,ActivityStartController.obtainStarter,拿到  ActivityStarter  去执行 execute 方法,继续看源码

/**
 * Starts an activity based on the request parameters provided earlier.
 * @return The starter result.
 */
int execute() {
	try {
		// TODO(b/64750076): Look into passing request directly to these methods to allow
		// for transactional diffs and preprocessing.
		if (mRequest.mayWait) {
			return startActivityMayWait(mRequest.caller, mRequest.callingUid,
					mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
					mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
					mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
					mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
					mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
					mRequest.inTask, mRequest.reason,
					mRequest.allowPendingRemoteAnimationRegistryLookup);
		} else {
			return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
					mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
					mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
					mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
					mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
					mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
					mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
					mRequest.outActivity, mRequest.inTask, mRequest.reason,
					mRequest.allowPendingRemoteAnimationRegistryLookup);
		}
	} finally {
		onExecutionComplete();
	}
}

由于我们在AMS的startActivityAsUser中调用了setMayWait方法,也就是ActivityStarter的setMayWait方法,所以第一个if判断条件满足

那就看 startActivityMayWait 方法的实现

private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
        // Refuse possible leaked file descriptors
        ......
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

        ....
    }

那就继续 startActivity (这传的参数是我见过最多的了。。)

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {

	if (TextUtils.isEmpty(reason)) {
		throw new IllegalArgumentException("Need to specify a reason.");
	}
	mLastStartReason = reason;
	mLastStartActivityTimeMs = System.currentTimeMillis();
	mLastStartActivityRecord[0] = null;

	mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
			aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
			callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
			options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
			inTask, allowPendingRemoteAnimationRegistryLookup);

	if (outActivity != null) {
		// mLastStartActivityRecord[0] is set in the call to startActivity above.
		outActivity[0] = mLastStartActivityRecord[0];
	}

	return getExternalResult(mLastStartActivityResult);
}

又把startActivity 的锅 甩给了 startActivity ...

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
	int err = ActivityManager.START_SUCCESS;
	// Pull the optional Ephemeral Installer-only bundle out of the options early.
	final Bundle verificationBundle
			= options != null ? options.popAppVerificationBundle() : null;

	ProcessRecord callerApp = null;
	if (caller != null) {
		callerApp = mService.getRecordForAppLocked(caller);
		if (callerApp != null) {
			callingPid = callerApp.pid;
			callingUid = callerApp.info.uid;
		} else {
			Slog.w(TAG, "Unable to find app for caller " + caller
					+ " (pid=" + callingPid + ") when starting: "
					+ intent.toString());
			err = ActivityManager.START_PERMISSION_DENIED;
		}
	}

	final int userId = aInfo != null && aInfo.applicationInfo != null
			? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

	if (err == ActivityManager.START_SUCCESS) {
		Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
				+ "} from uid " + callingUid);
	}

	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;
			}
		}
	}

	final int 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;
		}
	}

	if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
		// We couldn't find a class that can handle the given Intent.
		// That's the end of that!
		err = ActivityManager.START_INTENT_NOT_RESOLVED;
	}

	if (err == ActivityManager.START_SUCCESS && aInfo == null) {
		// We couldn't find the specific class specified in the Intent.
		// Also the end of the line.
		err = ActivityManager.START_CLASS_NOT_FOUND;
	}

	if (err == ActivityManager.START_SUCCESS && sourceRecord != null
			&& sourceRecord.getTask().voiceSession != null) {
		// If this activity is being launched as part of a voice session, we need
		// to ensure that it is safe to do so.  If the upcoming activity will also
		// be part of the voice session, we can only launch it if it has explicitly
		// said it supports the VOICE category, or it is a part of the calling app.
		if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
				&& sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
			try {
				intent.addCategory(Intent.CATEGORY_VOICE);
				if (!mService.getPackageManager().activitySupportsIntent(
						intent.getComponent(), intent, resolvedType)) {
					Slog.w(TAG,
							"Activity being started in current voice task does not support voice: "
									+ intent);
					err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
				}
			} catch (RemoteException e) {
				Slog.w(TAG, "Failure checking voice capabilities", e);
				err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
			}
		}
	}

	if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
		// If the caller is starting a new voice session, just make sure the target
		// is actually allowing it to run this way.
		try {
			if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
					intent, resolvedType)) {
				Slog.w(TAG,
						"Activity being started in new voice task does not support: "
								+ intent);
				err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
			}
		} catch (RemoteException e) {
			Slog.w(TAG, "Failure checking voice capabilities", e);
			err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
		}
	}

	final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();

	if (err != START_SUCCESS) {
		if (resultRecord != null) {
			resultStack.sendActivityResultLocked(
					-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
		}
		SafeActivityOptions.abort(options);
		return err;
	}

	boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
			requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
			inTask != null, callerApp, resultRecord, resultStack);
	abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
			callingPid, resolvedType, aInfo.applicationInfo);

	// 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 (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
			callingUid, checkedOptions)) {
		// activity start was intercepted, e.g. because the target user is currently in quiet
		// mode (turn off work) or the target application is suspended
		intent = mInterceptor.mIntent;
		rInfo = mInterceptor.mRInfo;
		aInfo = mInterceptor.mAInfo;
		resolvedType = mInterceptor.mResolvedType;
		inTask = mInterceptor.mInTask;
		callingPid = mInterceptor.mCallingPid;
		callingUid = mInterceptor.mCallingUid;
		checkedOptions = mInterceptor.mActivityOptions;
	}

	if (abort) {
		if (resultRecord != null) {
			resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
					RESULT_CANCELED, null);
		}
		// We pretend to the caller that it was really started, but
		// they will just get a cancel result.
		ActivityOptions.abort(checkedOptions);
		return START_ABORTED;
	}

	// 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);

			final int 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;

			resolvedType = null;
			callingUid = realCallingUid;
			callingPid = realCallingPid;

			rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
					computeResolveFilterUid(
							callingUid, realCallingUid, mRequest.filterCallingUid));
			aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
					null /*profilerInfo*/);

			if (DEBUG_PERMISSIONS_REVIEW) {
				Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
						true, false) + "} from uid " + callingUid + " on display "
						+ (mSupervisor.mFocusedStack == null
						? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
			}
		}
	}

	// If we have an ephemeral app, abort the process of launching the resolved intent.
	// Instead, launch the ephemeral installer. Once the installer is finished, it
	// starts either the intent we resolved here [on install error] or the ephemeral
	// app [on install success].
	if (rInfo != null && rInfo.auxiliaryInfo != null) {
		intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
				callingPackage, verificationBundle, resolvedType, userId);
		resolvedType = null;
		callingUid = realCallingUid;
		callingPid = realCallingPid;

		aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
	}

	ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
			callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
			resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
			mSupervisor, checkedOptions, sourceRecord);
	if (outActivity != null) {
		outActivity[0] = r;
	}

	if (r.appTimeTracker == null && sourceRecord != null) {
		// If the caller didn't specify an explicit time tracker, we want to continue
		// tracking under any it has.
		r.appTimeTracker = sourceRecord.appTimeTracker;
	}

	final ActivityStack stack = mSupervisor.mFocusedStack;

	// If we are starting an activity that is not from the same uid as the currently resumed
	// one, check whether app switches are allowed.
	if (voiceSession == null && (stack.getResumedActivity() == null
			|| stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
		if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
				realCallingPid, realCallingUid, "Activity start")) {
			mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
					sourceRecord, startFlags, stack, callerApp));
			ActivityOptions.abort(checkedOptions);
			return ActivityManager.START_SWITCHES_CANCELED;
		}
	}

	if (mService.mDidAppSwitch) {
		// This is the second allowed switch since we stopped switches,
		// so now just generally allow switches.  Use case: user presses
		// home (switches disabled, switch to home, mDidAppSwitch now true);
		// user taps a home icon (coming from home so allowed, we hit here
		// and now allow anyone to switch again).
		mService.mAppSwitchesAllowedTime = 0;
	} else {
		mService.mDidAppSwitch = true;
	}

	mController.doPendingActivityLaunches(false);

	return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
			true /* doResume */, checkedOptions, inTask, outActivity);
}

这个方法真够长的,分解来看

1、首先检查了启动权限。

if (caller != null) {
	callerApp = mService.getRecordForAppLocked(caller);
	if (callerApp != null) {
		callingPid = callerApp.pid;
		callingUid = callerApp.info.uid;
	} else {
		Slog.w(TAG, "Unable to find app for caller " + caller
				+ " (pid=" + callingPid + ") when starting: "
				+ intent.toString());
		err = ActivityManager.START_PERMISSION_DENIED;
	}
}

2、获取调用者 ActivityRecord,ActivityRecord 在 system_server 代表一个 activity 对象

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;
		}
	}
}

3、中间大量的错误判断

4:构建出 AMS 端的一个Activityrecord对象

ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);

然后继续执行甩锅的操作 startActivity 

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);

再来分析这个startActivity

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
	int result = START_CANCELED;
	try {
		mService.mWindowManager.deferSurfaceLayout();
		result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
				startFlags, doResume, options, inTask, outActivity);
	} finally {
		// If we are not able to proceed, disassociate the activity from the task. Leaving an
		// activity in an incomplete state can lead to issues, such as performing operations
		// without a window container.
		final ActivityStack stack = mStartActivity.getStack();
		if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
			stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
					null /* intentResultData */, "startActivity", true /* oomAdj */);
		}
		mService.mWindowManager.continueSurfaceLayout();
	}

	postStartActivityProcessing(r, result, mTargetStack);

	return result;
}

在try 块中 执行startActivityUnchecked 

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

	setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
			voiceInteractor);
    // 1
	computeLaunchingTaskFlags();
    
	computeSourceStack();

	mIntent.setFlags(mLaunchFlags);
    // 2
	ActivityRecord reusedActivity = getReusableIntentActivity();

   ....

	if (reusedActivity != null) {
		   ...

			if (top != null) {
				if (top.frontOfTask) {
					// Activity aliases may mean we use different intents for the top activity,
					// so make sure the task now has the identity of the new intent.
					top.getTask().setIntent(mStartActivity);
				}
				deliverNewIntent(top);
			}
		}

		...
		 
	}
    // 3
	if (mStartActivity.packageName == null) {
		final ActivityStack sourceStack = mStartActivity.resultTo != null
				? mStartActivity.resultTo.getStack() : null;
		if (sourceStack != null) {
			sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
					mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
					null /* data */);
		}
		ActivityOptions.abort(mOptions);
		return START_CLASS_NOT_FOUND;
	}
   
   
   
	// 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 = mSupervisor.mFocusedStack;
	final ActivityRecord topFocused = topStack.getTopActivity();
	final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
	final boolean dontStart = top != null && mStartActivity.resultTo == null
			&& top.realActivity.equals(mStartActivity.realActivity)
			&& top.userId == mStartActivity.userId
			&& top.app != null && top.app.thread != null
			&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
			|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
	if (dontStart) {
		// For paranoia, make sure we have correctly resumed the top activity.
		topStack.mLastPausedActivity = null;
		if (mDoResume) {
			mSupervisor.resumeFocusedStackTopActivityLocked();
		}
		ActivityOptions.abort(mOptions);
		if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
			// We don't need to start a new activity, and the client said not to do
			// anything if that is the case, so this is it!
			return START_RETURN_INTENT_TO_CALLER;
		}
        // 4    
		deliverNewIntent(top);

		// Don't use mStartActivity.task to show the toast. We're not starting a new activity
		// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
		mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
				preferredLaunchDisplayId, topStack);

		return START_DELIVERED_TO_TOP;
	}

	boolean newTask = false;
	final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
			? mSourceRecord.getTask() : null;

	// 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;
		result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
	} else if (mSourceRecord != null) {
		result = setTaskFromSourceRecord();
	} else if (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;
	}

	mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
			mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
	mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
			mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
	if (newTask) {
		EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
				mStartActivity.getTask().taskId);
	}
	ActivityStack.logStartActivity(
			EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
	mTargetStack.mLastPausedActivity = null;

	mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
    // 5
	mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
			mOptions);
	if (mDoResume) {
		final ActivityRecord topTaskActivity =
				mStartActivity.getTask().topRunningActivityLocked();
		if (!mTargetStack.isFocusable()
				|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
				&& 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.
			mTargetStack.ensureActivitiesVisibleLocked(null, 0, !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.
			mService.mWindowManager.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.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
				mTargetStack.moveToFront("startActivityUnchecked");
			}
            //  6
			mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
					mOptions);
		}
	} else if (mStartActivity != null) {
		mSupervisor.mRecentTasks.add(mStartActivity.getTask());
	}
	mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

	mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
			preferredLaunchDisplayId, mTargetStack);

	return START_SUCCESS;
}

这里 主要 做了 一下几件事情,在代码中 标注了 1--5

1、主要是计算启动activity的flag

2、获取是否有可以复用的activity 

3、找不到启动的activity

4、找到复用的activity就将此 activity 派到栈顶

5、startActivityLocked 又做了一些事情: 

    5.1 调整activity在task中的位置,将其放在顶部
    这个方法主要是如果创建了新的task那么将新的task至于Stack的前台,如果没有新建task那么则插入到task的顶部

// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
	// Last activity in task had been removed or ActivityManagerService is reusing task.
	// Insert or replace.
	// Might not even be in.
	insertTaskAtTop(rTask, r);
}

    5.2 向wms添加token值

if (r.getWindowContainerController() == null) {
    r.createWindowContainer();
}

   5.3 添加启动动画

mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);

    5.4   添加 启动 窗口

r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));

6、调用resumeFocusedStackTopActivityLocked  ,在这个方法中 有调用了

if (targetStack != null && isFocusedStack(targetStack)) {
     return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
	if (mStackSupervisor.inResumeTopActivity) {
		// Don't even start recursing.
		return false;
	}

	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;
	}

	return result;
}

接着调用  result = resumeTopActivityInnerLocked(prev, options);

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
	 ...
		synchronized(mWindowManager.getWindowManagerLock()) {
			...

			try {
				...
			} catch (Exception e) {
				...
				mStackSupervisor.startSpecificActivityLocked(next, true, false);
				...
			}
		}

		...
	} else {
		 ....
		mStackSupervisor.startSpecificActivityLocked(next, true, true);
	}

	if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
	return true;
}

代码实在是多啊,截取了关键的跳转下一个的方法:mStackSupervisor.startSpecificActivityLocked(next, true, true);

void startSpecificActivityLocked(ActivityRecord r,
		boolean andResume, boolean checkConfig) {
	// Is this activity's application already running?
	ProcessRecord app = mService.getProcessRecordLocked(r.processName,
			r.info.applicationInfo.uid, true);

	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.
	}

	mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
			"activity", r.intent.getComponent(), false, false, true);
}

看到了曙光, realStartActivityLocked(r, app, andResume, checkConfig);  终于要启动 activity 

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

        ....
                // 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.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

                ...

        return true;
    }

 mService.getLifecycleManager().scheduleTransaction(clientTransaction);  

说明:

ActivityManagerService mService;

ClientLifecycleManager getLifecycleManager() {
     return mLifecycleManager;
}

其实还是调用了transaction

void scheduleTransaction(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();
	}
}

值得注意的是 

IApplicationThread client = transaction.getClient();

这个的client 的实现 是在 ActivityThread 的 ApplicationThread

那么程序就从服务端进程进入到了 客户 端进程

由于class ActivityThread extends ClientTransactionHandler继承的是ClientTransactionHandler对象,那么调用的是父类的

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

发送一个消息到ActivityThread的主线程

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;

进而执行 execute方法

 /**
 * Resolve transaction.
 * First all callbacks will be executed in the order they appear in the list. If a callback
 * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
 * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
 * either remain in the initial state, or last state needed by a callback.
 */
public void execute(ClientTransaction transaction) {
	final IBinder token = transaction.getActivityToken();
	log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

	executeCallbacks(transaction);

	executeLifecycleState(transaction);
	mPendingActions.clear();
	log("End resolving transaction");
}

进而执行  executeLifecycleState 方法

/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
    ...

	// Execute the final transition with proper parameters.
	lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
	lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

lifecycleItem 是 ActivityLifecycleItem 类型的对象
而ActivityLifecycleItem是一个抽象类
会调用两个关键的方法

executeCallbacks(transaction);
executeLifecycleState(transaction);
executeCallbacks(transaction);会调用 item 的 execute 方法
public void executeCallbacks(ClientTransaction transaction) {
	...
	for (int i = 0; i < size; ++i) {
		...
        final ClientTransactionItem item = callbacks.get(i);
		item.execute(mTransactionHandler, token, mPendingActions);
		item.postExecute(mTransactionHandler, token, mPendingActions);
		...
		}
	}
}

每一个item 又是从list 里面取出来的, 这个list 的添加就在 我们刚刚看到的 realStartActivityLocked 看到曙光的那一刻,这样一行代码

 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));

这个callback 方法找出来是这样的,传入的参数是  ClientTransactionItem 类型

/**
     * Add a message to the end of the sequence of callbacks.
     * @param activityCallback A single message that can contain a lifecycle request/callback.
     */
    public void addCallback(ClientTransactionItem activityCallback) {
        if (mActivityCallbacks == null) {
            mActivityCallbacks = new ArrayList<>();
        }
        mActivityCallbacks.add(activityCallback);
    }

  开始 执行 LaunchActivityItem 的 excute 方法

  @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

  Client是 ClientTransactionHandler 类型的数据,也就是 ActivityThread,进入执行到 ActivityThread 的 handleLaunchActivity 方法

    /**
     * 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) {
            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();
            }
        }

        return a;
    }

  接着执行 

 final Activity a = performLaunchActivity(r, customIntent);

主要是通过反射的机制创建一个activity对象,调用其attach方法,并且执行oncreate方法,也就是activity的oncreate方法可能被回调到,attach方法主要做了三件事情
1:关联一个context对象
2:创建phonewindow对象
3:为activity设置windowmanager对象

 

执行完成 executeCallbacks  方法执行  executeLifecycleState 方法

 /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(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);
    }

executeLifecycleState的入口有一个重要的方法

final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();

此时lifecycleItem对象应该是ResumeActivityItem类型的对象

cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

ResumeActivityItem的目标状态是ON_Resumed的
接下来看cycleToPath的计算
调用的是同名的cycleToPath,并且不包含最后的状态

final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);

start值的计算为
final int start = r.getLifecycleState();也就是ON_CREATE状态
finish状态值也就是ON_RESUMED状态

最后在getLifecyclePath 中计算 当前Activity 的声明周期

 @VisibleForTesting
    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
        ....
        if (finish >= start) {
            // just go there
            for (int i = start + 1; i <= finish; i++) {
                mLifecycleSequence.add(i);
            }
        }
        ....
    }

根据上面的计算很显然是进入到该判断条件,也就是添加了两种状态onstart,onresume
然后执行方法  performLifecycleSequence(r, path);

private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            log("Transitioning to state: " + state);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                            false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY");
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(r.token, false /* show */,
                            0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                            "LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }

也就是回调ActivityThread的handleStartActivity和handleResumeActivity方法

handleStartActivity   和  handleResumeActivity 都是的 

ClientTransactionHandler的抽象方法,

因为有这么个关系

public final class ActivityThread extends ClientTransactionHandler {

所以 这两个 handleStartActivity和handleResumeActivity方法 就都在主线程执行了。

handleResumeActivity方法

该方法主要是将decorView添加到windowmanager里面,并且将窗口类型设置为
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
然后调用activity的makeVisibile方法将其设为可见状态
这样一个activity基本启动完成,后续的便是窗口的添加,relayout等其他操作

 

参考文章:Android 组件--Activity 启动流程(9.0)

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Activity 的启动分析 ( 9.0 ) 的相关文章

  • 订阅购买后失效日期无效

    我有一个带有应用内订阅的 Android 应用程序 用户购买订阅后 我通过 Google API 通过我们的后端请求 validUntilTimestampMsec 和 initiationTimestampMsec 返回的时间戳 init
  • Android 上的多处理

    我一直在 Android 上执行一些测试 以验证并行化算法 如 FFT 的性能可以提高多少 我通过使用带有 JNI FFTW 的 pthread 和 Java 线程 来自 JTransforms 来实现这些算法 我没有像预期那样通过使用线程
  • 按钮点击和声音之间的延迟

    我不太明白为什么按钮点击和声音之间有延迟 以下是我的代码 button Button findViewById R id playBtn final MediaPlayer playButtonClick MediaPlayer creat
  • Context.startForegroundService 然后没有调用Service.startForeground

    这是我的 BroadcastReciever 类 该类处理启动电话状态 Code public class BroadCastRecieverBoot extends BroadcastReceiver Override public vo
  • 使用 ViewPager 从 Activity 到 Fragment 的通信

    我有一个 Activity 和两个 Fragmentstablayout含有一个viewpager 现在我可以通过实现谷歌的指南回调接口从片段到活动进行通信 但我怎样才能以另一种方式沟通从活动到片段 如果活动中发生了一些事情 外部事件 我想
  • 使用 HashMap 映射 String 和 int

    我有一个显示国家 地区名称的列表视图 我已将名称作为字符串数组存储在 strings xml 中 称为国家 地区名称 在填充 ListView 时 我使用从 strings xml 读取的 ArrayAdapter String count
  • Android 操作栏 SearchView 作为自动完成功能?

    我在操作栏中使用 SearchView 我想在搜索视图上使用自动完成功能来从数据库中获取结果 这可能吗 或者我是否需要使用自定义文本框 然后添加自动完成功能 所以我只需要对 v7 版本执行此操作 并沮丧地发现我不能简单地使用 ArrayAd
  • 从txt文件中读取数据而不下载它?

    我想从提供的文本文件中解析信息 有没有一种方法可以在应用程序中执行此操作 而无需先下载文件 以某种方式传输文本内容 打开到 URL 的 Http 连接 使用内置 HttpURLConnection 或使用 commons httpclien
  • 检测Android N版本代码

    是否可以检测用户是否运行 Android N 我有一台装有 Android N 开发者预览版的 Nexus 6 如果我尝试获取构建版本Build VERSION SDK INT 它返回 23 等于 Android Marshmallow Q
  • 使用audioSessionId值实例化AudioFx类?

    我已经阅读了 Android API 并尝试在互联网上搜索有关声明自定义audioSessionId然后用它audioSessionId初始化 AudioFx 类并为我的 MediaPlayer 或 AudioTrack 分配硬编码audi
  • 如何以编程方式关闭画中画

    我在使用画中画模式时遇到了这个问题 当从 PIP 本身以外的其他位置再次打开 Activity 时 我想关闭 PIP 画中画 不是来自关闭按钮 我想要与 youtube 相同的场景 即当用户单击 PIP 画中画 时 它会打开相同的活动 但是
  • android gradle插件-离线安装

    我必须在离线电脑上安装 android gradle 插件 通过谷歌搜索 我了解到我可以通过本地 Maven 存储库来做到这一点 但从不成功的尝试和所有关于这个问题的质量保证中我知道这并不简单 我从来没有和maven一起工作过 有经验的人可
  • java.exe 以非零退出值 1 结束

    只是为了开始 我并不是真正尝试从 Android 中的 xlsx 文件中读取单元格 我已经尝试了几乎所有我在 Google 上搜索到的内容 但是每次 在两台不同的 PC 上 都是 Java 1 7 0 79 当我尝试构建 运行 这个应用程序
  • Android 10 中没有设备筛选器的 USB_DEVICE_ATTACHED

    我正在开发一个 Android 应用程序 它在清单中为 BroadcastReceiver 注册了四个意图过滤器 这些都是 android hardware usb action USB DEVICE ATTACHED android ha
  • React Native v0.71.8 React-native-vector-icons 你看不到的图标

    我在用react native版本v0 71 8 我安装了react native vector icons库 但图标未显示 似乎链接在最新版本的 React Native 中不再起作用 所以我按照说明进行操作 但它不再编译 出现以下错误
  • 如何在捆绑中存储稀疏数组

    我有一个SparseArray
  • 布局聊天气泡问题:TextView 占满整个屏幕

    我正在研究泡泡聊天 我使用具有两种布局的适配器 一种用于传入消息 另一种用于我的消息 适配器工作正常 我的问题在于传入布局 无法很好地显示传入时间文本 当消息文本增长时 会填满屏幕的整个宽度 并隐藏消息时间的文本 第一个问题 如何才能实现这
  • android中如何将字符串转换为unicode

    我正在解析一些unicodes from json to my android应用程序 API 给出unicodes像这样的图标 ue600 当我将这个unicode直接添加到textview like textview setText u
  • 突出显示菜单抽屉/滑动菜单中的所选项目

    使用的库 https github com SimonVT android menudrawer https github com SimonVT android menudrawer https github com JakeWharto
  • Android IntentService无法实例化类;没有空构造函数

    我有一个MainActivity需要访问在线 API 从而使用网络资源 的类 这需要我在单独的文件中创建的后台线程HttpRequestService java MainActivity java public class MainActi

随机推荐

  • hdu 1074 Doing Homework

    Problem acm hdu edu cn showproblem php pid 1074 题意 n 份作业 分别给出名字 完成所需时间 cost 最迟上交时间 deadline 作业每迟交一天扣一分 问最少的扣分数 Analysis
  • 关于.sln和.suo文件

    sln 和 suo都是是解决方案文件 sln Visual Studio Solution 它通过为环境提供对项目 项目项和解决方案项在磁盘上位置的引用 可将它们组织到解决方案中 包含了较为通用的信息 包括解决方案所包含项目的列表 解决方案
  • TCL foreach的用法

    总结放于前 foreach var list body是foreach的的常见用法 foreach为关键字 var为形参 list为数据容器 数组等 body为函数块 程序每次在程序执行时从list中取到值并赋给形参var 函数块利用var
  • sql外连接内连接

    内连接 两表的交集 符合要求的数据列出来 外连接 左外连接就是查询 join左边表中的所有数据 并且把join右边表中对应的数据查询出来 主表的数据去跟从表一一比较 有就全部列出来 没有就也要列出一条 主表数据全要 他的从表数据变成Null
  • springboot集成Redis

    springboot集成Redis 1 windows平台安装Redis 2 引入依赖 3 修改配置文件 4 启动类添加注解 5 指定缓存哪个方法 6 配置Redis的超时时间 小BUG 测试 对于项目中一些访问量较大的接口 配置上Redi
  • python连接mysql数据库报错pymysql.err.OperationalError

    一 报错信息 pymysql err OperationalError 1045 Access denied for user root localhost using password YES Traceback most recent
  • docker基础:docker stats监控容器资源消耗

    docker stats docker stats 命令用来显示容器使用的系统资源 默认情况下 stats 命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl c 下面是输出的主要内容 CONTAINER 以短格式显示容器的 ID
  • 基于反事实因果推断的度小满额度模型

    本文约4400字 建议阅读9分钟 本文从三个角度与你分享基于反事实因果推断的度小满额度模型 1 因果推断的研究范式 1 相关性与因果性 2 三大基本假设 2 因果推断的框架演进 1 从随机数据到观测数据 2 反事实表示学习 3 反事实额度模
  • 四川百幕晟科技有限公司:抖音没有视频怎么开店铺?

    抖音是中国最受欢迎的短视频平台之一 吸引了数亿用户 很多电商卖家希望利用抖音平台开展业务 但他们可能没有视频资源 幸运的是 抖音还提供了非视频商店功能 允许卖家开设自己的商店并在抖音上推广产品 本文将详细介绍在抖音上开店的步骤 并探讨如何在
  • 破解windows明文密码

    之前看了法国人写的一个软件 mimikatz 可以直接获取windows下的明文密码 简直是丧心病狂 作者已经开源 大家可以去谷歌一下 用SVN下载了源码 是vs2010的工程 然后按照下面命令开始看代码 privilege debug i
  • SQLAlchemy映射已有数据表

    方法一 手动创建数据表模型类进行映射 映射的表必须要有主键 配置数据库连接参数 class Config SQLALCHEMY DATABASE URI mysql pymysql root 123456 localhost 3306 te
  • mysql5.7 免安装版的配置过程

    1 去官网下载mysql 5 7 2 解压压缩包 首先给压缩包重命名一下 修改为你自己想要的 将解压目录下默认文件 my default ini 拷贝一份 改名 my ini 3 修改一下my ini 文件里的内容 client port
  • 基于卷积神经网络结合注意力机制长短记忆网络CNN-LSTM-Attention实现风电功率多输入单输出回归预测附matlab代码

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 更多Matlab仿真内容点击 智能优化算法 神经网络预测 雷达通信 无线传感器 电力系统 信号
  • Kafka安装及测试

    系统环境 Linux Ubuntu 16 04 jdk 7u75 linux x64 相关知识 Kafka是由LinkedIn开发的一个分布式的消息系统 使用Scala编写 它因可以水平扩展和高吞吐率而被广泛使用 目前越来越多的开源分布式处
  • WPF编程,通过Path类型制作沿路径运动的动画另一种方法。

    上一篇文章给了一个这方面的例子 那个文章里是通过后台按钮事件进行动画的开始 停止 继续等 这里给出的是通过前台XAML来实现 1 前台 定义路径 定义运动的主体 这里是一圆
  • IEEE 754 round-to-nearest-even

    IEEE 754 二进制的向偶舍入 舍入的值保证最靠近原浮点数值 如果舍入为中间值 即舍还是入距离相等 那么按其最末尾一位是奇数 则入 如果为偶数 则舍 下面例子说明 xxx yyyyy10000 x为实数任意值 y为任意值 最末尾y为需要
  • 用C++实现简单的小游戏

    采用面向对象的编程思想 在头文件中引入acllic图形库 实现c 控制图片以及生成可视化窗口 所需工具 acllib图形库下载地址 acl图形库下载地址 win32位项目的创建 通过visual studio创建win32项目 三张图片 t
  • python 数据分析--数据处理工具Pandas(2)

    数据处理模块 Pandas 4 Pandas处理字符串和日期数据 5 Pandas 数据清洗 5 1 重复观测处理 5 2 缺失值处理 5 2 1 删除法 5 2 2 替换法 5 3 异常值处理 6 获取数据子集 7 透视表 合并与连接 分
  • Transformer中的position encoding(位置编码一)

    本文主要讲解Transformer 中的 position encoding 在当今CV的目标检测最前沿 都离不开position encoding 在DETR VIT MAE框架中应用广泛 下面谈谈我的理解 一般position enco
  • Activity 的启动分析 ( 9.0 )

    Activity 的启动系统已经做了很多的封装 使得我们在开发的时候不用去关注底层的东西 需要一句代码就可以搞定拉起一个Activity Intent intent new Intent this TestActivity class st