【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,不过不是分析重点,可自行了解

相关推荐
轻口味1 小时前
Android应用性能优化
android
全职计算机毕业设计1 小时前
基于 UniApp 平台的学生闲置物品售卖小程序设计与实现
android·uni-app
dgiij2 小时前
AutoX.js向后端传输二进制数据
android·javascript·websocket·node.js·自动化
SevenUUp3 小时前
Android Manifest权限清单
android
高林雨露3 小时前
Android 检测图片抓拍, 聚焦图片后自动完成拍照,未对准图片的提示请将摄像头对准要拍照的图片
android·拍照抓拍
wilanzai3 小时前
Android View 的绘制流程
android
INSBUG4 小时前
CVE-2024-21096:MySQLDump提权漏洞分析
android·adb
Mercury Random5 小时前
Qwen 个人笔记
android·笔记
苏苏码不动了6 小时前
Android 如何使用jdk命令给应用/APK重新签名。
android
aqi006 小时前
FFmpeg开发笔记(五十三)移动端的国产直播录制工具EasyPusher
android·ffmpeg·音视频·直播·流媒体