Activity启动流程(一)

343 阅读24分钟

1. Activity应用层启动:

在应用层,通常我们使用startActivity(Intent intent)启动一个新的Activity。例如:

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

2. Activity在Framework层启动:

API版本:API 29

2.1 Activity.java

path:frameworks/base/core/java/android/app/Activity.java

2.1.1 startActivity()

 /**
 * Same as {  @link #startActivity(Intent, Bundle)} with no options
 * specified.
 *  @param intent The intent to start.
 *  @throws android.content.ActivityNotFoundException
 *  @see #startActivity(Intent, Bundle)
 *  @see #startActivityForResult
 */
@Override

public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

2.1.2 startActivity()

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

Opptions == null,走下面两个参数的startActivityForResult()

2.1.3 startActivityForResult()

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

哎嘿,实际上还是走三参的函数

2.1.4 startActivityForResult()

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        // 执行execStartActivity函数,详见2.2.1
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            // 返回启动结果  TODO 详见2.15.5
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        ......
        cancelInputsAndStartExitTransition(options);
    } 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);
        }
    }
}

2.1.5 attach()

@UnsupportedAppUsage
private Instrumentation mInstrumentation;
@UnsupportedAppUsage
/*package*/ ActivityThread mMainThread;
@UnsupportedAppUsage
private IBinder mToken;

@UnsupportedAppUsage
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, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
    attachBaseContext(context);
    mFragments.attachHost(null /*parent*/);
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    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;
    ......
    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;
    mWindow.setColorMode(info.colorMode);
    setAutofillOptions(application.getAutofillOptions()); setContentCaptureOptions(application.getContentCaptureOptions());
}

在Activity中最终执行execStartActivity()在mInstrumentation中实现,需要7个参数,其中:

  • mInstrumentation:Instrumentation对象,具体实现execStartActivity()方法,在attach()中初始化
  • mMainThread.getApplicationThread():ActivityThread对象,此处调用getApplicationThread()返回的是ApplicationThread类;mMainThread在attach()中初始化
  • mToken:IBinder对象,在attach()中初始化

2.1.6 performCreate()


final void performCreate(Bundle icicle) {
    performCreate(icicle, null);
}

调用performCreate,详见2.1.7

2.1.7 performCreate()



final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }

    writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
    mActivityTransitionState.readState(icicle);
    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
    com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}

启动Activity,执行Activity的onCreate()函数

2.2 Instrumentation.java

path:frameworks/base/core/java/android/app/Instrumentation.java

2.2.1 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) {
            // 同步锁校验
            ......
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        // AMS.startActivity(),详见2.3.1和2.5.1
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        // 2.2.2 检查activity是否启动成功    TODO        
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

实用ActivityManager.getService()获取ActivityManagerService对象,调用startActivity()开启activity。

2.2.2 checkStartActivityResult()

TODO 
/** @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);
    }
}

TODO:返回处理结果

2.2.3 callActivityOnCreate()

/**
 * Perform calling of an activity's {@link Activity#onCreate}
 * method.  The default implementation simply calls through to that method.
 *
 * @param activity The activity being created.
 * @param icicle The previously frozen state (or null) to pass through to onCreate().
 */
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    // 执行前预处理
    prePerformCreate(activity);
    // 执行activtity的onCreate()函数。详见2.1.6
    activity.performCreate(icicle);
    // 执行后处理
    postPerformCreate(activity);
}

2.2.4 prePerformCreate()

预处理

private void prePerformCreate(Activity activity) {
    if (mWaitingActivities != null) {
        synchronized (mSync) {
            final int N = mWaitingActivities.size();
            for (int i=0; i<N; i++) {
                final ActivityWaiter aw = mWaitingActivities.get(i);
                final Intent intent = aw.intent;
                if (intent.filterEquals(activity.getIntent())) {
                    aw.activity = activity;
                    mMessageQueue.addIdleHandler(new ActivityGoing(aw));
                }
            }
        }
    }
}

2.2.5 postPerformCreate()

后处理

private void postPerformCreate(Activity activity) {
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                am.match(activity, activity, activity.getIntent());
            }
        }
    }
}

2.3 ActivityManager.java

path:frameworks/base/core/java/android/app/ActivityManager.java

2.3.1 getService()

/**
 * @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);
                // client
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };
  • ActivityManager中获取Context.ACTIVITY_SERVICE对应的service,然后绑定客户端 IActivityManager (抽象类,实现是ActivityManager)。
  • 使用ServiceManager.getService(Context.ACTIVITY_SERVICE)获取public static final String ACTIVITY_SERVICE = "activity"暴露出的service。

2.4 SystemServiceRegistry.java

path:frameworks/base/core/java/android/app/SystemServiceRegistry.java

static {
    ......
// register activity_service
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
        new CachedServiceFetcher<ActivityManager>() {
    @Override
    public ActivityManager createService(ContextImpl ctx) {
        return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
    }});
    ......
}

ACTIVITY_SERVICE暴露的service在SystemServiceRegister.java中注册。

2.5 ActivityManagerService.java

path:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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

2.5.2 startActivityAsUser()

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

2.5.3 startActivityAsUser()

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

2.5.4 startActivityAsUser()

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) {
        // 判断此进程是不是被隔离的进程,隔离的就抛出异常停止;否则继续
        // 详见 2.5.5
    enforceNotIsolatedCaller("startActivity");
         // 交给ActivityStartController检查
         // 详见 2.7.1
    userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // 详见 2.9和2.10 使用ActivityStarter.execute()开启Activity 
    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();
}

startActivityAsUser()是AMS最终调用ActivityStarter.execute()函数的入口。在离startActivityAsUser()方法开启Activity之前,需要做一下两个检查:

  1. 需要先检查“startActivity”这个请求者是不是被隔离的用户ID,一般不是在沙箱使用id号范围内的,都不是被隔离的用户id。
  2. 检查目标用户,获取用户id:userId,将用户作为参数构建ActivityStarter。

2.5.5 enforceNotIsolatedCaller()

// 判断是否是被隔离的userid
void enforceNotIsolatedCaller(String caller) {
    //详见 2.6.1 
    if (UserHandle.isIsolated(Binder.getCallingUid())) {
        throw new SecurityException("Isolated process not allowed to call " + caller);
    }
}

2.5.6 startProcessLocked()

@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

2.5.7 startProcessLocked()

@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
        boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
        String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkTime(startTime, "startProcess: after getProcessRecord");

        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
            // If we are in the background, then check to see if this process
            // is bad.  If so, we will just silently fail.
            if (mAppErrors.isBadProcessLocked(info)) {
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                        + "/" + info.processName);
                return null;
            }
        } else {
            // When the user is explicitly starting a process, then clear its
            // crash count so that we won't make it bad until they see at
            // least one crash dialog again, and make the process good again
            // if it had been bad.
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                    + "/" + info.processName);
            mAppErrors.resetProcessCrashTimeLocked(info);
            if (mAppErrors.isBadProcessLocked(info)) {
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mAppErrors.clearBadProcessLocked(info);
                if (app != null) {
                    app.bad = false;
                }
            }
        }
    } else {
        // If this is an isolated process, it can't re-use an existing process.
        app = null;
    }

    // We don't have to do anything more if:
    // (1) There is an existing application record; and
    // (2) The caller doesn't think it is dead, OR there is no thread
    //     object attached to it so we know it couldn't have crashed; and
    // (3) There is a pid assigned to it, so it is either starting or
    //     already running.
    if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
            + " app=" + app + " knownToBeDead=" + knownToBeDead
            + " thread=" + (app != null ? app.thread : null)
            + " pid=" + (app != null ? app.pid : -1));
    if (app != null && app.pid > 0) {
        if ((!knownToBeDead && !app.killed) || app.thread == null) {
            // We already have the app running, or are waiting for it to
            // come up (we have a pid but not yet its thread), so keep it.
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: done, added package to proc");
            return app;
        }

        // An application record is attached to a previous process,
        // clean it up now.
        if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
        checkTime(startTime, "startProcess: bad proc running, killing");
        killProcessGroup(app.uid, app.pid);
        handleAppDiedLocked(app, true, true);
        checkTime(startTime, "startProcess: done killing old proc");
    }

    String hostingNameStr = hostingName != null
            ? hostingName.flattenToShortString() : null;

    if (app == null) {
        checkTime(startTime, "startProcess: creating new process record");
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) {
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        app.crashHandler = crashHandler;
        app.isolatedEntryPoint = entryPoint;
        app.isolatedEntryPointArgs = entryPointArgs;
        checkTime(startTime, "startProcess: done creating new process record");
    } else {
        // If this is a new package in the process, add the package to the list
        app.addPackage(info.packageName, info.versionCode, mProcessStats);
        checkTime(startTime, "startProcess: added package to existing proc");
    }

    // If the system is not ready yet, then hold off on starting this
    // process until it is.
    if (!mProcessesReady
            && !isAllowedWhileBooting(info)
            && !allowWhileBooting) {
        if (!mProcessesOnHold.contains(app)) {
            mProcessesOnHold.add(app);
        }
        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                "System not ready, putting on hold: " + app);
        checkTime(startTime, "startProcess: returning with proc on hold");
        return app;
    }

    checkTime(startTime, "startProcess: stepping in to startProcess");
    final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
    checkTime(startTime, "startProcess: done starting proc!");
    return success ? app : null;
}

2.5.8 startProcessLocked()

@GuardedBy("this")
private final boolean startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr, String abiOverride) {
    return startProcessLocked(app, hostingType, hostingNameStr,
            false /* disableHiddenApiChecks */, abiOverride);
}

2.5.9 startProcessLocked()

/**
 * @return {@code true} if process start is successful, false otherwise.
 */
@GuardedBy("this")
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
    if (app.pendingStart) {
        return true;
    }
    long startTime = SystemClock.elapsedRealtime();
    if (app.pid > 0 && app.pid != MY_PID) {
        checkTime(startTime, "startProcess: removing from pids map");
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        checkTime(startTime, "startProcess: done removing from pids map");
        app.setPid(0);
        app.startSeq = 0;
    }

    if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
            "startProcessLocked removing on hold: " + app);
    mProcessesOnHold.remove(app);

    checkTime(startTime, "startProcess: starting to update cpu stats");
    updateCpuStats();
    checkTime(startTime, "startProcess: done updating cpu stats");

    try {
        try {
            final int userId = UserHandle.getUserId(app.uid);
            AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }

        /// M: onStartProcess @{
        mAmsExt.onStartProcess(hostingType, app.info.packageName);
        /// M: onStartProcess @}

        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
        if (!app.isolated) {
            int[] permGids = null;
            try {
                checkTime(startTime, "startProcess: getting gids from package manager");
                final IPackageManager pm = AppGlobals.getPackageManager();
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DEBUG_TRIAGED_MISSING, app.userId);
                StorageManagerInternal storageManagerInternal = LocalServices.getService(
                        StorageManagerInternal.class);
                mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            /*
             * Add shared application and profile GIDs so applications can share some
             * resources like shared libraries and access user-wide resources
             */
            if (ArrayUtils.isEmpty(permGids)) {
                gids = new int[3];
            } else {
                gids = new int[permGids.length + 3];
                System.arraycopy(permGids, 0, gids, 3, permGids.length);
            }
            gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
            gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
            gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));

            // Replace any invalid GIDs
            if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
            if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
        }
        checkTime(startTime, "startProcess: building args");
        if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                    && mTopComponent != null
                    && app.processName.equals(mTopComponent.getPackageName())) {
                uid = 0;
            }
            if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
                    && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
                uid = 0;
            }
        }
        int runtimeFlags = 0;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
            runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
            // Also turn on CheckJNI for debuggable apps. It's quite
            // awkward to turn on otherwise.
            runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        // Run the app in safe mode if its manifest requests so or the
        // system is booted in safe mode.
        if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
            mSafeMode == true) {
            runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
        }
        if ("1".equals(SystemProperties.get("debug.checkjni"))) {
            runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
        if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
            runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
        }
        String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
        if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
            runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
        }
        if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
            runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
        }
        if ("1".equals(SystemProperties.get("debug.assert"))) {
            runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;
        }
        if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {
            // Enable all debug flags required by the native debugger.
            runtimeFlags |= Zygote.DEBUG_ALWAYS_JIT;          // Don't interpret anything
            runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info
            runtimeFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE;   // Disbale optimizations
            mNativeDebuggingApp = null;
        }

        if (app.info.isPrivilegedApp() &&
                DexManager.isPackageSelectedToRunOob(app.pkgList.keySet())) {
            runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
        }

        if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
            app.info.maybeUpdateHiddenApiEnforcementPolicy(
                    mHiddenApiBlacklist.getPolicyForPrePApps(),
                    mHiddenApiBlacklist.getPolicyForPApps());
            @HiddenApiEnforcementPolicy int policy =
                    app.info.getHiddenApiEnforcementPolicy();
            int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
            if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
                throw new IllegalStateException("Invalid API policy: " + policy);
            }
            runtimeFlags |= policyBits;
        }

        String invokeWith = null;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            // Debuggable apps may include a wrapper script with their library directory.
            String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                if (new File(wrapperFileName).exists()) {
                    invokeWith = "/system/bin/logwrapper " + wrapperFileName;
                }
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) {
            requiredAbi = Build.SUPPORTED_ABIS[0];
        }

        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) {
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }

        app.gids = gids;
        app.requiredAbi = requiredAbi;
        app.instructionSet = instructionSet;

        // the per-user SELinux context must be set
        if (TextUtils.isEmpty(app.info.seInfoUser)) {
            Slog.wtf(TAG, "SELinux tag not defined",
                    new IllegalStateException("SELinux tag not defined for "
                    + app.info.packageName + " (uid " + app.uid + ")"));
        }
        final String seInfo = app.info.seInfo
                + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
        // Start the process.  It will either succeed and return a result containing
        // the PID of the new process, or else throw a RuntimeException.
        final String entryPoint = "android.app.ActivityThread";

        return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                startTime);
    } catch (RuntimeException e) {
        Slog.e(TAG, "Failure starting process " + app.processName, e);

        // Something went very wrong while trying to start this process; one
        // common case is when the package is frozen due to an active
        // upgrade. To recover, clean up any active bookkeeping related to
        // starting this process. (We already invoked this method once when
        // the package was initially frozen through KILL_APPLICATION_MSG, so
        // it doesn't hurt to use it again.)
        forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
                false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
        return false;
    }
}

2.5.10 startProcessLocked()

@GuardedBy("this")
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
    app.pendingStart = true;
    app.killedByAm = false;
    app.removed = false;
    app.killed = false;
    if (app.startSeq != 0) {
        Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
                + " with non-zero startSeq:" + app.startSeq);
    }
    if (app.pid != 0) {
        Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
                + " with non-zero pid:" + app.pid);
    }
    final long startSeq = app.startSeq = ++mProcStartSeqCounter;
    app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
    if (mConstants.FLAG_PROCESS_START_ASYNC) {
        if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                "Posting procStart msg for " + app.toShortString());
        mProcStartHandler.post(() -> {
            try {
                synchronized (ActivityManagerService.this) {
                    final String reason = isProcStartValidLocked(app, startSeq);
                    if (reason != null) {
                        Slog.w(TAG_PROCESSES, app + " not valid anymore,"
                                + " don't start process, " + reason);
                        app.pendingStart = false;
                        return;
                    }
                    app.usingWrapper = invokeWith != null
                            || SystemProperties.get("wrap." + app.processName) != null;
                    mPendingStarts.put(startSeq, app);
                }
                final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                        app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                        requiredAbi, instructionSet, invokeWith, app.startTime);
                synchronized (ActivityManagerService.this) {
                    handleProcessStartedLocked(app, startResult, startSeq);
                }
            } catch (RuntimeException e) {
                synchronized (ActivityManagerService.this) {
                    Slog.e(TAG, "Failure starting process " + app.processName, e);
                    mPendingStarts.remove(startSeq);
                    app.pendingStart = false;
                    forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                            false, false, true, false, false,
                            UserHandle.getUserId(app.userId), "start failure");
                }
            }
        });
        return true;
    } else {
        try {
            final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
                    uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                    invokeWith, startTime);
            handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                    startSeq, false);
        } catch (RuntimeException e) {
            Slog.e(TAG, "Failure starting process " + app.processName, e);
            app.pendingStart = false;
            forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                    false, false, true, false, false,
                    UserHandle.getUserId(app.userId), "start failure");
        }
        return app.pid > 0;
    }
}

2.5.11 startProcess()

private ProcessStartResult startProcess(String hostingType, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkTime(startTime, "startProcess: asking zygote to start proc");
        final ProcessStartResult startResult;
        if (hostingType.equals("webview_service")) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        } else {
            // 详见2.19.1
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        }
        checkTime(startTime, "startProcess: returned from zygote!");
        return startResult;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

2.6 UserHandle.java

path:frameworks/base/core/java/android/os/UserHandle.java

2.6.1 isIsolated()

UserHandle.java

/**
 * 如果用户id孤立的,就抛出异常;当用户id>=99000(沙箱进程第一个id)
 * 并且<=99999(沙箱进程最后一个id),说明是被隔离的,
 * 否则不是被隔离的,均返回false
 */
public static boolean isIsolated(int uid) {
    if (uid > 0) {
        final int appId = getAppId(uid);
        return appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID;
    } else {
        return false;
    }
}

2.7 ActivityStartController.java

path:frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java

2.7.1 checkTargetUser()

/**
 * If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling
 * user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into
 * account "current user", etc.
 *
 * If {@code validateIncomingUser} is false, it skips the above check, but instead
 * ensures {@code targetUserId} is a real user ID and not a special user ID such as
 * {@link android.os.UserHandle#USER_ALL}, etc.
 *
 
int checkTargetUser(int targetUserId, boolean validateIncomingUser,
        int realCallingPid, int realCallingUid, String reason) {
    if (validateIncomingUser) {
        // 详见 2.8.1
        return mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid,
                targetUserId, false, ALLOW_FULL_ONLY, reason, null);
    } else {
        // 详见 2.8.3
        mService.mUserController.ensureNotSpecialUser(targetUserId);
        return targetUserId;
    }
}
 

如果此时validateIncomingUser==true,则需要对比targetUserId和realCallingUid, 然后返回实际的用户id

如果此时validateIncomingUser==false,跳过检查,只需要保证userid不是一种特殊的userid

2.8 UserController.java

path:frameworks/base/services/core/java/com/android/server/am/UserController.java

2.8.1 handleIncomingUser()

int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
        int allowMode, String name, String callerPackage) {
    // 获取请求callingUserId
    final int callingUserId = UserHandle.getUserId(callingUid);
    // 如果callingUserId==userid,直接返回
    if (callingUserId == userId) {
        return userId;
    }

    // Note that we may be accessing mCurrentUserId outside of a lock...
    // shouldn't be a big deal, if this is being called outside
    // of a locked context there is intrinsically a race with
    // the value the caller will receive and someone else changing it.
    // We assume that USER_CURRENT_OR_SELF will use the current user; later
    // we will switch to the calling user if access to the current user fails.
    int targetUserId = unsafeConvertIncomingUser(userId);

    if (callingUid != 0 && callingUid != SYSTEM_UID) {
        final boolean allow;
        if (mInjector.isCallerRecents(callingUid)
                && callingUserId == getCurrentUserId()
                && isSameProfileGroup(callingUserId, targetUserId)) {
            // If the caller is Recents and it is running in the current user, we then allow it
            // to access its profiles.
            allow = true;
        } else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
                callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
            // If the caller has this permission, they always pass go.  And collect $200.
            allow = true;
        } else if (allowMode == ALLOW_FULL_ONLY) {
            // We require full access, sucks to be you.
            allow = false;
        } else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
                callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
            // If the caller does not have either permission, they are always doomed.
            allow = false;
        } else if (allowMode == ALLOW_NON_FULL) {
            // We are blanket allowing non-full access, you lucky caller!
            allow = true;
        } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE) {
            // We may or may not allow this depending on whether the two users are
            // in the same profile.
            allow = isSameProfileGroup(callingUserId, targetUserId);
        } else {
            throw new IllegalArgumentException("Unknown mode: " + allowMode);
        }
        if (!allow) {
            if (userId == UserHandle.USER_CURRENT_OR_SELF) {
                // In this case, they would like to just execute as their
                // owner user instead of failing.
                targetUserId = callingUserId;
            } else {
                StringBuilder builder = new StringBuilder(128);
                builder.append("Permission Denial: ");
                builder.append(name);
                if (callerPackage != null) {
                    builder.append(" from ");
                    builder.append(callerPackage);
                }
                builder.append(" asks to run as user ");
                builder.append(userId);
                builder.append(" but is calling from user ");
                builder.append(UserHandle.getUserId(callingUid));
                builder.append("; this requires ");
                builder.append(INTERACT_ACROSS_USERS_FULL);
                if (allowMode != ALLOW_FULL_ONLY) {
                    builder.append(" or ");
                    builder.append(INTERACT_ACROSS_USERS);
                }
                String msg = builder.toString();
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
        }
    }
    if (!allowAll) {
        // 确保不是特别用户
        ensureNotSpecialUser(targetUserId);
    }
    // 检查shell权限
    if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
        if (hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId)) {
            throw new SecurityException("Shell does not have permission to access user "
                    + targetUserId + "\n " + Debug.getCallers(3));
        }
    }
    return targetUserId;
}

2.8.2 unsafeConvertIncomingUser()

/**

*/
int unsafeConvertIncomingUser(int userId) {
    return (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF)
            ? getCurrentUserId(): userId;
}

如果用户id是UserHandle.USER_CURRENT(-2)或者UserHandle.USER_CURRENT_OR_SELF(-3)返回前台用户id:mCurrentUserId,否则返回userId

2.8.3 ensureNotSpecialUser()

/**
* 确保不是特定的用户
*/
void ensureNotSpecialUser(int userId) {
    if (userId >= 0) {
        return;
    }
    throw new IllegalArgumentException("Call does not support special user #" + userId);
}

2.9 ActivityStartController

path:frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java

2.9.1 obtainStarter()

/**
 * @return A starter to configure and execute starting an activity. It is valid until after
 *         {@link ActivityStarter#execute} is invoked. At that point, the starter should be
 *         considered invalid and no longer modified or used.
 */
 // 详细实现见2.10
ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

使用工厂模式创建一个ActivityStarter对象,然后在这个对象中设置intent和reason。

2.10 ActivityStarter.java

path:frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

2.10.1 factory.obtain()


/**
 * An interface that to provide {@link ActivityStarter} instances to the controller. This is
 * used by tests to inject their own starter implementations for verification purposes.
 */
@VisibleForTesting
interface Factory {
    /**
     * Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
     */
    void setController(ActivityStartController controller);

    /**
     * Generates an {@link ActivityStarter} that is ready to handle a new start request.
     * @param controller The {@link ActivityStartController} which the starter who will own
     *                   this instance.
     * @return an {@link ActivityStarter}
     */
    ActivityStarter obtain();

    /**
     * Recycles a starter for reuse.
     */
    void recycle(ActivityStarter starter);
}

2.10.2 factory.obtain()

    ......
    // 一次最多能起三个starter
    private final int MAX_STARTER_COUNT = 3;
    // 同步线程池
    private SynchronizedPool<ActivityStarter> mStarterPool =
        new SynchronizedPool<>(MAX_STARTER_COUNT);
        
    @Override
    public ActivityStarter obtain() {
        ActivityStarter starter = mStarterPool.acquire();
    
        if (starter == null) {
            starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
        }
    
        return starter;
    }
}

2.10.3 ActivityStarter()构造函数

private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
private final ActivityStartController mController;

ActivityStarter(ActivityStartController controller, ActivityManagerService service,
        ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
    mController = controller;
    mService = service;
    mSupervisor = supervisor;
    mInterceptor = interceptor;
    reset(true);
}

2.10.4 添加intent、reason等参数:

ActivityStarter setIntent(Intent intent) {
    mRequest.intent = intent;
    return this;
}

ActivityStarter setReason(String reason) {
    mRequest.reason = reason;
    return this;
}

ActivityStarter setCallingPackage(String callingPackage) {
    mRequest.callingPackage = callingPackage;
    return this;
}

ActivityStarter setResolvedType(String type) {
    mRequest.resolvedType = type;
    return this;
}

ActivityStarter setResultTo(IBinder resultTo) {
    mRequest.resultTo = resultTo;
    return this;
}

ActivityStarter setResultWho(String resultWho) {
    mRequest.resultWho = resultWho;
    return this;
}

ActivityStarter setRequestCode(int requestCode) {
    mRequest.requestCode = requestCode;
    return this;
}

ActivityStarter setStartFlags(int startFlags) {
    mRequest.startFlags = startFlags;
    return this;
}

ActivityStarter setProfilerInfo(ProfilerInfo info) {
    mRequest.profilerInfo = info;
    return this;
}

ActivityStarter setActivityOptions(Bundle bOptions) {
    return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
}


ActivityStarter setMayWait(int userId) {
    mRequest.mayWait = true;
    mRequest.userId = userId;

    return this;
}

从2.4 中的ActivityManagerService.java中的代码来看:

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

mActivityStartController.obtainStarter(intent, "startActivityAsUser")这里是通过ActivityController创建了一个ActivityStarter对象,然后通过setIntent和setReason设置这个activityStarter的intent为传来的intent,reason为"startActivityAsUser"。接下来设置这个starter的一堆相关属性,例如caller、callingPackage等参数,最后执行execute()函数。

在ActivityManagerService执行execute之前,设置属性包括:

  • Intent:从启动Activity时传来的参数
  • Reason:启动activity的reason,此处reason为 “startActivityAsUser
  • callingPackage: 调用者activity所在的包名。在Instrumentation启动Activity的时候通过who.getBasePackageName()获取的
  • resolvedType:在Instrumentation启动Activity的时候通过intent.resolveTypeIfNeeded(who.getContentResolver()
  • resultTo: Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息
  • resultWho:Activity.mEmbeddedID, 其中Activity是指调用者所在Activity
  • requestCode:请求码,当前为 -1
  • startFlags:开始标志,当前为 0
  • profilerInfo:null
  • activityOptions:null
  • mayWait:将userid传来,封装进mRequest中,并且将mayWait置为true

2.10.5 execute()

/**
 * Starts an activity based on the request parameters provided earlier.
 * @return The starter result.
 */
int execute() {
    try {
        // for transactional diffs and preprocessing.
        if (mRequest.mayWait) {
            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                    mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                    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();
    }
}

当设置userId的时候,默认设置mRequest.mayWait==true,因此执行startActivityMayWait()函数

在execute()函数中,当前传入的参数为:

  • mRequest.caller:调用者线程;mActivityStartController使用set方法设置的。
  • mRequest.callingUid:-1
  • mRequest.callingPackage:调用者包名。mActivityStartController使用set方法设置的
  • mRequest.realCallingPid:0
  • mRequest.realCallingUid:-10000
  • mRequest.intent:从启动Activity时传来的参数
  • mRequest.resolvedType:在Instrumentation启动Activity的时候通过intent.resolveTypeIfNeeded(who.getContentResolver())获得
  • mRequest.voiceSession:null
  • mRequest.voiceInteractor:null
  • mRequest.resultTo:Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息
  • mRequest.resultWho:Activity.mEmbeddedID, 其中Activity是指调用者所在Activity
  • mRequest.requestCode:开启新的Activity请求码,当前为 -1
  • mRequest.startFlags:请求新Activity开始标志,当前为 0
  • mRequest.profilerInfo:null
  • mRequest.waitResult:null
  • mRequest.globalConfig:null
  • mRequest.activityOptions:null
  • mRequest.ignoreTargetSecurity:false
  • mRequest.userId:用户id。
  • mRequest.inTask:null。mActivityStartController使用set方法设置的
  • mRequest.reason:reason。mActivityStartController使用set方法设置的
  • mRequest.allowPendingRemoteAnimationRegistryLookup:true

2.10.6 startActivityMayWait()

private int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
        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) {
    // 当intent!=null&&intent中有文件描述符的时候,抛出异常
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    // TODO 详见2.11.1
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
    // 判断组件是否为null
    boolean componentSpecified = intent.getComponent() != null;
    // 一下两种获取中,均以requestRealCallingPid为主
    // 获取realCallingPid
    final int realCallingPid = requestRealCallingPid != Request.DEFAULT_REAL_CALLING_PID
                               ? requestRealCallingPid
                               : Binder.getCallingPid();
    // 获取realCallingUid
    final int realCallingUid = requestRealCallingUid != Request.DEFAULT_REAL_CALLING_UID
                               ? requestRealCallingUid
                               : Binder.getCallingUid();
    // 定义局部变量callingPid
    int callingPid;
    if (callingUid >= 0) {
        callingPid = -1;
    } else if (caller == null) {
        callingPid = realCallingPid;
        callingUid = realCallingUid;
    } else {
        callingPid = callingUid = -1;
    }

    // 定义一个局部变量,存储传来的intent
    final Intent ephemeralIntent = new Intent(intent);
    // 新建一个intent对象,不修改传来的intent对象
    intent = new Intent(intent);
    // 如果满足以下条件:
    if (componentSpecified
            && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
            && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && mService.getPackageManagerInternalLocked()
                    .isInstantAppInstallerComponent(intent.getComponent())) {
        // 拦截直接针对临时安装程序的intent,临时安装程序的intent不能以原始intent启动。相反
        // 需要调整意图,使其看起来像“正常”应用程序的启动
        intent.setComponent(null /*component*/);
        componentSpecified = false;
    }
    // TODO 详见2.11.2
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, mRequest.filterCallingUid));
    if (rInfo == null) {
        // TODO 详见2.11.3 通过userId获取用户信息
        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,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, mRequest.filterCallingUid));
            }
        }
    }
    //  详见2.11.4 
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

    synchronized (mService) {
        final ActivityStack stack = mSupervisor.mFocusedStack;
        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 &&
                mService.mHasHeavyWeightFeature) {
            // heavy-wright进程:重量级进程,检查是否有另一个已经存在的重量级进程正在运行
            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());
                            SafeActivityOptions.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;
                    // 2.11.2 
                    rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
                            0 /* matchFlags */, computeResolveFilterUid(
                                    callingUid, realCallingUid, mRequest.filterCallingUid));
                    aInfo = rInfo != null ? rInfo.activityInfo : null;
                    if (aInfo != null) {
                        aInfo = mService.getActivityInfoForUser(aInfo, userId);
                    }
                }
            }
        }

        final ActivityRecord[] outRecord = new ActivityRecord[1];
        // 详见2.10.7 调用startActivity()开启新的Activity
        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);

        Binder.restoreCallingIdentity(origId);

        if (stack.mConfigWillChange) {
            // 如果调用者也想切换到新配置,请立即执行。这允许干净的切换,
            // 因为我们正在等待当前活动暂停(因此我们不会销毁它),并且尚未开始下一个活动。
            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;

            final ActivityRecord r = outRecord[0];
            
            // 判断开启结果,执行不同的逻辑操作
            switch(res) {
                // 开启成功
                case START_SUCCESS: {
                    // 详见 2.11.5
                    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;
                    }
                    break;
                }
                // 置顶
                case START_DELIVERED_TO_TOP: {
                    outResult.timeout = false;
                    outResult.who = r.realActivity;
                    outResult.totalTime = 0;
                    outResult.thisTime = 0;
                    break;
                }
                // TODO ?放到前台
                case START_TASK_TO_FRONT: {
                    // ActivityRecord may represent a different activity, but it should not be
                    // in the resumed state.
                    if (r.nowVisible && r.isState(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);
                    }
                    break;
                }
            }
        }

        mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
        return res;
    }
}

该函数主要做了以下功能:

  • 通过resolveIntent()获取ActivityInfo,做开启前处理
  • startActivity()启动新的Activity
  • 获取新的Activity启动结果,并做处理

2.10.7 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) {
    ......
    mLastStartReason = reason;
    mLastStartActivityTimeMs = System.currentTimeMillis();
    mLastStartActivityRecord[0] = null;
    // 详见2.10.8
    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);
    ......
    // 获取结果并返回
    return getExternalResult(mLastStartActivityResult);
}

2.10.8 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) {
    // 默认返回值为 ActivityManager.START_SUCCESS
    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) {
        // 获取调用者所在的Activity,详见2.11.6
        sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                "Will send result to " + resultTo + " " + sourceRecord);
        if (sourceRecord != null) {
            // 调用时Requestcode==-1,不会走if中判断
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }
    // 获取intent的flags
    final int launchFlags = intent.getFlags();

    // 转换activity的执行结果从源activity到即将启动的新activity,包括失败等
    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;
        }
    }
    // 从intent中无法找到对应的component,结束
    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;
    }
    // 从intent中无法找到对应的activityinfo,结束
    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;
    }
    // 确保voiveSession安全
    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;
            }
        }
    }
    // 确保目标允许使用这种途径开启一个新的voice session
    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;
        }
    }
    // resultStack == null
    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;
    }
    // 权限检查,详见2.11.7
    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);
    }
    
    // ActivityController不为空的情况
    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;
        }
    }

    // activity启动过程中被打断
    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
    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;
    }
    // 创建ActivityStack对象stack,并且将mSupervisor.mFocusedStack赋值给他
    final ActivityStack stack = mSupervisor.mFocusedStack;

    // 如果我们启动的activity与当前resumed的activity的uid不同,检查是否允许切换
    if (voiceSession == null && (stack.getResumedActivity() == null
            || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
            // 检查app是否允许切换
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
                // 不允许切换的时候,需要吧启动的activity添加到mPendingActivityLaunches,然后直接返回
            mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                    sourceRecord, startFlags, stack, callerApp));
            ActivityOptions.abort(checkedOptions);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }
     // 从上次禁止app切换依赖,这是第二次允许切换,因此允许切换时间设置为0,表示可以任意切换 
    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;
    }
    // 处理pending activity的启动
    mController.doPendingActivityLaunches(false);
    // 详见2.10.9
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity);
}

在这个函数中,主要实现以下功能:

  • 处理activity
  • 检查权限

2.10.9 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();
        // 详见2.10.10
        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();
    }
    // TODO 返回值
    postStartActivityProcessing(r, result, mTargetStack);
    // 返回值
    return result;
}

2.10.10 startActivityUnchecked()

// 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) {
    // 初始化状态
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);
    // 处理启动任务flags
    computeLaunchingTaskFlags();
    // 处理源栈信息
    computeSourceStack();
    // 设置flag
    mIntent.setFlags(mLaunchFlags);
    // 获取是否将新的activity插入到已存在的栈中
    ActivityRecord reusedActivity = getReusableIntentActivity();

    int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
    int preferredLaunchDisplayId = DEFAULT_DISPLAY;
    if (mOptions != null) {
        preferredWindowingMode = mOptions.getLaunchWindowingMode();
        preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
    }

    // windowing mode and preferred launch display values from {@link LaunchParams} take
    // priority over those specified in {@link ActivityOptions}.
    if (!mLaunchParams.isEmpty()) {
        if (mLaunchParams.hasPreferredDisplay()) {
            preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
        }

        if (mLaunchParams.hasWindowingMode()) {
            preferredWindowingMode = mLaunchParams.mWindowingMode;
        }
    }
    // 不为空表示需要加入
    if (reusedActivity != null) {
        // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
        // still needs to be a lock task mode violation since the task gets cleared out and
        // the device would otherwise leave the locked task.
        if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }
     ......
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        // 创建新的TackRecord
        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();
    }
    ......    
    // 根据activity的启动模式来判断是直接插入已存在的栈顶还是创建新的栈
    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");
            }
            // 详见2.11.8  
            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;
}

本方法主要做以下工作:

  • 处理Activity启动模式关键字与栈之间的关系,Android启动模式可以设置FLAG_ACTIVITY_NEW_TASK等关键字,设置FLAG_ACTIVITY_NEW_TASK的时候,会创建一个新的栈来描述Activity的任务栈。
  • 调用ActivityStackSupervisor. resumeFocusedStackTopActivityLocked()函数

2.11 ActivityStackSupervisor.java

path:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

2.11.1 getActivityMetricsLogger().notifyActivityLaunched

private ActivityMetricsLogger mActivityMetricsLogger;

public ActivityMetricsLogger getActivityMetricsLogger() {
    return mActivityMetricsLogger;
}

2.11.2 resolveIntent()

ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
        int filterCallingUid) {
    synchronized (mService) {
        try {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
            int modifiedFlags = flags
                    | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
            if (intent.isWebIntent()
                        || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
                modifiedFlags |= PackageManager.MATCH_INSTANT;
            }

            // In order to allow cross-profile lookup, we clear the calling identity here.
            // Note the binder identity won't affect the result, but filterCallingUid will.

            // Cross-user/profile call check are done at the entry points
            // (e.g. AMS.startActivityAsUser).
            final long token = Binder.clearCallingIdentity();
            try {
                return mService.getPackageManagerInternalLocked().resolveIntent(
                        intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }
}

2.11.3 getUserInfo()

UserInfo getUserInfo(int userId) {
    final long identity = Binder.clearCallingIdentity();
    try {
        return UserManager.get(mService.mContext).getUserInfo(userId);
    } finally {
        Binder.restoreCallingIdentity(identity);
    }
}

2.11.4 resolveActivity()

int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
        @Nullable TaskRecord task) {
    // Preference is given to the activity type for the activity then the task since the type
    // once set shouldn't change.
    int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
    if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
        activityType = task.getActivityType();
    }
    if (activityType != ACTIVITY_TYPE_UNDEFINED) {
        return activityType;
    }
    if (options != null) {
        activityType = options.getLaunchActivityType();
    }
    return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
}

2.11.5 waitActivityVisible()

void waitActivityVisible(ComponentName name, WaitResult result) {
    final WaitInfo waitInfo = new WaitInfo(name, result);
    mWaitingForActivityVisible.add(waitInfo);
}

2.11.6 isInAnyStackLocked()

ActivityRecord isInAnyStackLocked(IBinder token) {
    int numDisplays = mActivityDisplays.size();
    for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
        final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
        for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = display.getChildAt(stackNdx);
            final ActivityRecord r = stack.isInStackLocked(token);
            if (r != null) {
                return r;
            }
        }
    }
    return null;
}

2.11.7 checkStartAnyActivityPermission()

        String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, boolean ignoreTargetSecurity, boolean launchingInTask,
        ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) {
    final boolean isCallerRecents = mService.getRecentTasks() != null &&
            mService.getRecentTasks().isCallerRecents(callingUid);
    final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
            callingUid);
    if (startAnyPerm == PERMISSION_GRANTED || (isCallerRecents && launchingInTask)) {
        // If the caller has START_ANY_ACTIVITY, ignore all checks below. In addition, if the
        // caller is the recents component and we are specifically starting an activity in an
        // existing task, then also allow the activity to be fully relaunched.
        return true;
    }
    final int componentRestriction = getComponentRestrictionForCallingPackage(
            aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
    final int actionRestriction = getActionRestrictionForCallingPackage(
            intent.getAction(), callingPackage, callingPid, callingUid);
    if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
            || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1,
                    resultRecord, resultWho, requestCode,
                    Activity.RESULT_CANCELED, null);
        }
        final String msg;
        if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
            msg = "Permission Denial: starting " + intent.toString()
                    + " from " + callerApp + " (pid=" + callingPid
                    + ", uid=" + callingUid + ")" + " with revoked permission "
                    + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
        } else if (!aInfo.exported) {
            msg = "Permission Denial: starting " + intent.toString()
                    + " from " + callerApp + " (pid=" + callingPid
                    + ", uid=" + callingUid + ")"
                    + " not exported from uid " + aInfo.applicationInfo.uid;
        } else {
            msg = "Permission Denial: starting " + intent.toString()
                    + " from " + callerApp + " (pid=" + callingPid
                    + ", uid=" + callingUid + ")"
                    + " requires " + aInfo.permission;
        }
        Slog.w(TAG, msg);
        throw new SecurityException(msg);
    }

    if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
        final String message = "Appop Denial: starting " + intent.toString()
                + " from " + callerApp + " (pid=" + callingPid
                + ", uid=" + callingUid + ")"
                + " requires " + AppOpsManager.permissionToOp(
                        ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
        Slog.w(TAG, message);
        return false;
    } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
        final String message = "Appop Denial: starting " + intent.toString()
                + " from " + callerApp + " (pid=" + callingPid
                + ", uid=" + callingUid + ")"
                + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
        Slog.w(TAG, message);
        return false;
    }

    return true;
}

2.11.8 resumeFocusedStackTopActivityLocked()

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

    if (!readyToResume()) {
        return false;
    }

    if (targetStack != null && isFocusedStack(targetStack)) {
        // 详见2.12.1
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || !r.isState(RESUMED)) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } else if (r.isState(RESUMED)) {
        // Kick off any lingering app transitions form the MoveTaskToFront operation.
        mFocusedStack.executeAppTransition(targetOptions);
    }

    return false;
}

从ActivityStarter中传来的参数可知:

  • targetStack==true
  • sFocusedStack(targetStack) == true

因此代码执行targetStack.resumeTopActivityUncheckedLocked()

2.11.9 startSpecificActivityLocked()

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    // 获取即将要启动的Activity所在的进程
    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);
            }
            // 详见2.11.10
            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.
    }
    // 进程不存在就创建该进程。详见2.5.6
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

本次由于字数限制,暂时更新到这里,后续详见Activity启动流程(二)