背景:
本节课开始带大家来开始分析ShellTransition的最开始的WMCore端启动Transition部分的相关的内容及源码剖析。
源码分析部分:
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment,
BalVerdict balVerdict,
NeededUriGrants intentGrants, int realCallingUid) {
// Create a transition now to record the original intent of actions taken within
// startActivityInner. Otherwise, logic in startActivityInner could start a different
// transition based on a sub-action.
// Only do the create here (and defer requestStart) since startActivityInner might abort.
final TransitionController transitionController = r.mTransitionController;
//创建对应的Transition
Transition newTransition = transitionController.isShellTransitionsEnabled()
? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null;
RemoteTransition remoteTransition = r.takeRemoteTransition();
mService.deferWindowLayout();
//把ActivityRecord进行collect收集处理
transitionController.collect(r);
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, options, inTask, inTaskFragment, balVerdict,
intentGrants, realCallingUid);
} catch (Exception ex) {
Slog.e(TAG, "Exception on startActivityInner", ex);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
//handleStartResult中会对transition进行requestStartTransition处理
startedActivityRootTask = handleStartResult(r, options, result, newTransition,
remoteTransition);
}
上面startActivityUnchecked中主要有3个部分和transition相关步骤
1、创建并启动收集对应的Transition
Transition newTransition = transitionController.isShellTransitionsEnabled()
? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null;
这里transitionController.createAndStartCollecting(TRANSIT_OPEN)就是创建出对应的Transition
frameworks/base/services/core/java/com/android/server/wm/TransitionController.java
Transition createAndStartCollecting(int type) {
//构建Transition
Transition transit = new Transition(type, 0 /* flags */, this, mSyncEngine);
//调用moveToCollecting
moveToCollecting(transit);
return transit;
}
/** Starts Collecting */
void moveToCollecting(@NonNull Transition transition) {
mCollectingTransition = transition;
//实际调用了Transition的startCollecting
mCollectingTransition.startCollecting(timeoutMs);
}
核心重点就是startCollecting方法
frameworks/base/services/core/java/com/android/server/wm/Transition.java
/** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
void startCollecting(long timeoutMs) {
//设置状态为COLLECTING
mState = STATE_COLLECTING;
//调用mSyncEngine方法获取mSyncId
mSyncId = mSyncEngine.startSyncSet(this, timeoutMs,
TAG + "-" + transitTypeToString(mType),
mParallelCollectType != PARALLEL_TYPE_NONE);
mSyncEngine.setSyncMethod(mSyncId, TransitionController.SYNC_METHOD);
}
这里主要看看mSyncEngine.startSyncSet方法
frameworks/base/services/core/java/com/android/server/wm/BLASTSyncEngine.java
int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name,
boolean parallel) {
final SyncGroup s = prepareSyncSet(listener, name);
startSyncSet(s, timeoutMs, parallel);
return s.mSyncId;
}
/**
* Prepares a {@link SyncGroup} that is not active yet. Caller must call {@link #startSyncSet}
* before calling {@link #addToSyncSet(int, WindowContainer)} on any {@link WindowContainer}.
*/
SyncGroup prepareSyncSet(TransactionReadyListener listener, String name) {
return new SyncGroup(listener, mNextSyncId++, name);
}
void startSyncSet(SyncGroup s, long timeoutMs, boolean parallel) {
//新建的SyncGroup放入到mActiveSyncs
mActiveSyncs.add(s);
// For now, parallel implies this.
s.mIgnoreIndirectMembers = parallel;
scheduleTimeout(s, timeoutMs);
}
总结一下transitionController.createAndStartCollecting干的事情
1、创建出systemserver层面的一个Transition
2、调用Transition的startCollecting设置Transition的mState为STATE_COLLECTING
3、调用BLASTSyncEngine创建一个SyncGroup,每个SyncGroup有一个固定的SyncId
4、把创建的SyncGroup放入到BLASTSyncEngine的mActiveSyncs集合中
2、正式收集collect对应WindowContainer
上面第一步只是处于收集中的一种状态,并不是真正收集,在第二步就是正式开始收集各个WindowContainer
transitionController.collect®方法进行剖析
frameworks/base/services/core/java/com/android/server/wm/TransitionController.java
/** @see Transition#collect */
void collect(@NonNull WindowContainer wc) {
if (mCollectingTransition == null) return;
//mCollectingTransition就是第一步new的Transition
mCollectingTransition.collect(wc);
}
这里实际调用到了Transition的collect
/**
* Adds wc to set of WindowContainers participating in this transition.
*/
void collect(@NonNull WindowContainer wc) {
//这里判断一定要属于Collecting状态
if (!isCollecting()) {
// Too late, transition already started playing, so don't collect.
return;
}
if (!isInTransientHide(wc)) {
//调用addToSyncSet把wc放入到SyncEngine中
mSyncEngine.addToSyncSet(mSyncId, wc);
}
ChangeInfo info = mChanges.get(wc);
if (info == null) {
//针对wc构造对应的ChangeInfo
info = new ChangeInfo(wc);
updateTransientFlags(info);
//加入到mChanges集合中
mChanges.put(wc, info);
}
//把wc加入到Transition的mParticipants集合中
mParticipants.add(wc);
recordDisplay(wc.getDisplayContent());
if (info.mShowWallpaper) {
// Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
wc.mDisplayContent.mWallpaperController.collectTopWallpapers(this);
}
}
boolean isCollecting() {
return mState == STATE_COLLECTING || mState == STATE_STARTED;
}
collect里面主要有3个部分,addToSyncSet添加wc,通过wc构造ChangeInfo,mParticipants集合添加wc。
这里重点来看看addToSyncSet方法
frameworks/base/services/core/java/com/android/server/wm/BLASTSyncEngine.java
void addToSyncSet(int id, WindowContainer wc) {
getSyncGroup(id).addToSync(wc);
}
private void addToSync(WindowContainer wc) {
if (mRootMembers.contains(wc)) {
return;
}
final SyncGroup dependency = wc.getSyncGroup();
if (dependency != null && dependency != this && !dependency.isIgnoring(wc)) {
} else {
mRootMembers.add(wc);//添加到mRootMembers的集合中
wc.setSyncGroup(this);//让WindowContainer与SyncGroup产生链接
}
wc.prepareSync();//调用WindowContainer的prepareSync方法
}
addToSyncSet主要就是
1、添加到mRootMembers的集合中
2、让WindowContainer与SyncGroup产生链接
3、调用WindowContainer的prepareSync方法
下面继续看看prepareSync方法
frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
boolean prepareSync() {
if (mSyncState != SYNC_STATE_NONE) {
// Already part of sync
return false;
}
//这里会遍历WindowContainer的所有child,然后让child也进行prepareSync
for (int i = getChildCount() - 1; i >= 0; --i) {
final WindowContainer child = getChildAt(i);
child.prepareSync();
}
//核心就是把WindowContainer的mSyncState设置成了SYNC_STATE_READY状态
mSyncState = SYNC_STATE_READY;
return true;
}
可以看出WindowContainer的prepareSync主要就是对mSyncState变量变成SYNC_STATE_READY。
3、requestStartTransition剖析
/** Asks the transition player (shell) to start a created but not yet started transition. */
@NonNull
Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
@Nullable RemoteTransition remoteTransition,
@Nullable TransitionRequestInfo.DisplayChange displayChange) {
//省略部分
//构造出对应TransitionRequestInfo
final TransitionRequestInfo request = new TransitionRequestInfo(transition.mType,
startTaskInfo, pipTaskInfo, remoteTransition, displayChange,
transition.getFlags(), transition.getSyncId());
//跨进程通讯通知到systemui端
mTransitionPlayers.getLast().mPlayer.requestStartTransition(
transition.getToken(), request);
//这里把remoteTransition设置给transition
if (remoteTransition != null) {
transition.setRemoteAnimationApp(remoteTransition.getAppThread());
}
return transition;
}
这个requestStartTransition执行后,就会跨进程通讯到wmshell端,即就是systemui进程,接下来就是要systemui进程来负责相关的Transition的业务。
更多framework实战干货,请关注下面“千里马学框架”