Android9.0源码学习 - Launcher Activi

作者: Dufre | 来源:发表于2018-12-23 18:31 被阅读13次

    由于篇幅限制,第二部分AMS->Activity在Android9.0源码学习 - Launcher Activity(二)

    其实9.0与8.0的ActivityManager差不多,但是看到网上的文章基本是分析了8.0之前的,导致我看这些博客再对照9.0的Code看的时候经常会卡壳,所以干脆自己写一篇好了,虽然会花费大量的时间,但是应该会有更深的理解了。

    Artical Architecture

    • Activity Base
    • Process

    那首先会写Activity基础的基本概念,不然是没法继续看code。

    Activity Base

    之前写过一篇Activity基本的知识,有兴趣请移步Android App components - Activities
    还有一些博客,关于Task&LauncherMode:
    基础总结篇之一:Activity生命周期
    基础总结篇之二:Activity的四种launchMode

    那就我看code的情况,需要知道的概念有:

    • Tasks&Back Stack
    • Lifecycle
    • LauncherMode(standard/singleTop/singleTask/singleInstance)

    File List&Class List

    File List

    packages/apps/Launcher2/src/com/android/launcher2/
    - Launcher.java
    
    frameworks/base/core/java/android/app/
    - Activity.java
    - Instrumentation.java
    - ActivityManager.java
    - IActivityManager.aidl
    - ActivityThread.java
        - ApplicationThread.java
        - H.java
    - IApplicationThread.aidl
    
    frameworks/base/services/core/java/com/android/server/am/
    - ActivityManagerService.java
    - ActivityStarter.java
    - ActivityStackSupervisor.java
    - ActivityStack.java
    - ActivityRecord.java
    - ProcessRecord.java
    

    Class List

    Class Function
    Launcher Default launcher application.
    Activity Interact with the user.
    Instrumentation Monitor all of the interaction the system has with the application.
    ActivityManager Gives information about, and interacts with, activities, services, and the containing process.
    ActivityThread ApplicationThread /H
    ActivityManagerService This is a System Service
    ActivityStarter Controller for interpreting how and then launching an activity. This class collects all the logic for determining how an intent and flags should be turned into an activity and associated task and stack.
    ActivityStackSupervisor Supervisor of ActivityStack
    ActivityStack State and management of a single stack of activities.
    ClientLifecycleManager Class that is able to combine multiple client lifecycle transition requests and/or callbacks, and execute them as a single transaction.
    ClientTransaction A container that holds a sequence of messages, which may be sent to a client.
    ClientTransactionHandler Defines operations that a {@link android.app.servertransaction.ClientTransaction} or its items can perform on client.
    TransactionExecutor Class that manages transaction execution in the correct order.

    Process Communication

    在看函数调用之前,需要先了解process之间的关系,那这里的Launcher,system_service,Zygote,在System启动的时候就启起来了。那Launcher中是有所有App的图标,当用户点击这个图标,Launcher会告诉AMS(ActivityManagerService,在system_server进程中),我要启动一个Activity(App中android.intent.category.LAUNCHER的Activity)。但此时App还没启起来,因此,AMS通过Socket告诉Zygote去启一个process,那Zygote会fork这个App Process,最后App Process告诉AMS,process已经启起来了。

    在这里插入图片描述

    下面这张图是在前人的基础上稍稍改了一些,这张图也没什么好解释的,简化的Activity启动过程。

    1. Launcher告诉ActivityManagerService,我要启动一个APP了
    2. ActivityManagerService告诉Zygote,请求fork一个进程
    3. fork新进程,也就是APP进程
    4. 告诉AMS,APP进程已经启动完成
    5. 告诉Binder对象去发送启动Activity的请求
    6. 向应用程序发送启动Activity的请求
    7. 向APP进程的主线程发送启动MainActivity组件的操作,LAUNCH_ACTIVITY
    8. handleLaunchActivity


      在这里插入图片描述

    Activity Start Flow

    那我们就照着Process中提到的顺序一步一步分析:

    • Launcher -> AMS
    • APP -> AMS
    • AMS -> APP

    与Zygote与Process有关的这里就不分析了。

    Step 1: Launcher -> AMS

    首先是Launcher告诉AMS我要启动一个Activity的Flow

    当用户点击App图标,会调用Launcher中startActivitySafely(),这个函数本身没做什么事情,只是接着调用 startActivity(),取得startActivity()的返回值,并做异常处理,真正的逻辑在startActivity()里。

    startActivity(),可以看到intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),这涉及到Activity的Task,每个Activity都有一个Task,那么启动App的时候,Activity在一个新的Task中创建。然后又调用了一个startActivity(),这里的startActivity()是Launcher父类,也就是Activity的startActivity()

    /packages/apps/Launcher2/src/com/android/launcher2/Launcher.java - startActivity()

    
        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);
                UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
                LauncherApps launcherApps = (LauncherApps)
                        this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
                if (useLaunchAnimation) {
                    ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                            v.getMeasuredWidth(), v.getMeasuredHeight());
                    if (user == null || user.equals(android.os.Process.myUserHandle())) {
                        // Could be launching some bookkeeping activity
                        startActivity(intent, opts.toBundle());
                    } else {
                        launcherApps.startMainActivity(intent.getComponent(), user,
                                intent.getSourceBounds(),
                                opts.toBundle());
                    }
                } else {
                    if (user == null || user.equals(android.os.Process.myUserHandle())) {
                        startActivity(intent);
                    } else {
                        launcherApps.startMainActivity(intent.getComponent(), user,
                                intent.getSourceBounds(), null);
                    }
                }
                return true;
            } catch (SecurityException e) {
                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
    startActivity()中它会,调用startActivityForResult()

    /frameworks/base/core/java/android/app/Activity.java - startActivityForResult()

        @Override
        public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    

    startActivityForResult()中,会调用InstrumentationexecStartActivity(),那Instrumentation这个类之前有介绍,是用来监控system与application之间的交互。

    /frameworks/base/core/java/android/app/Activity.java - startActivityForResult()

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

    execStartActivity()里,前面有一些ActivityMonitor相关的代码,然后ActivityManager.getService() .startActivity() ,看到ActivityManager.getService(),这里应该敏感的看出这是一个Binder对象(其实Android中很多这种IPC的套路,AccessibilityManager/LocationManager...)。你可以去看ActivityManager看到这个函数是获取了一个IActivityManager对象,那它其实就是AMS的Binder对象。也就是说这里其实是调用了AMS的startActivity()函数。

    /frameworks/base/core/java/android/app/Instrumentation.java - execStartActivity()

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

    到这里呢,AMS就知道要启动一个Activity了。
    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java - startActivity()

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

    下面简单总结了一下Launcher到AMS的过程


    在这里插入图片描述

    AMS -> Zygote

    刚才讲到,到了AMS的startActivity(),里面调用了startActivityAsUser()
    这里可以看到返回了一个,mActivityStartController.obtainStarter(),那其实返回了ActivityStarter类的startActivityMayWait()的结果。

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java - 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) {
            enforceNotIsolatedCaller("startActivity");
    
            userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                    Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    
            // TODO: Switch to user app stacks here.
            return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                    .setCaller(caller)
                    .setCallingPackage(callingPackage)
                    .setResolvedType(resolvedType)
                    .setResultTo(resultTo)
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setProfilerInfo(profilerInfo)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .execute();
    
        }
    

    startActivityMayWait()调用了startActivity()。这段代码很长,因此这里省略了一部分。

    /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - startActivityMayWait()

        private int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                ProfilerInfo profilerInfo, WaitResult outResult,
                Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
                int userId, TaskRecord inTask, String reason,
                boolean allowPendingRemoteAnimationRegistryLookup) {
            /*
            省略
            */
    
                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);
    
                return res;
            /*
            省略
            */
        }
    

    startActivity()调用了startActivityUnchecked()

    /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - startActivity()

        private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
            int result = START_CANCELED;
            try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, doResume, options, inTask, outActivity);
            } finally {
                // If we are not able to proceed, disassociate the activity from the task. Leaving an
                // activity in an incomplete state can lead to issues, such as performing operations
                // without a window container.
                if (!ActivityManager.isStartResultSuccessful(result)
                        && mStartActivity.getTask() != null) {
                    mStartActivity.getTask().removeActivity(mStartActivity);
                }
                mService.mWindowManager.continueSurfaceLayout();
            }
    
            postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                    mTargetStack);
    
            return result;
        }
    

    startActivityUnchecked()里面,做了一些check的工作,比如顶部的Activity是否一样,是否应该launch等等。最后调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked()

    /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - 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);
    
            computeLaunchingTaskFlags();
    
            computeSourceStack();
    
            mIntent.setFlags(mLaunchFlags);
    
            ActivityRecord reusedActivity = getReusableIntentActivity();
    
            final int preferredLaunchStackId =
                    (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
            final int preferredLaunchDisplayId =
                    (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
    
            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 (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
                        (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.getTask() == null) {
                    mStartActivity.setTask(reusedActivity.getTask());
                }
                if (reusedActivity.getTask().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.
                    reusedActivity.getTask().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
                        || isDocumentLaunchesIntoExisting(mLaunchFlags)
                        || mLaunchSingleInstance || mLaunchSingleTask) {
                    final TaskRecord task = reusedActivity.getTask();
    
                    // 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 = task.performClearTaskForReuseLocked(mStartActivity,
                            mLaunchFlags);
    
                    // The above code can remove {@code reusedActivity} from the task, leading to the
                    // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
                    // task reference is needed in the call below to
                    // {@link setTargetStackAndMoveToFrontIfNeeded}.
                    if (reusedActivity.getTask() == null) {
                        reusedActivity.setTask(task);
                    }
    
                    if (top != null) {
                        if (top.frontOfTask) {
                            // Activity aliases may mean we use different intents for the top activity,
                            // so make sure the task now has the identity of the new intent.
                            top.getTask().setIntent(mStartActivity);
                        }
                        deliverNewIntent(top);
                    }
                }
    
                sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
    
                reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
    
                final ActivityRecord outResult =
                        outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
    
                // When there is a reused activity and the current result is a trampoline activity,
                // set the reused activity as the result.
                if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
                    outActivity[0] = reusedActivity;
                }
    
                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();
                    return START_RETURN_INTENT_TO_CALLER;
                }
                setTaskFromIntentActivity(reusedActivity);
    
                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();
                    if (outActivity != null && outActivity.length > 0) {
                        outActivity[0] = reusedActivity;
                    }
    
                    return START_TASK_TO_FRONT;
                }
            }
    
            if (mStartActivity.packageName == null) {
                final ActivityStack sourceStack = mStartActivity.resultTo != null
                        ? mStartActivity.resultTo.getStack() : null;
                if (sourceStack != null) {
                    sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                            mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                            null /* data */);
                }
                ActivityOptions.abort(mOptions);
                return START_CLASS_NOT_FOUND;
            }
    
            // If the activity being launched is the same as the one currently at the top, then
            // we need to check if it should only be launched once.
            final ActivityStack topStack = mSupervisor.mFocusedStack;
            final ActivityRecord topFocused = topStack.topActivity();
            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) {
                // 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;
                }
    
                deliverNewIntent(top);
    
                // Don't use mStartActivity.task to show the toast. We're not starting a new activity
                // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
                mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
                        preferredLaunchDisplayId, topStack.mStackId);
    
                return START_DELIVERED_TO_TOP;
            }
    
            boolean newTask = false;
            final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null;
    
            // Should this be considered a new task?
            int result = START_SUCCESS;
            if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                    && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
                newTask = true;
                result = setTaskFromReuseOrCreateNewTask(
                        taskToAffiliate, preferredLaunchStackId, topStack);
            } else if (mSourceRecord != null) {
                result = setTaskFromSourceRecord();
            } else if (mInTask != null) {
                result = setTaskFromInTask();
            } else {
                // This not being started from an existing activity, and not part of a new task...
                // just put it in the top task, though these days this case should never happen.
                setTaskToCurrentTopOrCreateNewTask();
            }
            if (result != START_SUCCESS) {
                return result;
            }
    
            mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                    mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
            mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
                    mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
            if (mSourceRecord != null) {
                mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
            }
            if (newTask) {
                EventLog.writeEvent(
                        EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
                        mStartActivity.getTask().taskId);
            }
            ActivityStack.logStartActivity(
                    EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
            mTargetStack.mLastPausedActivity = null;
    
            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
    
            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.
                    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");
                    }
                    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                            mOptions);
                }
            } else {
                mTargetStack.addRecentActivityLocked(mStartActivity);
            }
            mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
    
            mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
                    preferredLaunchDisplayId, mTargetStack.mStackId);
    
            return START_SUCCESS;
        }
    

    这里调用了ActivityStack的resumeTopActivityUncheckedLocked()

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java - resumeFocusedStackTopActivityLocked()

    
        boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            ///M: Add debug trace tag
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "ASS.resumeFocusedStackTopActivityLocked");
    
            if (!readyToResume()) {
                ///M: Add debug trace tag
                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
                return false;
            }
    
            if (targetStack != null && isFocusedStack(targetStack)) {
                boolean ret = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
                ///M: Add debug trace tag
                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
                return ret;
            }
    
            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);
            }
    
            ///M: Add debug trace tag
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
            return false;
        }
    

    resumeTopActivityUncheckedLocked的作用Ensure that the top activity in the stack is resumed,注释中还提到了,It is not safe to call this method directly as it can cause an activity in a non-focused stack to be resumed.然后它调用了resumeTopActivityInnerLocked()

    /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java - resumeTopActivityUncheckedLocked()

        boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            if (mStackSupervisor.inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
    
            boolean result = false;
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                result = resumeTopActivityInnerLocked(prev, options);
    
                // When resuming the top activity, it may be necessary to pause the top activity (for
                // example, returning to the lock screen. We suppress the normal pause logic in
                // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
                // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
                // to ensure any necessary pause logic occurs. In the case where the Activity will be
                // shown regardless of the lock screen, the call to
                // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
                final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
                if (next == null || !next.canTurnScreenOn()) {
                    checkReadyForSleep();
                }
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
    
            return result;
        }
    

    这里又回到了ActivityStackSupervisor,去调用了startSpecificActivityLocked()

    /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java - resumeTopActivityInnerLocked()

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        //...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
        //...
    }
    

    startSpecificActivityLocked函数中,会做一个activity application是否在running。有两种情况:

    • app is running:realStartActivityLocked()
    • app is not running:mService.startProcessLocked()
      这里的mService就是AMS,

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java - startSpecificActivityLocked()

        void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
    
            getLaunchTimeTracker().setLaunchTime(r);
    
            if (app != null && app.thread != null) {
                try {
                    if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                            || !"android".equals(r.info.packageName)) {
                        // Don't add this if it is a platform component that is marked
                        // to run in multiple processes, because this is actually
                        // part of the framework so doesn't make sense to track as a
                        // separate apk in the process.
                        app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                                mService.mProcessStats);
                    }
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }
    
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
    
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    

    那在AMS的startProcessLocked()去调用了start(),接着去调用了Process的start(),然后终于去了ZygoteProcess的startViaZygote()。这一部分可能不准确,但差不多是这个flow了。

    这里总结了AMS到Zygote的过程。


    在这里插入图片描述

    由于篇幅限制,第二部分AMS->Activity在Android9.0源码学习 - Launcher Activity(二)

    相关文章

      网友评论

        本文标题:Android9.0源码学习 - Launcher Activi

        本文链接:https://www.haomeiwen.com/subject/xuwnkqtx.html