03 App启动流程(一)

作者: 凤邪摩羯 | 来源:发表于2020-12-01 09:07 被阅读0次

从桌面图标的点击 Luancher——AMS

Launcher简介

在系统启动的最后一步会启动一个应用程序来显示系统中已经安装的应用程序,这个应用程序就叫做Launcher。Launcher在启动的过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表在系统桌面上,这样用户点击这些快捷方式图标来启动应用程序。

简而言之:作为Android系统中应用程序或其他桌面组件的管理者,负责显示、管理以及程序启动入口

当我们点击桌面图标到app开始启动,这个过程是从Luancher类开始的,Luancher继承于activity,他也实现了onClick方法,我们很容易想到在这个onClick方法里就有桌面图标点击事件的监听,即启动的入口:

public void onClick(View v) {
    ...
    Object tag = v.getTag();
    if (tag instanceof ShortcutInfo) {
        // 从快捷方式图标启动
        onClickAppShortcut(v);
    } else if (tag instanceof FolderInfo) {
        // 文件夹
        if (v instanceof FolderIcon) {
           onClickFolderIcon(v);
        }
    } else if (v == mAllAppsButton) {
        // “所有应用”按钮
        onClickAllAppsButton(v);
    } else if (tag instanceof AppInfo) {
        // 从“所有应用”中启动的应用
        startAppShortcutOrInfoActivity(v);
    } else if (tag instanceof LauncherAppWidgetInfo) {
        // 组件
        if (v instanceof PendingAppWidgetHostView) {
            onClickPendingWidget((PendingAppWidgetHostView) v);
        }
    }
}

我们看从快捷方式启动的onClickAppShortcut方法的实现:

/**
     * Event handler for an app shortcut click.
     *
     * @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
     */
    protected void onClickAppShortcut(final View v) {
       
        Object tag = v.getTag();
        if (!(tag instanceof ShortcutInfo)) {
            throw new IllegalArgumentException("Input must be a Shortcut");
        }

        // Open shortcut
        final ShortcutInfo shortcut = (ShortcutInfo) tag;

        if (shortcut.isDisabled != 0) {
            if ((shortcut.isDisabled &
                    ~ShortcutInfo.FLAG_DISABLED_SUSPENDED &
                    ~ShortcutInfo.FLAG_DISABLED_QUIET_USER) == 0) {
                //如果应用程序仅因上述标志而被禁用,则无论如
                //何都会启动活动。框架将告诉用户应用程序暂停的原因。
               
            } else {
            ···
        // Check for abandoned promise
        if ((v instanceof BubbleTextView) && shortcut.isPromise()) {
            String packageName = shortcut.intent.getComponent() != null ?
                    shortcut.intent.getComponent().getPackageName() : shortcut.intent.getPackage();
            if (!TextUtils.isEmpty(packageName)) {
                onClickPendingAppItem(v, packageName,
                        shortcut.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE));
                return;
            }
        }
        // 启动Activity
        startAppShortcutOrInfoActivity(v);
    }

这里调用了startAppShortcutOrInfoActivity方法,之后的调用分别为startAppShortcutOrInfoActivity到startActivitySafely方法,在startActivitySafely方法里的实现如下:

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        ······
        //启动新的任务栈
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            ······
            if (user == null || user.equals(Process.myUserHandle())) {
                // 启动活动
                startActivity(intent, optsBundle);
            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
           ······
        }
        return false;
    }

Activity启动入口

Launcher继承于Activity类,而Activity类实现了startActivity函数,因此,这里就调用了Activity.startActivity函数,而这个startActivity方法又是我们开发中经常使用的方法,所以这里我将它做为了Activity的入口。看看startActivity干了什么:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......
 
    @Override
    public void startActivity(Intent intent) {
        startActivityForResult(intent, -1);
    }
    ......
    public void startActivityForResult(Intent intent, int requestCode) {
        //mParent是一个activity对象,此时条件成立
        if (mParent == null) {
        // 调用 Instrumentation 的 execStartActivity 方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode);
            if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        //此时requestCode =-1
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
         cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
    public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        ...
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        ...
    }
}

我们看到在startActivity方法里,直接调用了startActivityForResult方法,传入的-1表示不需要这个Actvity结束后的返回结果,再接着看startActivityForResult方法,这里有一个mParent字段,他其实是一个Activity对象。因为是第一次启动,也就是启动的应用程序的根Activity,所以这个mParent肯定为空,然后执行了Instrumentation.ActivityResult的execStartActivity方法,即使mParent不为空,调用的startActivityFromChild方法内也调用的是Instrumentation.ActivityResult的execStartActivity方法。ActivityResult是Instrumentation的内部类,代表着Activity的启动结果数据,而Instrumentation的作用则是监控整个APP运行流程、交互流程。这一点可以通过源码上的注释发现:

/**
 * Base class for implementing application instrumentation code.  When running
 * with instrumentation turned on, this class will be instantiated for you
 * before any of the application code, allowing you to monitor all of the
 * interaction the system has with the application.  An Instrumentation
 * implementation is described to the system through an AndroidManifest.xml's
 * <instrumentation> tag.
 */
public class Instrumentation  {

/**
 * Description of a Activity execution result to return to the original
 * activity.
 */
public static final class ActivityResult {

那么这个execStartActivity方法里又做了什么呢,再看:

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {

 
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...

    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++;
                    //当该monitor阻塞activity启动,则直接返回
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //检查activity是否启动成功
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

我们看第一句,contextThread是一个IBinder对象,实际上它也是IApplicationThread 的实现类,IApplicationThread 继承了IInterface,简单看看:

/**
 * System private API for communicating with the application.  This is given to
 * the activity manager by an application  when it starts up, for the activity
 * manager to tell the application about things it needs to do.
 *
 * {@hide}
 */
public interface IApplicationThread extends IInterface {
    void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges, boolean dontReport) throws RemoteException;
    void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) throws RemoteException;
    void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
    void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
    void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)
            throws RemoteException;
    void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
    void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException;
    void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
            List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
            Configuration config, Configuration overrideConfig) throws RemoteException;
    void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;
    void scheduleDestroyActivity(IBinder token, boolean finished,
            int configChanges) throws RemoteException;
    void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
            int resultCode, String data, Bundle extras, boolean sync,
            int sendingUser, int processState) throws RemoteException;
    // 省略多个方法
    void scheduleBindService(IBinder token,
            Intent intent, boolean rebind, int processState) throws RemoteException;
    void scheduleUnbindService(IBinder token,
            Intent intent) throws RemoteException;
    //省略多个方法
    void scheduleStopService(IBinder token) throws RemoteException;
    //省略多个方法
    void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
            ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,
            IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
            int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
            Bundle coreSettings) throws RemoteException;
    void scheduleExit() throws RemoteException;
    // 省略多行代码
    void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
            int resultCode, String data, Bundle extras, boolean ordered,
            boolean sticky, int sendingUser, int processState) throws RemoteException;
    void scheduleLowMemory() throws RemoteException;
    void scheduleActivityConfigurationChanged(IBinder token, Configuration overrideConfig)
            throws RemoteException;
  //省略多个方法
    void scheduleTrimMemory(int level) throws RemoteException;
  //省略多个方法
}

看到这些方法,例如schedulePauseActivity,scheduleResumeActivity等,我们不难发现这个IApplicationThread好像与Activity的生命周期相关,而scheduleBindService、scheduleUnbindService等方法由于service的绑定等操作相关,所以IApplicationThread的实现类ApplicationThread主要完成Activity、service的创建等相关操作的。

然后再看 ActivityManager.getService().startActivity这一块,首先看看ActivityManager.getService()方法:

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

@UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                 // 向 ServiceManager 查询一个 key 为 Context.ACTIVITY_SERVICE" 的引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
\android\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\core\java\android\app\IActivityManager.java

public static android.app.IActivityManager asInterface(android.os.IBinder obj) {
    if ((obj==null)) {
        return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof android.app.IActivityManager))) {
        return ((android.app.IActivityManager)iin);
    }
    return new android.app.IActivityManager.Stub.Proxy(obj);
}

通过源码我们看到返回的是一个IActivitryManager,首先需要从ServiceManager中通过Context.ACTIVITY_SERVICE的一个字符串作为Key去查询(在ServiceManager中注册过的service会通过一个Map保存),然后返回了一个IBinder,然后又通过AIDL的方式,调用了IActivityManager.Stub.asInterface(b)方法返回一个IActivitryManager。需要注意的是,这里返回的代理对象并不是原来版本的ActivityManagerProxy对象,因为在API26之后就不再有ActivityManagerProxy这个类了,并且ActivityManagerNative也将被废弃,现在的AMN已经没有多少代码了,这里返回的应该是IActivityManager.Stub的内部类对象IActivityManager.Stub.Proxy,通过AIDL的方式在编译时会产生IActivityManager.java文件。那么这里最终是由谁去执行startActivity方法的呢,显然他应该是IActivityManager的实现类,没错就是ActivityManagerService。这样,IActivityManager.Stub与相当于一个Binder的客户端而ActivityManagerService相当于Binder的服务端,这样当IActivityManager.Stub.Proxy调用接口方法的时候底层通过Binder driver就会将请求数据与请求传递给server端,并在server端执行具体的接口逻辑。

在看AMS的startActivity之前,我们还要看看这个checkStartActivityResult方法:

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

顾名思义这个方法就是用来检查启动Activity的,代码中也可以很清晰的发现,这里会抛出各种比如异常,比如我们没有在AndroidManifest中声明activity就会抛出这个ActivityNotFoundException,提示have you declared this activity in your AndroidManifest.xml。

小结

所谓一图胜千言,我们看看第一部分的时序图

Launcher-AMS

Launcher-AMS

AMS——zygote过程

获取了ActivityManager的服务(AMS)来启动Activity后,我们就要来看他的实现类AMS的startActivity方法:

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

    /**
     * Priority we boost main thread and RT of top app to.
     */
    public static final int TOP_APP_PRIORITY_BOOST = -10;

    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
    private static final String TAG_BACKUP = TAG + POSTFIX_BACKUP;
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());   //注释1
    }

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

    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");   //注释3

         //检查启动Activity的userId是否是合法的
        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");    //注释4
          
        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")   //注释5
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();     
    }
}

首先在startActivity方法中又直接调用了父类的startActivityAsUser,最后调用自己的startActivityAsUser方法,注释3处会检查该进程是否被隔离了,然后检查启动activity的userId是否合法,最后进行了一长串的链式调用,我们看最后的execute方法。

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

这里有一个判断,他会返回true,为什么呢,在之前链式调用setMayWait方法时:

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

可见,下一步会调用startActivityMayWait方法,内部调用了startActivityLocked方法,然后进入startActivity方法,之后又调用了startActivityUnchecked方法,然后调用了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked,这个时候启动过程就从ActivityStarter 转移到ActivityStackSupervisor,源码调用过程如下:

//这里传进来的参数中比之前多了一个TaskRecord对象,代表着启动的activity所在的栈
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) {
            
    ···
    // 获得调用者的uid和pid
    final int realCallingPid = Binder.getCallingPid();
    final int realCallingUid = Binder.getCallingUid();
    ···
     // 从PackageManagerService处获取应用信息,PackageManagerService会解析应用的AndroidManifest.xml文件
     //然后把应用信息保存
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */,computeResolveFilterUid(
            callingUid, realCallingUid, mRequest.filterCallingUid));
       
    if (rInfo == null) {
       ...
    }
    
    // 根据ResolveInfo取得ActivityInfo,ActivityInfo保存着Activity的基本信息
    // Collect information about the target of the Intent.
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    ···
    
    //ActivityRecord也是activity任务栈模型中十分重要的一个数据结构 用来描述activity 记录了很多关键信息
    final ActivityRecord[] outRecord = new ActivityRecord[1];
    
    // 调用startActivity 并将TaskRecord 和 ActivityRecord传了进去
    int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

    Binder.restoreCallingIdentity(origId);
    ···
    
    if (outResult != null) {
           // 处理返回结果
           ...
    }
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
    return res;
}

之后进入了startActivivty方法中,这里有三个重载方法,比较长,我们一点点来看:

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
        //启动的理由不能为空
        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
        //紧接着调用了另一个startActivity方法
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask, allowPendingRemoteAnimationRegistryLookup);

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

        return getExternalResult(mLastStartActivityResult);
    }
    
}
    
    //这一个startActivity重载方法代码较长 截取了部分重要部分分析
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
        int err = ActivityManager.START_SUCCESS;
        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle
                = options != null ? options.popAppVerificationBundle() : null;
        //ProcessRecord类似于ActivityRecord 用于描述一个应用程序进程
        ProcessRecord callerApp = null;
        //这个caller是一个IApplicationThread类型的对象 对应的是Launcher进程的ApplicationThread对象
        if (caller != null) {
            //得到Launcher进程的callerApp
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                //获取Launcher进程的pid 和 uid
                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;
            }
        }

        //此处省略大量代码细节
        ······

        //创建即将要启动的activity的描述类ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        //为outActivity赋值 之后的调用会将它传递下去
        if (outActivity != null) {
            outActivity[0] = r;
        }

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

        final ActivityStack stack = mSupervisor.mFocusedStack;

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

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

        mController.doPendingActivityLaunches(false);

        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }
    
    //现在来看看最后一个startActivity方法做了哪些任务
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        //省略大量代码
        ······

        // Should this be considered a new task?
        int result = START_SUCCESS;
        //启动根activity需要将flag设置为FLAG_ACTIVITY_NEW_TASK
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            //创建新的TaskRecord 用于描述新的Activity任务栈
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
        if (result != START_SUCCESS) {
            return result;
        }

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

        mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);

        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mService.mWindowManager.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                
                //进入ActivityStackSupervisor
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

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

        return START_SUCCESS;
    }

这里来到了ActivityStackSupervisor这个类,上面简单提过一点ActivityStack的作用,而它主要是来管理ActivityStack的,继续看resumeFocusedStackTopActivityLocked方法又是如何运作的:

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

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

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

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

        return false;
    }

这个方法又调用了自身的resumeTopActivityInnerLocked方法,这个方法特别长,我们仔细看看:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
   if (!mService.mBooting && !mService.mBooted) {
       // Not ready yet!
       return false;
   }

   // 获取TaskRecord的栈顶Activity,如果正常的话这个ActivityRecord为待启动的Activity 
   // Find the next top-most activity to resume in this stack that is not finishing and is
   // focusable. If it is not focusable, we will fall into the case below to resume the
   // top activity in the next focusable task.
   final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

   final boolean hasRunningActivity = next != null;

   ...

   // 将待启动的Activity从下面几个队列中移除
   // The activity may be waiting for stop, but that is no longer
   // appropriate for it.
   mStackSupervisor.mStoppingActivities.remove(next);
   mStackSupervisor.mGoingToSleepActivities.remove(next);
   next.sleeping = false;
   mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);

   if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

   // 如果系统当前正在中断一个Activity,需要先等待那个Activity pause完毕,之后系统会重新调用resumeTopActivityInnerLocked函数,找到下一个要启动的Activity
   // If we are currently pausing an activity, then don't do anything until that is done.
   if (!mStackSupervisor.allPausedActivitiesComplete()) {
       if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
               "resumeTopActivityLocked: Skip resume: some activity pausing.");
       if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
       return false;
   }

   ...

   boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
   // mResumedActivity指向上一次启动的Activity,也就是当前界面显示的Activity
   if (mResumedActivity != null) {
       // 如果当前界面显示了一个Activity,那么在启动新的Activity之前
       // 必须中断当前的Activity,也就是调用当前Activity的onPause函数
       if (DEBUG_STATES) Slog.d(TAG_STATES,
               "resumeTopActivityLocked: Pausing " + mResumedActivity);
       pausing |= startPausingLocked(userLeaving, false, next, false);
   }
   if (pausing && !resumeWhilePausing) {
       //如果系统正在中断当前启动的Activity,并且未设置FLAG_RESUME_WHILE_PAUSING标签则会  
       //进入该分支,等当前Activity中断完成之后会重新调用resumeTopActivityInnerLocked函数
       if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
               "resumeTopActivityLocked: Skip resume: need to start pausing");
       // At this point we want to put the upcoming activity's process
       // at the top of the LRU list, since we know we will be needing it
       // very soon and it would be a waste to let it get killed if it
       // happens to be sitting towards the end.
       if (next.app != null && next.app.thread != null) {
           // 在中断当前界面的Activity时,调整待启动Activity所在进程的优先级,保证其不被kill
           mService.updateLruProcessLocked(next.app, true, null);
       }
       if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
       if (lastResumed != null) {
           lastResumed.setWillCloseOrEnterPip(true);
       }

       return true;
   } else if (mResumedActivity == next && next.isState(RESUMED)
           && mStackSupervisor.allResumedActivitiesComplete()) {
       // It is possible for the activity to be resumed when we paused back stacks above if the
       // next activity doesn't have to wait for pause to complete.
       // So, nothing else to-do except:
       // Make sure we have executed any pending transitions, since there
       // should be nothing left to do at this point.
       executeAppTransition(options);
       if (DEBUG_STATES) Slog.d(TAG_STATES,
               "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
       if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
       return true;
   }

   // 若之前存在未正常结束的Activity,那么要优先结束掉这些Activity
   // If the most recent activity was noHistory but was only stopped rather
   // than stopped+finished because the device went to sleep, we need to make
   // sure to finish it as we're making a new activity topmost.
   if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
           !mLastNoHistoryActivity.finishing) {
       if (DEBUG_STATES) Slog.d(TAG_STATES,
               "no-history finish of " + mLastNoHistoryActivity + " on new resume");
       requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
               null, "resume-no-history", false);
       mLastNoHistoryActivity = null;
   }

...

   ActivityStack lastStack = mStackSupervisor.getLastStack();
   if (next.app != null && next.app.thread != null) {
       // 如果待启动的Activity已有对应的进程存在,则只需要重启Activity
       ...

   } else {
       // Whoops, need to restart this activity!
       if (!next.hasBeenLaunched) {
           next.hasBeenLaunched = true;
       } else {
           if (SHOW_APP_STARTING_PREVIEW) {
               next.showStartingWindow(null /* prev */, false /* newTask */,
                       false /* taskSwich */);
           }
           if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
       }
       if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
       //如果待启动的Activity进程不存在则调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程
       mStackSupervisor.startSpecificActivityLocked(next, true, true);
   }

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

这个方法比较长,但是也可以清楚的发现些比较关键的地方:

  • 如果mResumedActivity不为空,则需要先暂停这个Activity。mResumedActivity代表当前已经存在于界面的Activity。当需要启动一个新的Activity时,需要先停止当前的Activity。这部分工作由startPausingLocked函数来完成。当前的Activity被中断后,将重新启动新的Activity。
  • 当mResumedActivity为空时,若待启动的Activity对应的进程已经存在,那么仅需要重新启动该Activity;否则,需要调用ActivityStackSupervisor的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);
    }

这个方法的内部实现可以发现它的作用是根据app进程是否存在来调用不同的方法,当app进程已经存在就直接调用了realStartActivityLocked方法,否则调用startProcessLocked方法,顾名思义这个方法将用于app进程的创建,当然真正的创建工作并不是他完成的,想知道他是在哪实现的,还需要知道mService是什么,通过构造方法我们发现,其实就是AMS:

public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
        mService = service;
        mLooper = looper;
        mHandler = new ActivityStackSupervisorHandler(looper);
 }

相关文章

网友评论

    本文标题:03 App启动流程(一)

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