跳转至

Activity框架02-ActivityClientRecord

Tip

基于 android-14.0.0_r45

背景

冷启动 Activity 其生命周期 依次是 

  • onCreate()
  • onStart()
  • onResume()

在前面的 Activity框架01-客户端事务管理 分析中,在 ActivityThread 对应的 Handle方法中接受的第一个参数都是 ActivityClientRecord 类型。

那这个 ActivityClientRecord 是哪里来的呢,每一个 Handle方法接收到的 ActivityClientRecord 都是同一个吗?

我们先看看 ActivityClientRecord ,目前不知道这个 ActivityClientRecord 存在的意义,先不管。

public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {

    /**
     * Activity client record, used for bookkeeping for the real {@link Activity} instance.
     */
    public static final class ActivityClientRecord {
        @UnsupportedAppUsage
        public IBinder token;


        public ActivityClientRecord(IBinder token, Intent intent, int ident,
                                    ActivityInfo info, Configuration overrideConfig,
                                    String referrer, IVoiceInteractor voiceInteractor, Bundle state,
                                    PersistableBundle persistentState, List<ResultInfo> pendingResults,
                                    List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
                                    boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
                                    IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble,
                                    IBinder taskFragmentToken) {
            this.token = token;

            ...
        }

        ...
    }
}

倒推

根据 Activity框架01-客户端事务管理 可知,在 ActivityThread 对应的每一个 Handle方法接收到的 ActivityClientRecord 都是从对应的 item 的 execute() 得来的。

那我们就先从 LaunchActivityItem.execute() 这里入手。

LaunchActivityItem.execute()

public class LaunchActivityItem extends ClientTransactionItem {  
    @Override  
    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, mReferrer, mVoiceInteractor, mState, mPersistentState,  
                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,  
                client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,  
                mTaskFragmentToken);  
        client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);  
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);  
    }
}

这里 new 了一个 ActivityClientRecord,并通过 handleLaunchActivity() 函数把 ActivityClientRecord 传到 ActivityThread。

创建 ActivityClientRecord 时,传了一个非常重要的 IBinder 对象 token。 根据 Activity框架01-客户端事务管理 可知,中 TransactionExecutor.executeCallbacks() 会通过 ClientTransaction.getActivityToken() 获取到 token 。 那么这个 ClientTransaction 的这个 mActivityToken 又是哪里来的呢?先留一个疑问。

ActivityThread.handleLaunchActivity()

public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {

    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
        ...

        final Activity a = performLaunchActivity(r, customIntent);

        ...

        return a;
    }
}

我们不深入分析,先看主流程。

ActivityThread.performLaunchActivity()

public final class ActivityThread extends ClientTransactionHandler  
        implements ActivityThreadInternal {  

    @UnsupportedAppUsage  
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();  

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {   

        ...  

        try {  

            // updatePendingActivityConfiguration() reads from mActivities to update  
            // ActivityClientRecord which runs in a different thread. Protect modifications to            
            // mActivities to avoid race.            
            synchronized (mResourcesManager) {  
                mActivities.put(r.token, r);  
            }  

            ...  

            r.setState(ON_CREATE);  

        } catch (SuperNotCalledException e) {  
            ...  
        } catch (Exception e) {  
            ...  
        }  

        return activity;  
    }  
}

把 ActivityClientRecord 存在 mActivities 这个 map 中,key 是 ActivityClientRecord 的 token,value 是 ActivityClientRecord。

目前我们知道了 LaunchActivityItem 创建的 ActivityClientRecord 是存在 ActivityThread 的 mActivities 中。

那我们继续分析另一个 item 的 execute() 到底是创建新的 ActivityClientRecord 还是通过什么方式获取到 ActivityClientRecord 的?

ResumeActivityItem.execute()

public class ResumeActivityItem extends ActivityLifecycleItem {

    @Override
    public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r,
            @NonNull PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
        client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
                mShouldSendCompatFakeFocus, "RESUME_ACTIVITY");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

}

这里跟 LaunchActivityItem 的 execute() 方法不一样了。直接传一个 ActivityClientRecord 给 ActivityThread 的 handleResumeActivity()。

我们只能去看 ResumeActivityItem 的父类了。

ActivityTransactionItem.execute()

public abstract class ActivityTransactionItem extends ClientTransactionItem {  

    @Override  
    public final void execute(ClientTransactionHandler client, IBinder token,  
            PendingTransactionActions pendingActions) {  
        final ActivityClientRecord r = getActivityClientRecord(client, token);  

        execute(client, r, pendingActions);  
    }  

    /**  
     * Like {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)},  
     * but take non-null {@link ActivityClientRecord} as a parameter.  
     */@VisibleForTesting(visibility = PACKAGE)  
    public abstract void execute(@NonNull ClientTransactionHandler client,  
            @NonNull ActivityClientRecord r, PendingTransactionActions pendingActions);  

    /**  
     * Gets the {@link ActivityClientRecord} instance that corresponds to the provided token.  
     * @param client Target client handler.  
     * @param token Target activity token.  
     * @return The {@link ActivityClientRecord} instance that corresponds to the provided token.  
     */@NonNull ActivityClientRecord getActivityClientRecord(  
            @NonNull ClientTransactionHandler client, IBinder token) {  
        final ActivityClientRecord r = client.getActivityClient(token);  
        if (r == null) {  
            throw new IllegalArgumentException("Activity client record must not be null to execute "  
                    + "transaction item: " + this);  
        }  
        if (client.getActivity(token) == null) {  
            throw new IllegalArgumentException("Activity must not be null to execute "  
                    + "transaction item: " + this);  
        }  
        return r;  
    }  

}

从这里可以看到 getActivityClientRecord() 函数,通过 token 获取了 ActivityClientRecord。

ClientTransactionHandler 是一个抽象类,而 ActivityThread 继承 ClientTransactionHandler。

所以 client.getActivityClient() 其实就是 ActivityThread.getActivityClient() 。

根据 Activity框架01-客户端事务管理 可知,中 TransactionExecutor.executeLifecycleState() 会通过 ClientTransaction.getActivityToken() 获取到 token 。

所以也意味着跟 LaunchActivityItem.execute() 获取的 token 来源都是一样的。

这里的代码比 android-14.0.0_r30 清晰多了,之前 android-14.0.0_r30 写得有点绕。 虽然到这里我们可以明确知道都是同一个 token 了,但既然都分析了,索性继续分析这里的 mActivityToken 是什么吧。

ActivityThread.getActivityClient()

@Override  
public ActivityClientRecord getActivityClient(IBinder token) {  
    return mActivities.get(token);  
}

看到这个代码,结案了。基本上可以猜测在 LaunchActivityItem 时创建一个 ActivityClientRecord,然后保存在 ActivityThread 的 mActivities 中。后面的生命周期都是通过 ActivityThread.getActivityClient() 方法获取到这个 ActivityClientRecord 。

要追溯 mActivityToken 到底是什么,得回到 Activity框架01-客户端事务管理 最初的函数 ActivityTaskSupervisor.realStartActivityLocked(),因为 LaunchActivityItem 和 ResumeActivityItem 是那个时候被创建起来的。

而 ActivityTaskSupervisor.realStartActivityLocked() 函数里的 r.token,是在创建一个 ActivityRecord 的时候创建的。

这个结论我们不再推导,再后续的文章中我们会讲到。 我们直接从 ActivityStarter.executeRequest() 入手。

token来源

ActivityStarter.executeRequest()

class ActivityStarter {  

    private int executeRequest(Request request) {  

        ...  

        final ActivityRecord r = new ActivityRecord.Builder(mService)  
                .setCaller(callerApp)  
                .setLaunchedFromPid(callingPid)  
                .setLaunchedFromUid(callingUid)  
                .setLaunchedFromPackage(callingPackage)  
                .setLaunchedFromFeature(callingFeatureId)  
                .setIntent(intent)  
                .setResolvedType(resolvedType)  
                .setActivityInfo(aInfo)  
                .setConfiguration(mService.getGlobalConfiguration())  
                .setResultTo(resultRecord)  
                .setResultWho(resultWho)  
                .setRequestCode(requestCode)  
                .setComponentSpecified(request.componentSpecified)  
                .setRootVoiceInteraction(voiceSession != null)  
                .setActivityOptions(checkedOptions)  
                .setSourceRecord(sourceRecord)  
                .build();  

        ...  

    }  
}

ActivityStarter.executeRequest() 会创建一个 ActivityRecord。

new ActivityRecord()

final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {  

    private ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,  
                           int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,  
                           @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,  
                           ActivityInfo aInfo, Configuration _configuration, com.android.server.wm.ActivityRecord _resultTo,  
                           String _resultWho, int _reqCode, boolean _componentSpecified,  
                           boolean _rootVoiceInteraction, ActivityTaskSupervisor supervisor,  
                           ActivityOptions options, com.android.server.wm.ActivityRecord sourceRecord, PersistableBundle persistentState,  
                           TaskDescription _taskDescription, long _createTime) {  
        // 调用父类 WindowToken 的构造函数进行初始化,其中包括窗口管理服务、Token 类型等信息。  
        super(_service.mWindowManager, new Token(), TYPE_APPLICATION, true,  
                null /* displayContent */, false /* ownerCanManageAppTokens */);  

        // 将当前 ActivityRecord 的弱引用赋值给 token 的 mActivityRef
        ((Token) token).mActivityRef = new WeakReference<>(this);  
    }  

     private static class Token extends Binder {  
        // 保存 ActivityRecord 的弱引用,防止内存泄漏。  
        @NonNull WeakReference<ActivityRecord> mActivityRef;  

    }  

    static class Builder {  
        ActivityRecord build() {  
            if (mConfiguration == null) {  
                mConfiguration = mAtmService.getConfiguration();  
            }  
            return new ActivityRecord(mAtmService, mCallerApp, mLaunchedFromPid,  
                    mLaunchedFromUid, mLaunchedFromPackage, mLaunchedFromFeature, mIntent,  
                    mResolvedType, mActivityInfo, mConfiguration, mResultTo, mResultWho,  
                    mRequestCode, mComponentSpecified, mRootVoiceInteraction,  
                    mAtmService.mTaskSupervisor, mOptions, mSourceRecord, mPersistentState,  
                    mTaskDescription, mCreateTime);  
        }  
    }  
}

当启动一个新的 Activity 时,系统会创建一个新的 ActivityRecord 实例来表示这个活动,并将其添加到相应的任务栈中。 而这里正好是在 ActivityRecord 构造函数中创建了一个 Token。

WindowToken.token

class WindowToken extends WindowContainer<WindowState> {  

    /** The actual token */  
    final IBinder token;  

    protected WindowToken(WindowManagerService service, IBinder _token, int type,  
                          boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens) {  
        this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,  
                false /* roundedCornerOverlay */, false /* fromClientToken */, null /* options */);  
    }  

    protected WindowToken(WindowManagerService service, IBinder _token, int type,  
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,  
            boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {  
        super(service);  
        token = _token;  
        ...  
    }  
}

看到这里我们知道了,ActivityRecord 构造函数创建的 Token 保存在 WindowToken 函数的成员 token 变量中。

中间的一系列流程我们也不再倒推了,直接跳级到 ActivityTaskSupervisor.realStartActivityLocked() 中。

后续文章会详细讲解。

ActivityTaskSupervisor.realStartActivityLocked()

public class ActivityTaskSupervisor implements RecentTasks.Callbacks {

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,  
            boolean andResume, boolean checkConfig) throws RemoteException {  

        ...  

        // Create activity launch transaction.  
        final ClientTransaction clientTransaction = ClientTransaction.obtain(  
                proc.getThread(), r.token);  

        final boolean isTransitionForward = r.isTransitionForward();  
        final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();  

        final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());  
        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(), deviceId,  
                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));  

        // Set desired final state.  
        final ActivityLifecycleItem lifecycleItem;  
        if (andResume) {  
            lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,  
                    r.shouldSendCompatFakeFocus());  
        } else {  
            lifecycleItem = PauseActivityItem.obtain();  
        }  
        clientTransaction.setLifecycleStateRequest(lifecycleItem);  

        // Schedule transaction.  
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);  
        ...  
    }  
}

这里的 r 就是 ActivityRecord,所以 r.token 就是 WindowToken 函数的成员 token 变量。

这个函数也能看到 ClientTransaction.obtain() 传的参数是 r.token 。

ClientTransaction.obtain()

/**
 * 一个包含一系列消息的容器,这些消息可能会发送到客户端。
 * 包括一个回调列表和一个最终的生命周期状态。
 *
 * @see com.android.server.am.ClientLifecycleManager
 * @see ClientTransactionItem
 * @see ActivityLifecycleItem
 * @hide
 */
public class ClientTransaction implements Parcelable, ObjectPoolItem {


    /** 目标客户端活动。如果整个事务目标是应用程序,可能为空。 */
    private IBinder mActivityToken;

    public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
        // 从对象池中获取一个 ClientTransaction 实例
        ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);

        // 如果对象池中没有可用的实例,则创建一个新的实例
        if (instance == null) {
            instance = new ClientTransaction();
        }

        // 初始化实例的属性
        instance.mClient = client;
        instance.mActivityToken = activityToken;

        // 返回初始化后的实例
        return instance;
    }

    /**
     * 获取目标活动。
     * @return 目标活动标识符。
     */
    @Nullable @UnsupportedAppUsage 
    public IBinder getActivityToken() {
        return mActivityToken;
    }

}

mActivityToken 就是传进来的 r.token ,也就是 WindowToken 里的成员变量 token。

到这里真正的结案了, 所有的地方最终都是通过 ClientTransaction.getActivityToken() 获取到的都是同一个token,也就是 ActivityRecord 构造函数中创建的那个 Token。

特殊的ActivityRelaunchItem

虽然 ActivityRelaunchItem 也是 ActivityTransactionItem 的子类,但 ActivityTransactionItem 跟其他子类不太一样。 ActivityRelaunchItem.execute() 中并不是一直通过父类拿到 ActivityClientRecord 的。而是通过其 preExecute() 函数去拿到 ActivityClientRecord。

ActivityRelaunchItem.preExecute()

public class ActivityRelaunchItem extends ActivityTransactionItem {

    private ActivityClientRecord mActivityClientRecord;  

    @Override  
    public void preExecute(@NonNull ClientTransactionHandler client) {  
        // The local config is already scaled so only apply if this item is from server side.  
        if (!client.isExecutingLocalTransaction()) {  
            CompatibilityInfo.applyOverrideScaleIfNeeded(mConfig);  
        }  
        mActivityClientRecord = client.prepareRelaunchActivity(getActivityToken(), mPendingResults,  
                mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow);  
    }
}

这里可以看到,是通过 ActivityThread.prepareRelaunchActivity() 去拿到 ActivityClientRecord,并且传给 prepareRelaunchActivity() 函数的是 getActivityToken()。

从前面分析知道,这里的 getActivityToken() 跟别的子类都是同一个 IBinder的,也就是 ActivityTransactionItem 中的 mActivityToken。

ActivityThread.prepareRelaunchActivity()

public final class ActivityThread extends ClientTransactionHandler  
        implements ActivityThreadInternal {  

    @Override  
    public ActivityClientRecord prepareRelaunchActivity(IBinder token,  
                                                        List<ResultInfo> pendingResults,  
                                                        List<ReferrerIntent> pendingNewIntents,  
                                                        int configChanges,  
                                                        MergedConfiguration config,  
                                                        boolean preserveWindow) {  
        // 初始化目标 ActivityClientRecord        
        ActivityClientRecord target = null;  
        // 标识是否需要调度重新启动的标志  
        boolean scheduleRelaunch = false;  

        synchronized (mResourcesManager) {  
            // 遍历正在重新启动的活动列表  
            for (int i = 0; i < mRelaunchingActivities.size(); i++) {  
                ActivityClientRecord r = mRelaunchingActivities.get(i);  
                // 检查当前记录的token是否匹配  
                if (r.token == token) {  
                    target = r;  
                    ...  
                    break;  
                }  
            }  

            // 如果未找到匹配的ActivityClientRecord  
            if (target == null) {  
                // 创建新的ActivityClientRecord  
                target = new ActivityClientRecord();  
                target.token = token;  
                target.pendingResults = pendingResults;  
                target.pendingIntents = pendingNewIntents;  
                target.mPreserveWindow = preserveWindow;  
                // 将新的记录添加到重新启动活动列表中  
                mRelaunchingActivities.add(target);  
                scheduleRelaunch = true;  
            }  
            // 更新目标记录的配置  
            target.createdConfig = config.getGlobalConfiguration();  
            target.overrideConfig = config.getOverrideConfiguration();  
            target.pendingConfigChanges |= configChanges;  
        }  

        // 返回新的目标记录如果需要调度重新启动  
        return scheduleRelaunch ? target : null;  
    }  

}
  • 如果未找到匹配的 ActivityClientRecord,则创建新的 ActivityClientRecord,并返回新创建的 ActivityClientRecord
  • 如果找到匹配的 ActivityClientRecord,则返回空。也就是从不需要 relaunch。

所以除了 LaunchActivityItem 会创建新的 ActivityClientRecord ,ActivityRelaunchItem 也有可能会创建。

移除ActivityClientRecord

前面的分析我们知道了在 ActivityThread.performLaunchActivity() 中把 LaunchActivityItem 创建的 ActivityClientRecord 添加到 ActivityThread 的成员变量 mActivities 中,那是什么时候移除的呢?

根据 Activity 的生命周期猜测,应该是在 onDestroy() 的时候移除的,看代码果然如此:

public class DestroyActivityItem extends ActivityLifecycleItem {

    @Override  
    public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r,  
            @NonNull PendingTransactionActions pendingActions) {  
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");  
        client.handleDestroyActivity(r, mFinished, mConfigChanges,  
                false /* getNonConfigInstance */, "DestroyActivityItem");  
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);  
    }
}

public final class ActivityThread extends ClientTransactionHandler  
        implements ActivityThreadInternal {  

    @Override  
    public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,  
                                      boolean getNonConfigInstance, String reason) {  
        performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);  
        ...  
    }  

    void performDestroyActivity(ActivityClientRecord r, boolean finishing,  
                                int configChanges, boolean getNonConfigInstance, String reason) {  
        ...  
        // updatePendingActivityConfiguration() reads from mActivities to update  
        // ActivityClientRecord which runs in a different thread. Protect modifications to        // mActivities to avoid race.        synchronized (mResourcesManager) {  
            mActivities.remove(r.token);  
        }  
    }  

}

总结

在 app 端 Activity 和 ActivityClientRecord 是一一对应的。每一个应用开发者实现的 Activity 在创建前都会在 ActivityThread 有一个对应的 ActivityClientRecord 被创建。

也就是先在 LaunchActivityItem.execute() 中创建 ActivityClientRecord 。以创建出来的ActivityClientRecord 为参数再调用 ActivityThread.handleLaunchActivity() 。最终通过类名反射去创建应用开发都实现的 Activity,并让 ActivityClientRecord 持有此 Activity 的引用。最后再把 ActivityClientRecord 存储到 mActivities,这样一个打开的 Activity 在应用就可以被长期引用了。后续其他生命周期的流转,都是通过 token 查找到对应 Activity,再调用到具体的生命周期。

评论