【Android 13】Activity启动流程-3

为Activity启动的第三篇, 主要是在目标应用进程启动后的逻辑

1. 应用进程创建

java的方法的main函数 其实在执行到AMS::attachApplication前,应用进程也有一段逻辑

java 复制代码
# ActivityThread
    // ApplicationThread 是 AMS 作为 C 端时,与应用进程通信的方式
    final ApplicationThread mAppThread = new ApplicationThread();
    public static void main(String[] args) {
        ......
        // 重点 *1. 主线程Looper 处理已经创建ActivityThread
        // 主线程Looper
        Looper.prepareMainLooper();
        ......
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        // 主线程Looper
         Looper.loop();
    }
    private void attach(boolean system, long startSeq) {
        ......
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //重点 *2.  将mAppThread告知AMS,用于AMS与应用进程通信
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        ......
    }

应用进程(电话)创建完毕后,在main方法里会执行attach,就是要将自己的信息告知AMS,毕竟AMS 是管理模块。

2. AMS收到"电话"进程创建完毕的执行 realStartActivityLocked

因为进程创建也不是由AMS执行,AMS也不知道具体什么时候进程创建好了,所以在应用进程创建好后,会执行 AMS::attachApplication来告知。 这样就可以AMS就知道可以开始处理后续逻辑了

2.1 调用链

arduino 复制代码
AMS::attachApplication
    AMS::attachApplicationLocked
        ActivityThread::bindApplication
            ActivityTaskManagerService.LocalService::attachApplication
                WindowContainer::forAllRootTasks  --- 省略forAllRootTasks等固定堆栈
                    Task::forAllRootTasks
                        WindowContainer::forAllActivities
                            ActivityRecord::forAllActivities
                                RootWindowContainer.AttachApplicationHelper::test
                                    RootWindowContainer.AttachApplicationHelper::test
                                        ActivityTaskSupervisor::realStartActivityLocked  -- 构建LaunchActivityItem

接上一篇知道如果进程启动了ActivityTaskSupervisor::startSpecificActivity就会走进去ActivityTaskSupervisor::realStartActivityLocked。 但是可能会好奇怎么就知道要执行应用MainActivity到onCreate就一定是在这个方法里呢? 调试方法有很多,比如加log,打堆栈,但是对应这个逻辑比较简单的是,需要执行Activity启动到onCreate的控制在LaunchActivityItem中,而LaunchActivityItem在framework的引用出了本身,就只有在ActivityTaskSupervisor。

2.2 主流程

scss 复制代码
# AMS 
    // 当应用进程调用attachApplication 执行
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        if (thread == null) {
            throw new SecurityException("Invalid application interface");
        }
        synchronized (this) {
            // 获取 应用进程的信息后执行attachApplicationLocked
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
            // 需要启动应用的进程数据
            ProcessRecord app;
            ......
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    // 通过mPidsSelfLocked获取
                    app = mPidsSelfLocked.get(pid);
                }
                ......
            } 
            ...... 
            // 触发ActivityThread::bindApplication 逻辑
            if (app.getIsolatedEntryPoint() != null) {

            } else if (instr2 != null) {
                // bindApplication
                thread.bindApplication(processName, appInfo,
                        app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                        providerList,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.getCompat(), getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.getDisabledCompatChanges(), serializedSystemFontMap,
                        app.getStartElapsedTime(), app.getStartUptime());      
            } else {
                // bindApplication
                thread.bindApplication(processName, appInfo,
                        app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                        providerList, null, profilerInfo, null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.getCompat(), getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.getDisabledCompatChanges(), serializedSystemFontMap,
                        app.getStartElapsedTime(), app.getStartUptime());
            }
            ......
            if (normalMode) {
                try {
                    // 重点 触发构建 LaunchActivityItem 流程
                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
            ......
    }

这里是触发 LaunchActivityItem 的流程主线 , mAtmInternal是 ATMS 的内部类 LocalService

java 复制代码
# ActivityTaskManagerService.LocalService
        @Override
        public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
            ......
            return mRootWindowContainer.attachApplication(wpc);
            ......
        }
# RootWindowContainer
        boolean attachApplication(WindowProcessController app) throws RemoteException {
            try {
                return mAttachApplicationHelper.process(app);
            } finally {
                mAttachApplicationHelper.reset();
            }
        }
# RootWindowContainer.AttachApplicationHelper
        boolean process(WindowProcessController app) throws RemoteException {
            mApp = app;
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                // 重点* 调用每个容器的 forAllRootTasks
                getChildAt(displayNdx).forAllRootTasks(this);
                if (mRemoteException != null) {
                    throw mRemoteException;
                }
            }
            ......
        }

这里的重点是执行了forAllRootTasks,当孩子是RootTask容器的时候才会执行Lambda表达式的内容。

AttachApplicationHelper 必然实现了 Consumer 接口, 直接看其 accept 实现即可

java 复制代码
# RootWindowContainer.AttachApplicationHelper
  private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
        ......
        boolean process(WindowProcessController app) throws RemoteException {
            mApp = app;
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                // 重点*1. 调用每个容器的 forAllRootTasks
                getChildAt(displayNdx).forAllRootTasks(this);
                if (mRemoteException != null) {
                    throw mRemoteException;
                }
            }
            ......
        }
        @Override
        public void accept(Task rootTask) {
            ......
            // 执行 topRunningActivity
            mTop = rootTask.topRunningActivity();
            // 重点*2. 执行accept 让容器下的每个 ActivityRecord 执行
            rootTask.forAllActivities(this);
        }
        @Override
        public boolean test(ActivityRecord r) {
            ......
            try {
                // 重点*3. 执行 realStartActivityLocked 触发创建LaunchActivityItem
                if (mTaskSupervisor.realStartActivityLocked(r, mApp,
                        mTop == r && r.getTask().canBeResumed(r) /* andResume */,
                        true /* checkConfig */)) {
                    mHasActivityStarted = true;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
                mRemoteException = e;
                return true;
            }
            return false;
        }
  }

重点分析: AttachApplicationHelper 实现类Consumer,Predicate接口。 对应要实现的函数分别为accept和test

  1. RootWindowContainer 的 child 自然是 WindowContainer

这里可能有个疑问就是 forAllRootTasks 一个参数的方法有2个重载,参数分别为Consumer 接口和Predicate 接口。 当前的AttachApplicationHelper类这两个都实现了, 怎么判断执行的是哪个呢? 答案也很简单, 只要看一下泛型参数即可。 2. 根据上面的解释, 第二步执行 accept回调, 内部执行 Task::forAllActivities 函数, 但是Task本身没有该方法, 该方法定义在父类 WindowContainer 中

  1. 那么逻辑就来到了气到的realStartActivityLocked ,其内部会构建 LaunchActivityItem,这个在【Activity生命周期事务执行逻辑】有详细说明 在把 ActivityTaskSupervisor::realStartActivityLocked方法看一下,现在已知 setLifecycleStateRequest为ResumeActivityItem
scss 复制代码
# ActivityTaskSupervisor 

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
            //  重点* 判断是否执行完了pause 。 也就是2个条件之一,必须要执行完pause才可以进入后面
            if (!mRootWindowContainer.allPausedActivitiesComplete()) {
                // While there are activities pausing we skipping starting any new activities until
                // pauses are complete. NOTE: that we also do this for activities that are starting in
                // the paused state because they will first be resumed then paused on the client side.
                ProtoLog.v(WM_DEBUG_STATES,
                        "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
                        r);
                return false;
            }
            ......
                // 重点*1. 创建Activity启动事务.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);
                // 判断Activity是否处于向前转场状态
                final boolean isTransitionForward = r.isTransitionForward();
                // 获取Activity所在 TaskFragment Token
                final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
                // 重点*2. 将构建的 LaunchActivityItem 添加到 clientTransaction 中
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                        proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                        results, newIntents, r.takeOptions(), isTransitionForward,
                        proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                        r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
                // 重点*3. 设置预期的最终状态
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    // Resume逻辑,启动走的这。 表示需要执行到onCreate
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                } else {
                    //  Pause 逻辑
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // 重点*4. 调度事务,将clientTransaction添加到生命周期管理器中
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    }

2.2.1 LaunchActivityItem handleLaunchActivity (启动ActivityonCreate)

2.2.1.1 调用链

arduino 复制代码
LaunchActivityItem::execute
    ActivityThread::handleLaunchActivity
        ActivityThread::performLaunchActivity
            Instrumentation::newActivity --- 创建Activity
            Activity::attach  ---处理Window相关
                Window::init
                Window::setWindowManager
            Instrumentation::callActivityOnCreate ---onCreate流程
                Activity::performCreate
                    Activity::onCreate  --over

2.2.1.2 主流程

接下来看 LaunchActivityItem::execute

csharp 复制代码
# LaunchActivityItem 
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                mTaskFragmentToken);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

这里的 client 是 ClientTransactionHandler 类型, 而 ActivityThread 是 ClientTransactionHandler子类

重点是这边创建了ActivityClientRecord,第一个参数就是我们要找的token

逻辑来到应用进程 ActivityThread

scss 复制代码
# ActivityThread

    public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
                    ......
                    final Activity a = performLaunchActivity(r, customIntent);
                    ......
                }
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
                Activity activity = null;
                try {
                    // 重点* 1. 通过Instrumentation 反射创建Activity
                    java.lang.ClassLoader cl = appContext.getClassLoader();
                    activity = mInstrumentation.newActivity(
                            cl, component.getClassName(), r.intent);
                    ......
                }
                try {
                    ......
                    // 重点* 2. 执行 attach 流程
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
                            r.assistToken, r.shareableActivityToken);
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        重点* 3. OnCreate流程
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                }
        ......
    }

# Instrumentation
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        // onCreate流程
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
# Activity
    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ......
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            // 执行onCreate
            onCreate(icicle);
        }
        ......
    }

写过应用的都知道,默认都是一个参数的onCreate。 流程结束

tip:在添加回调的时候,还加了个请求的生命周期, 因为 LaunchActivityItem 只是创建,但是创建完成后,需要执行到对应的生命周期。 正常情况都是希望执行到onResume,所以会设置 ResumeActivityItem,不过不是分析重点,可自行了解

相关推荐
烬奇小云3 小时前
认识一下Unicorn
android·python·安全·系统安全
顾北川_野15 小时前
Android 进入浏览器下载应用,下载的是bin文件无法安装,应为apk文件
android
CYRUS STUDIO15 小时前
Android 下内联汇编,Android Studio 汇编开发
android·汇编·arm开发·android studio·arm
右手吉他15 小时前
Android ANR分析总结
android
PenguinLetsGo17 小时前
关于 Android15 GKI2407R40 导致梆梆加固软件崩溃
android·linux
杨武博19 小时前
音频格式转换
android·音视频
音视频牛哥21 小时前
Android音视频直播低延迟探究之:WLAN低延迟模式
android·音视频·实时音视频·大牛直播sdk·rtsp播放器·rtmp播放器·android rtmp
ChangYan.1 天前
CondaError: Run ‘conda init‘ before ‘conda activate‘解决办法
android·conda
二流小码农1 天前
鸿蒙开发:ForEach中为什么键值生成函数很重要
android·ios·harmonyos
夏非夏1 天前
Android 生成并加载PDF文件
android