文章标题

来源:互联网 发布:德国香肠 知乎 编辑:程序博客网 时间:2024/06/16 20:19

packages/AgoldApps/AguiLauncherTwoMenu/src/com/android/launcher3/Launcher.java

@Thunk void startAppShortcutOrInfoActivity(View v) {    Object tag = v.getTag();    final ShortcutInfo shortcut;    final Intent intent;    if (tag instanceof ShortcutInfo) {        shortcut = (ShortcutInfo) tag;        intent = shortcut.intent;        int[] pos = new int[2];        v.getLocationOnScreen(pos);        intent.setSourceBounds(new Rect(pos[0], pos[1],                pos[0] + v.getWidth(), pos[1] + v.getHeight()));    } else if (tag instanceof AppInfo) {        shortcut = null;        intent = ((AppInfo) tag).intent;    } else {        throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");    }    //这里调用startActivitySafely,intent中包含要启动的activity的信息。    boolean success = startActivitySafely(v, intent, tag);    mStats.recordLaunch(v, intent, shortcut);    if (success && v instanceof BubbleTextView) {        mWaitingForResume = (BubbleTextView) v;        mWaitingForResume.setStayPressed(true);    }}

packages/AgoldApps/AguiLauncherTwoMenu/src/com/android/launcher3/Launcher.java

public boolean startActivitySafely(View v, Intent intent, Object tag) {    boolean success = false;    //是安全模式 && 不是SystemApp    if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {        //Toast内容:Downloaded app disabled in Safe mode        Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();        return false;    }    try {        //调用startActivity        success = startActivity(v, intent, tag);    } catch (ActivityNotFoundException e) {        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();        Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);    }    return success;}

packages/AgoldApps/AguiLauncherTwoMenu/src/com/android/launcher3/Launcher.java

private boolean startActivity(View v, Intent intent, Object tag) {    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    try {        // Only launch using the new animation if the shortcut has not opted out (this is a        // private contract between launcher and may be ignored in the future).        boolean useLaunchAnimation = (v != null) &&                !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);        LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);        UserManagerCompat userManager = UserManagerCompat.getInstance(this);        UserHandleCompat user = null;        if (intent.hasExtra(AppInfo.EXTRA_PROFILE)) {            long serialNumber = intent.getLongExtra(AppInfo.EXTRA_PROFILE, -1);            user = userManager.getUserForSerialNumber(serialNumber);        }        Bundle optsBundle = null;        if (useLaunchAnimation) {            ActivityOptions opts = null;            if (Utilities.ATLEAST_MARSHMALLOW) {                int left = 0, top = 0;                int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();                if (v instanceof TextView) {                    // Launch from center of icon, not entire view                    Drawable icon = Workspace.getTextViewIcon((TextView) v);                    if (icon != null) {                        Rect bounds = icon.getBounds();                        left = (width - bounds.width()) / 2;                        top = v.getPaddingTop();                        width = bounds.width();                        height = bounds.height();                    }                }                opts = ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);            } else if (!Utilities.ATLEAST_LOLLIPOP) {                // Below L, we use a scale up animation                opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,                                v.getMeasuredWidth(), v.getMeasuredHeight());            } else if (Utilities.ATLEAST_LOLLIPOP_MR1) {                // On L devices, we use the device default slide-up transition.                // On L MR1 devices, we a custom version of the slide-up transition which                // doesn't have the delay present in the device default.                opts = ActivityOptions.makeCustomAnimation(this,                        R.anim.task_open_enter, R.anim.no_anim);            }            optsBundle = opts != null ? opts.toBundle() : null;        }        if (user == null || user.equals(UserHandleCompat.myUserHandle())) {            //primary user            StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();            try {                // Temporarily disable deathPenalty on all default checks. For eg, shortcuts                // containing file Uris would cause a crash as penaltyDeathOnFileUriExposure                // is enabled by default on NYC.                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()                        .penaltyLog().build());                // Could be launching some bookkeeping activity                //调用Activity的startActivity                startActivity(intent, optsBundle);            } finally {                StrictMode.setVmPolicy(oldPolicy);            }        } else {            //secondary user            // TODO Component can be null when shortcuts are supported for secondary user            launcherApps.startActivityForProfile(intent.getComponent(), user,                    intent.getSourceBounds(), optsBundle);        }        return true;    } catch (SecurityException e) {        if (Utilities.ATLEAST_MARSHMALLOW && tag instanceof ItemInfo) {            // Due to legacy reasons, direct call shortcuts require Launchers to have the            // corresponding permission. Show the appropriate permission prompt if that            // is the case.            if (intent.getComponent() == null                    && Intent.ACTION_CALL.equals(intent.getAction())                    && checkSelfPermission(Manifest.permission.CALL_PHONE) !=                        PackageManager.PERMISSION_GRANTED) {                // TODO: Rename sPendingAddItem to a generic name.                sPendingAddItem = preparePendingAddArgs(REQUEST_PERMISSION_CALL_PHONE, intent,                        0, (ItemInfo) tag);                requestPermissions(new String[]{Manifest.permission.CALL_PHONE},                        REQUEST_PERMISSION_CALL_PHONE);                return false;            }        }        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();        Log.e(TAG, "Launcher does not have the permission to launch " + intent +                ". Make sure to create a MAIN intent-filter for the corresponding activity " +                "or use the exported attribute for this activity. "                + "tag="+ tag + " intent=" + intent, e);    }    return false;}

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

public void startActivity(Intent intent, @Nullable Bundle options) {    if (options != null) {        //调用startActivityForResult        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);    }}

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

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,        @Nullable Bundle options) {    if (mParent == null) { //从桌面点击打开Activity        //调用Instrumentation的execStartActivity        Instrumentation.ActivityResult ar =            mInstrumentation.execStartActivity(                this, mMainThread.getApplicationThread(), mToken, this,                intent, requestCode, options);        if (ar != null) {            mMainThread.sendActivityResult(                mToken, mEmbeddedID, requestCode, ar.getResultCode(),                ar.getResultData());        }        if (requestCode >= 0) {            // If this start is requesting a result, we can avoid making            // the activity visible until the result is received.  Setting            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the            // activity hidden during this time, to avoid flickering.            // This can only be done when a result is requested because            // that guarantees we will get information back when the            // activity is finished, no matter what happens to it.            mStartedActivity = true;        }        cancelInputsAndStartExitTransition(options);        // TODO Consider clearing/flushing other event sources and events for child windows.    } else {        if (options != null) {            mParent.startActivityFromChild(this, intent, requestCode, options);        } else {            // Note we want to go through this method for compatibility with            // existing applications that may have overridden it.            mParent.startActivityFromChild(this, intent, requestCode);        }    }}

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

public ActivityResult execStartActivity(        Context who, IBinder contextThread, IBinder token, Activity target,        Intent intent, int requestCode, Bundle options) {    IApplicationThread whoThread = (IApplicationThread) contextThread;    Uri referrer = target != null ? target.onProvideReferrer() : null;    if (referrer != null) {        intent.putExtra(Intent.EXTRA_REFERRER, referrer);    }    if (mActivityMonitors != null) {        synchronized (mSync) {            final int N = mActivityMonitors.size();            for (int i=0; i<N; i++) {                final ActivityMonitor am = mActivityMonitors.get(i);                if (am.match(who, null, intent)) {                    am.mHits++;                    if (am.isBlocking()) {                        return requestCode >= 0 ? am.getResult() : null;                    }                    break;                }            }        }    }    try {        intent.migrateExtraStreamToClipData();        intent.prepareToLeaveProcess(who);        //调用ActivityManagerService的startActivity        int result = ActivityManagerNative.getDefault()            .startActivity(whoThread, who.getBasePackageName(), intent,                    intent.resolveTypeIfNeeded(who.getContentResolver()),                    token, target != null ? target.mEmbeddedID : null,                    requestCode, 0, null, options);        checkStartActivityResult(result, intent);    } catch (RemoteException e) {        throw new RuntimeException("Failure from system", e);    }    return null;}

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

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

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

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {    enforceNotIsolatedCaller("startActivity");    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),            userId, false, ALLOW_FULL_ONLY, "startActivity", null);    // TODO: Switch to user app stacks here.    //调用ActivityStarter的startActivityMayWait    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,            profilerInfo, null, null, bOptions, false, userId, null, null);}

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

final int startActivityMayWait(IApplicationThread caller, int callingUid,        String callingPackage, Intent intent, String resolvedType,        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,        IBinder resultTo, String resultWho, int requestCode, int startFlags,        ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,        Bundle bOptions, boolean ignoreTargetSecurity, int userId,        IActivityContainer iContainer, TaskRecord inTask) {    // Refuse possible leaked file descriptors    if (intent != null && intent.hasFileDescriptors()) {        throw new IllegalArgumentException("File descriptors passed in Intent");    }    mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();    boolean componentSpecified = intent.getComponent() != null;    // Save a copy in case ephemeral needs it    final Intent ephemeralIntent = new Intent(intent);    // Don't modify the client's object!    intent = new Intent(intent);    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);    if (rInfo == null) {        UserInfo userInfo = mSupervisor.getUserInfo(userId);        if (userInfo != null && userInfo.isManagedProfile()) {            // Special case for managed profiles, if attempting to launch non-cryto aware            // app in a locked managed profile from an unlocked parent allow it to resolve            // as user will be sent via confirm credentials to unlock the profile.            UserManager userManager = UserManager.get(mService.mContext);            boolean profileLockedAndParentUnlockingOrUnlocked = false;            long token = Binder.clearCallingIdentity();            try {                UserInfo parent = userManager.getProfileParent(userId);                profileLockedAndParentUnlockingOrUnlocked = (parent != null)                        && userManager.isUserUnlockingOrUnlocked(parent.id)                        && !userManager.isUserUnlockingOrUnlocked(userId);            } finally {                Binder.restoreCallingIdentity(token);            }            if (profileLockedAndParentUnlockingOrUnlocked) {                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,                        PackageManager.MATCH_DIRECT_BOOT_AWARE                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);            }        }    }    // Collect information about the target of the Intent.    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);    ActivityOptions options = ActivityOptions.fromBundle(bOptions);    ActivityStackSupervisor.ActivityContainer container =            (ActivityStackSupervisor.ActivityContainer)iContainer;    synchronized (mService) {        if (container != null && container.mParentActivity != null &&                container.mParentActivity.state != RESUMED) {            // Cannot start a child activity if the parent is not resumed.            return ActivityManager.START_CANCELED;        }        final int realCallingPid = Binder.getCallingPid();        final int realCallingUid = Binder.getCallingUid();        int callingPid;        if (callingUid >= 0) {            callingPid = -1;        } else if (caller == null) {            callingPid = realCallingPid;            callingUid = realCallingUid;        } else {            callingPid = callingUid = -1;        }        final ActivityStack stack;        if (container == null || container.mStack.isOnHomeDisplay()) {            stack = mSupervisor.mFocusedStack;        } else {            stack = container.mStack;        }        stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;        if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,                "Starting activity when config will change = " + stack.mConfigWillChange);        final long origId = Binder.clearCallingIdentity();        if (aInfo != null &&                (aInfo.applicationInfo.privateFlags                        & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {            // This may be a heavy-weight process!  Check to see if we already            // have another, different heavy-weight process running.            if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {                final ProcessRecord heavy = mService.mHeavyWeightProcess;                if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid                        || !heavy.processName.equals(aInfo.processName))) {                    int appCallingUid = callingUid;                    if (caller != null) {                        ProcessRecord callerApp = mService.getRecordForAppLocked(caller);                        if (callerApp != null) {                            appCallingUid = callerApp.info.uid;                        } else {                            Slog.w(TAG, "Unable to find app for caller " + caller                                    + " (pid=" + callingPid + ") when starting: "                                    + intent.toString());                            ActivityOptions.abort(options);                            return ActivityManager.START_PERMISSION_DENIED;                        }                    }                    IIntentSender target = mService.getIntentSenderLocked(                            ActivityManager.INTENT_SENDER_ACTIVITY, "android",                            appCallingUid, userId, null, null, 0, new Intent[] { intent },                            new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT                                    | PendingIntent.FLAG_ONE_SHOT, null);                    Intent newIntent = new Intent();                    if (requestCode >= 0) {                        // Caller is requesting a result.                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,                            new IntentSender(target));                    if (heavy.activities.size() > 0) {                        ActivityRecord hist = heavy.activities.get(0);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,                                hist.packageName);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,                                hist.task.taskId);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,                            aInfo.packageName);                    newIntent.setFlags(intent.getFlags());                    newIntent.setClassName("android",                            HeavyWeightSwitcherActivity.class.getName());                    intent = newIntent;                    resolvedType = null;                    caller = null;                    callingUid = Binder.getCallingUid();                    callingPid = Binder.getCallingPid();                    componentSpecified = true;                    rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);                    aInfo = rInfo != null ? rInfo.activityInfo : null;                    if (aInfo != null) {                        aInfo = mService.getActivityInfoForUser(aInfo, userId);                    }                }            }        }        final ActivityRecord[] outRecord = new ActivityRecord[1];        //调用startActivityLocked        int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,                aInfo, rInfo, voiceSession, voiceInteractor,                resultTo, resultWho, requestCode, callingPid,                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,                options, ignoreTargetSecurity, componentSpecified, outRecord, container,                inTask);        Binder.restoreCallingIdentity(origId);        if (stack.mConfigWillChange) {            // If the caller also wants to switch to a new configuration,            // do so now.  This allows a clean switch, as we are waiting            // for the current activity to pause (so we will not destroy            // it), and have not yet started the next activity.            mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,                    "updateConfiguration()");            stack.mConfigWillChange = false;            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,                    "Updating to new configuration after starting activity.");            mService.updateConfigurationLocked(config, null, false);        }        if (outResult != null) {            outResult.result = res;            if (res == ActivityManager.START_SUCCESS) {                mSupervisor.mWaitingActivityLaunched.add(outResult);                do {                    try {                        mService.wait();                    } catch (InterruptedException e) {                    }                } while (outResult.result != START_TASK_TO_FRONT                        && !outResult.timeout && outResult.who == null);                if (outResult.result == START_TASK_TO_FRONT) {                    res = START_TASK_TO_FRONT;                }            }            if (res == START_TASK_TO_FRONT) {                ActivityRecord r = stack.topRunningActivityLocked();                if (r.nowVisible && r.state == RESUMED) {                    outResult.timeout = false;                    outResult.who = new ComponentName(r.info.packageName, r.info.name);                    outResult.totalTime = 0;                    outResult.thisTime = 0;                } else {                    outResult.thisTime = SystemClock.uptimeMillis();                    mSupervisor.mWaitingActivityVisible.add(outResult);                    do {                        try {                            mService.wait();                        } catch (InterruptedException e) {                        }                    } while (!outResult.timeout && outResult.who == null);                }            }        }        final ActivityRecord launchedActivity = mReusedActivity != null                ? mReusedActivity : outRecord[0];        mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);        return res;    }}

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

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,        ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,        TaskRecord inTask) {    int err = ActivityManager.START_SUCCESS;    // [AGOLD][xuelb add][sunjin merged][20161018] START  bg task clear    Slog.i(TAG, "startActivityLocked intent:" + intent);    if (LimitThirdApp.isIntentIntercept(mService.mContext, intent)) {        return -1;    }    // [AGOLD] END    ProcessRecord callerApp = null;    if (caller != null) {        callerApp = mService.getRecordForAppLocked(caller);        if (callerApp != null) {            callingPid = callerApp.pid;            callingUid = callerApp.info.uid;        } else {            Slog.w(TAG, "Unable to find app for caller " + caller                    + " (pid=" + callingPid + ") when starting: "                    + intent.toString());            err = ActivityManager.START_PERMISSION_DENIED;        }    }    final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;    if (err == ActivityManager.START_SUCCESS) {        Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)                + "} from uid " + callingUid                + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?                Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :                (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :                        container.mActivityDisplay.mDisplayId)));    }    ActivityRecord sourceRecord = null;    ActivityRecord resultRecord = null;    if (resultTo != null) {        sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,                "Will send result to " + resultTo + " " + sourceRecord);        if (sourceRecord != null) {            if (requestCode >= 0 && !sourceRecord.finishing) {                resultRecord = sourceRecord;            }        }    }    final int launchFlags = intent.getFlags();    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {        // Transfer the result target from the source activity to the new        // one being started, including any failures.        if (requestCode >= 0) {            ActivityOptions.abort(options);            return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;        }        resultRecord = sourceRecord.resultTo;        if (resultRecord != null && !resultRecord.isInStackLocked()) {            resultRecord = null;        }        resultWho = sourceRecord.resultWho;        requestCode = sourceRecord.requestCode;        sourceRecord.resultTo = null;        if (resultRecord != null) {            resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);        }        if (sourceRecord.launchedFromUid == callingUid) {            // The new activity is being launched from the same uid as the previous            // activity in the flow, and asking to forward its result back to the            // previous.  In this case the activity is serving as a trampoline between            // the two, so we also want to update its launchedFromPackage to be the            // same as the previous activity.  Note that this is safe, since we know            // these two packages come from the same uid; the caller could just as            // well have supplied that same package name itself.  This specifially            // deals with the case of an intent picker/chooser being launched in the app            // flow to redirect to an activity picked by the user, where we want the final            // activity to consider it to have been launched by the previous app activity.            callingPackage = sourceRecord.launchedFromPackage;        }    }    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {        // We couldn't find a class that can handle the given Intent.        // That's the end of that!        err = ActivityManager.START_INTENT_NOT_RESOLVED;    }    if (err == ActivityManager.START_SUCCESS && aInfo == null) {        // We couldn't find the specific class specified in the Intent.        // Also the end of the line.        err = ActivityManager.START_CLASS_NOT_FOUND;    }    if (err == ActivityManager.START_SUCCESS && sourceRecord != null            && sourceRecord.task.voiceSession != null) {        // If this activity is being launched as part of a voice session, we need        // to ensure that it is safe to do so.  If the upcoming activity will also        // be part of the voice session, we can only launch it if it has explicitly        // said it supports the VOICE category, or it is a part of the calling app.        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0                && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {            try {                intent.addCategory(Intent.CATEGORY_VOICE);                if (!AppGlobals.getPackageManager().activitySupportsIntent(                        intent.getComponent(), intent, resolvedType)) {                    Slog.w(TAG,                            "Activity being started in current voice task does not support voice: "                                    + intent);                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;                }            } catch (RemoteException e) {                Slog.w(TAG, "Failure checking voice capabilities", e);                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;            }        }    }    if (err == ActivityManager.START_SUCCESS && voiceSession != null) {        // If the caller is starting a new voice session, just make sure the target        // is actually allowing it to run this way.        try {            if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),                    intent, resolvedType)) {                Slog.w(TAG,                        "Activity being started in new voice task does not support: "                                + intent);                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;            }        } catch (RemoteException e) {            Slog.w(TAG, "Failure checking voice capabilities", e);            err = ActivityManager.START_NOT_VOICE_COMPATIBLE;        }    }    final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;    if (err != START_SUCCESS) {        if (resultRecord != null) {            resultStack.sendActivityResultLocked(                    -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);        }        ActivityOptions.abort(options);        return err;    }    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,            requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,            resultRecord, resultStack, options);    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,            callingPid, resolvedType, aInfo.applicationInfo);    if (mService.mController != null) {        try {            // The Intent we give to the watcher has the extra data            // stripped off, since it can contain private information.            Intent watchIntent = intent.cloneFilter();            abort |= !mService.mController.activityStarting(watchIntent,                    aInfo.applicationInfo.packageName);        } catch (RemoteException e) {            mService.mController = null;        }    }    mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);    mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,            options);    intent = mInterceptor.mIntent;    rInfo = mInterceptor.mRInfo;    aInfo = mInterceptor.mAInfo;    resolvedType = mInterceptor.mResolvedType;    inTask = mInterceptor.mInTask;    callingPid = mInterceptor.mCallingPid;    callingUid = mInterceptor.mCallingUid;    options = mInterceptor.mActivityOptions;    if (abort) {        if (resultRecord != null) {            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,                    RESULT_CANCELED, null);        }        // We pretend to the caller that it was really started, but        // they will just get a cancel result.        ActivityOptions.abort(options);        return START_SUCCESS;    }    // If permissions need a review before any of the app components can run, we    // launch the review activity and pass a pending intent to start the activity    // we are to launching now after the review is completed.    /// M: CTA requirement - permission control    if (Build.isPermissionReviewRequired() && aInfo != null) {        if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(                aInfo.packageName, userId)) {            IIntentSender target = mService.getIntentSenderLocked(                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,                    callingUid, userId, null, null, 0, new Intent[]{intent},                    new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT                            | PendingIntent.FLAG_ONE_SHOT, null);            final int flags = intent.getFlags();            Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);            newIntent.setFlags(flags                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);            newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);            newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));            if (resultRecord != null) {                newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);            }            intent = newIntent;            resolvedType = null;            callingUid = realCallingUid;            callingPid = realCallingPid;            rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,                    null /*profilerInfo*/);            /// M: Permission review log enhancement @{            if (DEBUG_PERMISSIONS_REVIEW || !ActivityManagerService.IS_USER_BUILD) {                Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,                        true, false) + "} from uid " + callingUid + " on display "                        + (container == null ? (mSupervisor.mFocusedStack == null ?                        Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :                        (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :                                container.mActivityDisplay.mDisplayId)));            }            /// M: Permission review log enhancement @}        }    }    // 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.ephemeralResolveInfo != null) {        // Create a pending intent to start the intent resolved here.        final IIntentSender failureTarget = mService.getIntentSenderLocked(                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,                Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },                new String[]{ resolvedType },                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT                        | PendingIntent.FLAG_IMMUTABLE, null);        // Create a pending intent to start the ephemeral application; force it to be        // directed to the ephemeral package.        ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());        final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,                Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },                new String[]{ resolvedType },                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT                        | PendingIntent.FLAG_IMMUTABLE, null);        int flags = intent.getFlags();        intent = new Intent();        intent.setFlags(flags                | Intent.FLAG_ACTIVITY_NEW_TASK                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);        intent.putExtra(Intent.EXTRA_PACKAGE_NAME,                rInfo.ephemeralResolveInfo.getPackageName());        intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));        intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));        resolvedType = null;        callingUid = realCallingUid;        callingPid = realCallingPid;        rInfo = rInfo.ephemeralInstaller;        aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);    }    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,            requestCode, componentSpecified, voiceSession != null, mSupervisor, container,            options, sourceRecord);    if (outActivity != null) {        outActivity[0] = r;    }    if (r.appTimeTracker == null && sourceRecord != null) {        // If the caller didn't specify an explicit time tracker, we want to continue        // tracking under any it has.        r.appTimeTracker = sourceRecord.appTimeTracker;    }    final ActivityStack stack = mSupervisor.mFocusedStack;    if (voiceSession == null && (stack.mResumedActivity == null            || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,                realCallingPid, realCallingUid, "Activity start")) {            PendingActivityLaunch pal =  new PendingActivityLaunch(r,                    sourceRecord, startFlags, stack, callerApp);            mPendingActivityLaunches.add(pal);            ActivityOptions.abort(options);            return ActivityManager.START_SWITCHES_CANCELED;        }    }    if (mService.mDidAppSwitch) {        // This is the second allowed switch since we stopped switches,        // so now just generally allow switches.  Use case: user presses        // home (switches disabled, switch to home, mDidAppSwitch now true);        // user taps a home icon (coming from home so allowed, we hit here        // and now allow anyone to switch again).        mService.mAppSwitchesAllowedTime = 0;    } else {        mService.mDidAppSwitch = true;    }    doPendingActivityLaunchesLocked(false);    try {        mService.mWindowManager.deferSurfaceLayout();        //调用startActivityUnchecked        err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,                true, options, inTask);    } finally {        mService.mWindowManager.continueSurfaceLayout();    }    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);    return err;}

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

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,            voiceInteractor);    computeLaunchingTaskFlags();    computeSourceStack();    /// M: AMS log enhancement @{    if (!ActivityManagerService.IS_USER_BUILD || DEBUG_TASKS) {        Slog.d(TAG, "launchFlags(update): 0x" + Integer.toHexString(mLaunchFlags));    }    /// @}    mIntent.setFlags(mLaunchFlags);    mReusedActivity = getReusableIntentActivity();    final int preferredLaunchStackId =            (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;    if (mReusedActivity != 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 (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {            mSupervisor.showLockTaskToast();            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");            return START_RETURN_LOCK_TASK_MODE_VIOLATION;        }        if (mStartActivity.task == null) {            mStartActivity.task = mReusedActivity.task;        }        if (mReusedActivity.task.intent == null) {            // This task was started because of movement of the activity based on affinity...            // Now that we are actually launching it, we can assign the base intent.            mReusedActivity.task.setIntent(mStartActivity);        }        // This code path leads to delivering a new intent, we want to make sure we schedule it        // as the first operation, in case the activity will be resumed as a result of later        // operations.        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0                || mLaunchSingleInstance || mLaunchSingleTask) {            // In this situation we want to remove all activities from the task up to the one            // being started. In most cases this means we are resetting the task to its initial            // state.            final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(                    mStartActivity, mLaunchFlags);            if (top != null) {                if (top.frontOfTask) {                    // Activity aliases may mean we use different intents for the top activity,                    // so make sure the task now has the identity of the new intent.                    top.task.setIntent(mStartActivity);                }                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);                /// M: AMS log enhancement @{                if (DEBUG_TASKS) {                    Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);                }                /// @}                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,                        mStartActivity.launchedFromPackage);            }        }        mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {            // We don't need to start a new activity, and the client said not to do anything            // if that is the case, so this is it!  And for paranoia, make sure we have            // correctly resumed the top activity.            resumeTargetStackIfNeeded();            /// M: AMS log enhancement @{            if (DEBUG_TASKS) {                Slog.d(TAG, "START_RETURN_INTENT_TO_CALLER");            }            /// @}            return START_RETURN_INTENT_TO_CALLER;        }        setTaskFromIntentActivity(mReusedActivity);        if (!mAddingToTask && mReuseTask == null) {            // We didn't do anything...  but it was needed (a.k.a., client don't use that            // intent!)  And for paranoia, make sure we have correctly resumed the top activity.            resumeTargetStackIfNeeded();            /// M: AMS log enhancement @{            if (DEBUG_TASKS) {                Slog.d(TAG, "START_TASK_TO_FRONT");            }            /// @}            return START_TASK_TO_FRONT;        }    }    if (mStartActivity.packageName == null) {        if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {            mStartActivity.resultTo.task.stack.sendActivityResultLocked(                    -1, mStartActivity.resultTo, mStartActivity.resultWho,                    mStartActivity.requestCode, RESULT_CANCELED, null);        }        ActivityOptions.abort(mOptions);        /// M: AMS log enhancement @{        if (DEBUG_TASKS) {            Slog.d(TAG, "START_CLASS_NOT_FOUND");        }        /// @}        return START_CLASS_NOT_FOUND;    }    // If the activity being launched is the same as the one currently at the top, then    // we need to check if it should only be launched once.    final ActivityStack topStack = mSupervisor.mFocusedStack;    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);    final boolean dontStart = top != null && mStartActivity.resultTo == null            && top.realActivity.equals(mStartActivity.realActivity)            && top.userId == mStartActivity.userId            && top.app != null && top.app.thread != null            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0            || mLaunchSingleTop || mLaunchSingleTask);    if (dontStart) {        ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);        // For paranoia, make sure we have correctly resumed the top activity.        topStack.mLastPausedActivity = null;        if (mDoResume) {            mSupervisor.resumeFocusedStackTopActivityLocked();        }        ActivityOptions.abort(mOptions);        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {            // We don't need to start a new activity, and the client said not to do            // anything if that is the case, so this is it!            return START_RETURN_INTENT_TO_CALLER;        }        /// M: AMS log enhancement @{        if (DEBUG_TASKS) {            Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);        }        /// @}        top.deliverNewIntentLocked(                mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);        // Don't use mStartActivity.task to show the toast. We're not starting a new activity        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.        mSupervisor.handleNonResizableTaskIfNeeded(                top.task, preferredLaunchStackId, topStack.mStackId);        return START_DELIVERED_TO_TOP;    }    boolean newTask = false;    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)            ? mSourceRecord.task : null;    // Should this be considered a new task?    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {        newTask = true;        setTaskFromReuseOrCreateNewTask(taskToAffiliate);        if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {            /// M: ALPS02270164, Show lock task toast when in violation            mSupervisor.showLockTaskToast();            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);            return START_RETURN_LOCK_TASK_MODE_VIOLATION;        }        if (!mMovedOtherTask) {            updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);        }    } else if (mSourceRecord != null) {        if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {            /// M: ALPS02270164, Show lock task toast when in violation            mSupervisor.showLockTaskToast();            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);            return START_RETURN_LOCK_TASK_MODE_VIOLATION;        }        final int result = setTaskFromSourceRecord();        if (result != START_SUCCESS) {            return result;        }    } else if (mInTask != null) {        // The caller is asking that the new activity be started in an explicit        // task it has provided to us.        if (mSupervisor.isLockTaskModeViolation(mInTask)) {            /// M: ALPS02270164, Show lock task toast when in violation            mSupervisor.showLockTaskToast();            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);            return START_RETURN_LOCK_TASK_MODE_VIOLATION;        }        final int result = setTaskFromInTask();        if (result != START_SUCCESS) {            return result;        }    } 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();    }    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);    if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {        mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);    }    if (newTask) {        EventLog.writeEvent(                EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);        /// M: AMS log enhancement @{        if (DEBUG_TASKS) {            Slog.d(TAG, "ACT-AM_CREATE_TASK " + mStartActivity + " " + mStartActivity.task);        }        /// @}    }    ActivityStack.logStartActivity(            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);    /// M: AMS log enhancement @{    if (DEBUG_TASKS) {       Slog.d(TAG, "ACT-AM_CREATE_ACTIVITY " + mStartActivity + " " + mStartActivity.task);    }    /// @}    mTargetStack.mLastPausedActivity = null;    //调用ActivityStack的startActivityLocked    mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);    if (mDoResume) {        if (!mLaunchTaskBehind) {            // TODO(b/26381750): Remove this code after verification that all the decision            // points above moved targetStack to the front which will also set the focus            // activity.            //调用ActivityManagerService的setFocusedActivityLocked            mService.setFocusedActivityLocked(mStartActivity, "startedActivity");        }        final ActivityRecord topTaskActivity = mStartActivity.task.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.            mWindowManager.executeAppTransition();        } else {            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,                    mOptions);        }    } else {        mTargetStack.addRecentActivityLocked(mStartActivity);    }    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);    mSupervisor.handleNonResizableTaskIfNeeded(            mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);    return START_SUCCESS;}

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,        ActivityOptions options) {    TaskRecord rTask = r.task;    final int taskId = rTask.taskId;    // mLaunchTaskBehind tasks get placed at the back of the task stack.    if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {        // Last activity in task had been removed or ActivityManagerService is reusing task.        // Insert or replace.        // Might not even be in.        insertTaskAtTop(rTask, r);        mWindowManager.moveTaskToTop(taskId);    }    TaskRecord task = null;    if (!newTask) {        // If starting in an existing task, find where that is...        boolean startIt = true;        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {            task = mTaskHistory.get(taskNdx);            if (task.getTopActivity() == null) {                // All activities in task are finishing.                continue;            }            if (task == r.task) {                // Here it is!  Now, if this is not yet visible to the                // user, then just add it without starting; it will                // get started when the user navigates back to it.                if (!startIt) {                    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "                            + task, new RuntimeException("here").fillInStackTrace());                    task.addActivityToTop(r);                    r.putInHistory();                    addConfigOverride(r, task);                    if (VALIDATE_TOKENS) {                        validateAppTokensLocked();                    }                    ActivityOptions.abort(options);                    return;                }                break;            } else if (task.numFullscreen > 0) {                startIt = false;            }        }    }    // Place a new activity at top of stack, so it is next to interact    // with the user.    // If we are not placing the new activity frontmost, we do not want    // to deliver the onUserLeaving callback to the actual frontmost    // activity    if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {        mStackSupervisor.mUserLeaving = false;        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,                "startActivity() behind front, mUserLeaving=false");    }    task = r.task;    // Slot the activity into the history stack and proceed    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,            new RuntimeException("here").fillInStackTrace());    task.addActivityToTop(r);    task.setFrontOfTask();    r.putInHistory();    if (!isHomeStack() || numActivities() > 0) {        // We want to show the starting preview window if we are        // switching to a new task, or the next activity's process is        // not currently running.        boolean showStartingIcon = newTask;        ProcessRecord proc = r.app;        if (proc == null) {            proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);        }        if (proc == null || proc.thread == null) {            showStartingIcon = true;        }        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,                "Prepare open transition: starting " + r);        if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {            mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);            mNoAnimActivities.add(r);        } else {            mWindowManager.prepareAppTransition(newTask                    ? r.mLaunchTaskBehind                            ? TRANSIT_TASK_OPEN_BEHIND                            : TRANSIT_TASK_OPEN                    : TRANSIT_ACTIVITY_OPEN, keepCurTransition);            mNoAnimActivities.remove(r);        }        //调用addConfigOverride        addConfigOverride(r, task);        boolean doShow = true;        if (newTask) {            // Even though this activity is starting fresh, we still need            // to reset it to make sure we apply affinities to move any            // existing activities from other tasks in to it.            // If the caller has requested that the target task be            // reset, then do so.            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {                resetTaskIfNeededLocked(r, r);                doShow = topRunningNonDelayedActivityLocked(null) == r;            }        } else if (options != null && options.getAnimationType()                == ActivityOptions.ANIM_SCENE_TRANSITION) {            doShow = false;        }        if (r.mLaunchTaskBehind) {            // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we            // tell WindowManager that r is visible even though it is at the back of the stack.            mWindowManager.setAppVisibility(r.appToken, true);            ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);        } else if (SHOW_APP_STARTING_PREVIEW && doShow) {            // Figure out if we are transitioning from another activity that is            // "has the same starting icon" as the next one.  This allows the            // window manager to keep the previous window it had previously            // created, if it still had one.            ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();            if (prev != null) {                // We don't want to reuse the previous starting preview if:                // (1) The current activity is in a different task.                if (prev.task != r.task) {                    prev = null;                }                // (2) The current activity is already displayed.                else if (prev.nowVisible) {                    prev = null;                }            }            r.showStartingWindow(prev, showStartingIcon);        }    } else {        // If this is the first activity, don't do any fancy animations,        // because there is nothing for it to animate on top of.        addConfigOverride(r, task);        ActivityOptions.abort(options);        options = null;    }    if (VALIDATE_TOKENS) {        validateAppTokensLocked();    }}

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

void addConfigOverride(ActivityRecord r, TaskRecord task) {    final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();    // TODO: VI deal with activity    mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,            r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,            (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,            task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,            task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask(),            r.appInfo.targetSdkVersion);    r.taskConfigOverride = task.mOverrideConfig;}

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

boolean setFocusedActivityLocked(ActivityRecord r, String reason) {    /// M: BMW. Move freeform stack to top @{    if (MultiWindowManager.isSupported()) {        if (MultiWindowManager.DEBUG) {            Slog.v(TAG_FOCUS, "setFocusedActivityLocked: r =  "               + r + ", mFocusedActivity = " + mFocusedActivity);        }        if (r == null || (mFocusedActivity == r            && r.task.getLaunchStackId() != FREEFORM_WORKSPACE_STACK_ID)) {            return false;        }    } else if (r == null || mFocusedActivity == r) {        return false;    }    /// @}    if (!r.isFocusable()) {        if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: unfocusable r=" + r);        return false;    }    if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);    final boolean wasDoingSetFocusedActivity = mDoingSetFocusedActivity;    if (wasDoingSetFocusedActivity) Slog.w(TAG,            "setFocusedActivityLocked: called recursively, r=" + r + ", reason=" + reason);    mDoingSetFocusedActivity = true;    final ActivityRecord last = mFocusedActivity;    mFocusedActivity = r;    if (r.task.isApplicationTask()) {        if (mCurAppTimeTracker != r.appTimeTracker) {            // We are switching app tracking.  Complete the current one.            if (mCurAppTimeTracker != null) {                mCurAppTimeTracker.stop();                mHandler.obtainMessage(                        REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();                mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);                mCurAppTimeTracker = null;            }            if (r.appTimeTracker != null) {                mCurAppTimeTracker = r.appTimeTracker;                startTimeTrackingFocusedActivityLocked();            }        } else {            startTimeTrackingFocusedActivityLocked();        }    } else {        r.appTimeTracker = null;    }    // TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null    // TODO: Probably not, because we don't want to resume voice on switching    // back to this activity    if (r.task.voiceInteractor != null) {        startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);    } else {        finishRunningVoiceLocked();        IVoiceInteractionSession session;        if (last != null && ((session = last.task.voiceSession) != null                || (session = last.voiceSession) != null)) {            // We had been in a voice interaction session, but now focused has            // move to something different.  Just finish the session, we can't            // return to it and retain the proper state and synchronization with            // the voice interaction service.            finishVoiceTask(session);        }    }    if (mStackSupervisor.moveActivityStackToFront(r, reason + " setFocusedActivity")) {        mWindowManager.setFocusedApp(r.appToken, true);    }    applyUpdateLockStateLocked(r);    applyUpdateVrModeLocked(r);    if (mFocusedActivity.userId != mLastFocusedUserId) {        mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);        mHandler.obtainMessage(                FOREGROUND_PROFILE_CHANGED_MSG, mFocusedActivity.userId, 0).sendToTarget();        mLastFocusedUserId = mFocusedActivity.userId;    }    // Log a warning if the focused app is changed during the process. This could    // indicate a problem of the focus setting logic!    if (mFocusedActivity != r) Slog.w(TAG,            "setFocusedActivityLocked: r=" + r + " but focused to " + mFocusedActivity);    mDoingSetFocusedActivity = wasDoingSetFocusedActivity;    EventLogTags.writeAmFocusedActivity(            mFocusedActivity == null ? -1 : mFocusedActivity.userId,            mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName,            reason);    return true;}frameworks/base/services/core/java/com/android/server/am/ActivityStarter.javavoid postStartActivityUncheckedProcessing(        ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,        ActivityStack targetStack) {    if (result < START_SUCCESS) {        // If someone asked to have the keyguard dismissed on the next activity start,        // but we are not actually doing an activity switch...  just dismiss the keyguard now,        // because we probably want to see whatever is behind it.        mSupervisor.notifyActivityDrawnForKeyguard();        return;    }    // We're waiting for an activity launch to finish, but that activity simply    // brought another activity to front. Let startActivityMayWait() know about    // this, so it waits for the new activity to become visible instead.    if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {        mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);    }    int startedActivityStackId = INVALID_STACK_ID;    if (r.task != null && r.task.stack != null) {        startedActivityStackId = r.task.stack.mStackId;    } else if (mTargetStack != null) {        startedActivityStackId = targetStack.mStackId;    }    // If we launched the activity from a no display activity that was launched from the home    // screen, we also need to start recents to un-minimize the docked stack, since the    // noDisplay activity will be finished shortly after.    // TODO: We should prevent noDisplay activities from affecting task/stack ordering and    // visibility instead of using this flag.    final boolean noDisplayActivityOverHome = sourceRecord != null            && sourceRecord.noDisplay            && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;    if (startedActivityStackId == DOCKED_STACK_ID            && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {        final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);        final ActivityRecord topActivityHomeStack = homeStack != null                ? homeStack.topRunningActivityLocked() : null;        if (topActivityHomeStack == null                || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {            // We launch an activity while being in home stack, which means either launcher or            // recents into docked stack. We don't want the launched activity to be alone in a            // docked stack, so we want to immediately launch recents too.            if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");            mWindowManager.showRecentApps(true /* fromHome */);            return;        }    }    if (startedActivityStackId == PINNED_STACK_ID            && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {        // The activity was already running in the pinned stack so it wasn't started, but either        // brought to the front or the new intent was delivered to it since it was already in        // front. Notify anyone interested in this piece of information.        mService.notifyPinnedActivityRestartAttemptLocked();        return;    }}
原创粉丝点击