赞
踩
针对**>26** sdk 版本
在自己创建的Activity中调用startActivity()方法,其实调用流程为,在ContextWrapper中调用startActivity()方法 此方法为Context的抽象方法,由Activity重写;
public class Activity extends ContextThemeWrapper.........
public class ContextThemeWrapper extends ContextWrapper..........
pulic class ContextWrapper extends Context.........
public abstract class Context {
.......................
//此方法由Activity重写
public abstract void startActivity(@RequiresPermission Intent intent);
}
在Activity中的重写为:
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}`
可以看出此时实现的是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); } } }
mParent 代表的是 ActivityGroup 最开始被用来在一个界面嵌入多个子Activity 在 api 13被废弃,系统推荐使用Fragment来代替 ActivityGroup ,注意的是 mMainThread.getApplicationThread 获取的是 ApplicationThread 它是 ActivityThread 的一个内部类;重点看
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
从这个方法可以看出使用的是Instrumentation的execStartActivity()方法:
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; }
可以看出启动Activity调用的是ActivityManager.getService();在ActivityManager中代码实现如下:
/** * @hide */ 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; } };
Singleton是一个抽象类,有一个抽象方法create()。有一个get()方法,内部通过单例模式创建T对象,调用create方法创建T对象,且只会创建一次T对象。
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;
}
}
}
ServiceManager.getService(Context.ACTIVITY_SERVICE)获取一个关联了系统服务ActivityManagerService的Binder对象;IActivityManager.Stub.asInterface(b)返回一个IActivityManager的代理对象,基于Binder机制,通过调用代理对象的方法,使得系统服务ActivityManagerService对应的方法被调用。可以猜测ActivityManagerService肯定继承了IActivityManager.Stub。可以发现是通过AIDL的方式实现了服务的代理,ActivityManagerService源码如下:
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback..........
由上可知,Activity实际上是由 ActivityManager.getService() 来启动的,而 ActivityManager.getService() 获取到的实际上是 AMS 因此 Activity 的启动过程又转移到 AMS 中,则ActivityManager.getService(). 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) { enforceNotIsolatedCaller("startActivity"); userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, bOptions, false, userId, null, null, "startActivityAsUser"); }
查看ActivityStarter 的 ActivityStarter.startActivityMayWait源码:
final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask, String reason) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } mSupervisor.mActivityMetricsLogger.notifyActivityLaunching(); boolean componentSpecified = intent.getComponent() != null; // Save a copy in case ephemeral needs it final Intent ephemeralIntent = new Intent(intent); // Don't modify the client's object! intent = new Intent(intent); if (componentSpecified && intent.getData() != null && Intent.ACTION_VIEW.equals(intent.getAction()) && mService.getPackageManagerInternalLocked() .isInstantAppInstallerComponent(intent.getComponent())) { // intercept intents targeted directly to the ephemeral installer the // ephemeral installer should never be started with a raw URL; instead // adjust the intent so it looks like a "normal" instant app launch intent.setComponent(null /*component*/); componentSpecified = false; } ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); if (rInfo == null) { UserInfo userInfo = mSupervisor.getUserInfo(userId); if (userInfo != null && userInfo.isManagedProfile()) { // Special case for managed profiles, if attempting to launch non-cryto aware // app in a locked managed profile from an unlocked parent allow it to resolve // as user will be sent via confirm credentials to unlock the profile. UserManager userManager = UserManager.get(mService.mContext); boolean profileLockedAndParentUnlockingOrUnlocked = false; long token = Binder.clearCallingIdentity(); try { UserInfo parent = userManager.getProfileParent(userId); profileLockedAndParentUnlockingOrUnlocked = (parent != null) && userManager.isUserUnlockingOrUnlocked(parent.id) && !userManager.isUserUnlockingOrUnlocked(userId); } finally { Binder.restoreCallingIdentity(token); } if (profileLockedAndParentUnlockingOrUnlocked) { rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); } } } // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); ActivityOptions options = ActivityOptions.fromBundle(bOptions); ActivityStackSupervisor.ActivityContainer container = (ActivityStackSupervisor.ActivityContainer)iContainer; synchronized (mService) { if (container != null && container.mParentActivity != null && container.mParentActivity.state != RESUMED) { // Cannot start a child activity if the parent is not resumed. return ActivityManager.START_CANCELED; } final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { callingPid = -1; } else if (caller == null) { callingPid = realCallingPid; callingUid = realCallingUid; } else { callingPid = callingUid = -1; } final ActivityStack stack; if (container == null || container.mStack.isOnHomeDisplay()) { stack = mSupervisor.mFocusedStack; } else { stack = container.mStack; } stack.mConfigWillChange = globalConfig != null && mService.getGlobalConfiguration().diff(globalConfig) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = " + stack.mConfigWillChange); final long origId = Binder.clearCallingIdentity(); if (aInfo != null && (aInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { // This may be a heavy-weight process! Check to see if we already // have another, different heavy-weight process running. if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { final ProcessRecord heavy = mService.mHeavyWeightProcess; if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid || !heavy.processName.equals(aInfo.processName))) { int appCallingUid = callingUid; if (caller != null) { ProcessRecord callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { appCallingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); ActivityOptions.abort(options); return ActivityManager.START_PERMISSION_DENIED; } } IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, "android", appCallingUid, userId, null, null, 0, new Intent[] { intent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null); Intent newIntent = new Intent(); if (requestCode >= 0) { // Caller is requesting a result. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); } newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, new IntentSender(target)); if (heavy.activities.size() > 0) { ActivityRecord hist = heavy.activities.get(0); newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName); newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().taskId); } newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, aInfo.packageName); newIntent.setFlags(intent.getFlags()); newIntent.setClassName("android", HeavyWeightSwitcherActivity.class.getName()); intent = newIntent; resolvedType = null; caller = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); componentSpecified = true; rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId); aInfo = rInfo != null ? rInfo.activityInfo : null; if (aInfo != null) { aInfo = mService.getActivityInfoForUser(aInfo, userId); } } } } final ActivityRecord[] outRecord = new ActivityRecord[1]; int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason); Binder.restoreCallingIdentity(origId); if (stack.mConfigWillChange) { // If the caller also wants to switch to a new configuration, // do so now. This allows a clean switch, as we are waiting // for the current activity to pause (so we will not destroy // it), and have not yet started the next activity. mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); stack.mConfigWillChange = false; if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Updating to new configuration after starting activity."); mService.updateConfigurationLocked(globalConfig, null, false); } if (outResult != null) { outResult.result = res; if (res == ActivityManager.START_SUCCESS) { mSupervisor.mWaitingActivityLaunched.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (outResult.result != START_TASK_TO_FRONT && !outResult.timeout && outResult.who == null); if (outResult.result == START_TASK_TO_FRONT) { res = START_TASK_TO_FRONT; } } if (res == START_TASK_TO_FRONT) { final ActivityRecord r = outRecord[0]; // ActivityRecord may represent a different activity, but it should not be in // the resumed state. if (r.nowVisible && r.state == RESUMED) { outResult.timeout = false; outResult.who = r.realActivity; outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mSupervisor.waitActivityVisible(r.realActivity, outResult); // Note: the timeout variable is not currently not ever set. do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } } } mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]); return res; } } //--------------------------------继续查看------------------------------------------------------- int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) { 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, container, inTask); if (outActivity != null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } return mLastStartActivityResult; } //--------------------------------继续查看------------------------------------------------------- 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, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { 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 ? 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) { ActivityOptions.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 (!AppGlobals.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 (!AppGlobals.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); } ActivityOptions.abort(options); return err; } boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, resultRecord, resultStack, options); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); 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); mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid, options); intent = mInterceptor.mIntent; rInfo = mInterceptor.mRInfo; aInfo = mInterceptor.mAInfo; resolvedType = mInterceptor.mResolvedType; inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; callingUid = mInterceptor.mCallingUid; options = 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(options); return START_SUCCESS; } // 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); 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 " + (container == null ? (mSupervisor.mFocusedStack == null ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : (container.mActivityDisplay == null ? DEFAULT_DISPLAY : container.mActivityDisplay.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, container, options, 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 (voiceSession == null && (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp); mPendingActivityLaunches.add(pal); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; } } if (mService.mDidAppSwitch) { // This is the second allowed switch since we stopped switches, // so now just generally allow switches. Use case: user presses // home (switches disabled, switch to home, mDidAppSwitch now true); // user taps a home icon (coming from home so allowed, we hit here // and now allow anyone to switch again). mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity); } //--------------------------------继续查看------------------------------------------------------- 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. if (!ActivityManager.isStartResultSuccessful(result) && mStartActivity.getTask() != null) { mStartActivity.getTask().removeActivity(mStartActivity); } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord, mTargetStack); return result; } //--------------------------------继续查看------------------------------------------------------- // Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { //...code mSupervisor.resumeFocusedStackTopActivityLocked(); //...code }
变量mSupervisor是一个ActivityStackSupervisor对象。
查看ActivityStackSupervisor的resumeFocusedStackTopActivityLocked()方法源码如下:
boolean resumeFocusedStackTopActivityLocked() { return resumeFocusedStackTopActivityLocked(null, null, null); } boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || r.state != RESUMED) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.state == RESUMED) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; }
此时又调用了ActivityStack 的resumeTopActivityUncheckedLocked()方法,源码如下:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { //...code result = resumeTopActivityInnerLocked(prev, options); //...code } private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { //...code mStackSupervisor.startSpecificActivityLocked(next, true, true); //...code }
这里继续调用了 ActivityStackSupervisor 的startSpecificActivityLocked ()方法:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { //...code realStartActivityLocked(r, app, andResume, checkConfig); //...code } //-------------------------------------------继续查看--------------------------------------------------- final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { //...code app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, 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, !andResume, mService.isNextTransitionForward(), profilerInfo); //...code }
变量app是一个ProcessRecord对象,app.thread 类型为 IApplicationThread,它的最终实现者就是 ApplicationThread (是ActivityThread的内部类),ApplicationThread继承了IApplicationThread.Stub,并提出ApplicationThread重写接口IApplicationThread的抽象方法在哪里被调用。有意思的是,app.thread调用scheduleLaunchActivity方法,通过Binder机制,会使ApplicationThread$scheduleLaunchActivity方法被调用。
于是,基于Binder机制,实现了一次进程间的通信,将启动Activity的操作交给了ApplicationThread类。
@Override public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.referrer = referrer; r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profilerInfo = profilerInfo; r.overrideConfig = overrideConfig; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY, r); }
创建了一个ActivityClientRecord对象,用于封装启动Activity需要的一些参数值。调用ActivityThread的sendMessage方法, 就是发送了一个启动消息给 Handler ,这个 Handler 简称H(ActivityThread的内部类),实现如下:查看其源码如下:
private void sendMessage(int what, Object obj) { sendMessage(what, obj, 0, 0, false); } private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg);//mH是一个H对象,类H是ActivityThread的内部类,并继承了Handler private class H extends Handler { //...code public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; //...code }
最终处理者为 ActivityThread 的 handleLaunchActivity 方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { //... Activity a = performLaunchActivity(r, customIntent); //... if (a != null) { //... handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); //... } 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(); } } }
调用performLaunchActivity方法启动Activity;若a不为空,则调用handleResumeActivity方法,内部会调用Activity
o
n
R
e
s
u
m
e
方
法
。
具
体
的
代
码
流
程
还
是
比
较
好
跟
的
。
当
a
为
空
,
也
就
是
创
建
A
c
t
i
v
i
t
y
的
实
例
出
错
了
,
走
e
l
s
e
语
句
。
A
c
t
i
v
i
t
y
M
a
n
a
g
e
r
.
g
e
t
S
e
r
v
i
c
e
(
)
前
面
已
经
分
析
过
了
,
返
回
I
A
c
t
i
v
i
t
y
M
a
n
a
g
e
r
的
代
理
对
象
,
调
用
该
代
理
对
象
的
方
法
,
会
向
系
统
服
务
A
c
t
i
v
i
t
y
M
a
n
a
g
e
r
S
e
r
v
i
c
e
发
送
请
求
,
基
于
B
i
n
d
e
r
机
制
,
最
终
会
调
用
A
c
t
i
v
i
t
y
M
a
n
a
g
e
r
S
e
r
v
i
c
e
onResume方法。具体的代码流程还是比较好跟的。当a为空,也就是创建Activity的实例出错了,走else语句。ActivityManager.getService()前面已经分析过了,返回IActivityManager的代理对象,调用该代理对象的方法,会向系统服务ActivityManagerService发送请求,基于Binder机制,最终会调用ActivityManagerService
onResume方法。具体的代码流程还是比较好跟的。当a为空,也就是创建Activity的实例出错了,走else语句。ActivityManager.getService()前面已经分析过了,返回IActivityManager的代理对象,调用该代理对象的方法,会向系统服务ActivityManagerService发送请求,基于Binder机制,最终会调用ActivityManagerServicefinishActivity方法。 也就是说,当创建Activity实例出错后,停止启动Activity的具体操作交给ActivityManagerService来处理。
回到启动Activity的流程,查看ActivityThread的performLaunchActivity源码如下:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; //...code java.lang.ClassLoader cl = appContext.getClassLoader(); if (appContext.getApplicationContext() instanceof Application) { activity = ((Application) appContext.getApplicationContext()) .instantiateActivity(cl, component.getClassName(), r.intent); } if (activity == null) { activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); } //...code Application app = r.packageInfo.makeApplication(false, mInstrumentation); //...code if (activity != null) { //...code activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); //...code mInstrumentation.callActivityOnCreate(activity, r.state); //...code } return activity;、 }
ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); }
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
//...................................................
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
//...................................................
return appContext;
}
ContextImpl的createActivityContext()方法源码如下
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
//...省略代码
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
activityToken, null, 0, classLoader);
//...省略代码
}
Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } }
至于 Instrumentation 的 newActivity 就是通过类加载器来创建 Activity 对象:
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; //...省略代码块 app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); //...省略代码块 mApplication = app; instrumentation.callApplicationOnCreate(app); //...省略代码块 return app; }
可以看出,如果Application已经被创建郭,那么不会再重复创建了,一个应用只有一个Application,Application对象的创建也是通过Instrumentation来完成的,这个过程和Activity对象的创建一样,都是通过类加载器来完成的,Application创建后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate()方法:
public void callApplicationOnCreate(Application app) {
app.onCreate();
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window) { attachBaseContext(context); mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this, window); mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) { mWindow.setUiOptions(info.uiOptions); } mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; mToken = token; mIdent = ident; mApplication = application; mIntent = intent; mReferrer = referrer; mComponent = intent.getComponent(); mActivityInfo = info; mTitle = title; mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; if (voiceInteractor != null) { if (lastNonConfigurationInstances != null) { mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor; } else { mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this, Looper.myLooper()); } } mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; }
ContextImpl 是一个重要的数据结构,它是 Context 的具体实现, Context 中的大部分逻辑都是由 ContextImpl 来完成的,ContextImpl 是通过 Activity 的 attach 方法和 Activity 建立关联的,初次之外,在 attach 方法中,Activity 还会完成 Window 的创建并建立自己跟 Window 的关联,这样当 Window 接收到外部输入事件后就可以将事件传递给 Activity。
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
//Activity 的 onCreate 方法已经被调用
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
0k, Activity的启动流程就分析完毕啦!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。