Google关键提交
Replace old app transition type to new transition type (1/N)
Replace old app transition type to new transition type (2/N)
Replace old app transition type to new transition type (3/N)
从提交说明可以看出这次重构主要做了三件事:
- 将旧的TransitionType注更为TransitionOldType
- 增加AppTransitionController#getTransitCompatType方法用于确定apptransition类型
- 移除了大量old transition逻辑
原来的TransitionType注解变更为TransitionOldType
- core/java/android/view/WindowManager.java
- packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
重新定义了新的TransitionType
TransitionType参数全部变更为TransitionOldType
core/java/android/view/RemoteAnimationDefinition.java
core/java/android/window/TransitionInfo.java
libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
services/core/java/com/android/server/wm/AccessibilityController.java
services/core/java/com/android/server/wm/AppTransitionController.java
...
修改了prepareAppTransition的调用逻辑
// services/core/java/com/android/server/wm/AppTransition.java
private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>();
boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) {
if (mService.mAtmService.getTransitionController().getTransitionPlayer() != null) {
return false;
}
mNextAppTransitionRequests.add(transit);
mNextAppTransitionFlags |= flags;
updateBooster();
removeAppTransitionTimeoutCallbacks();
mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable,
APP_TRANSITION_TIMEOUT_MS);
return prepare();
}
对比AndroidR源码,不再使用之前的mNextAppTransition变量直接指定下一次的transition类型,
而是替换为将transition类型添加到mNextAppTransitionRequests列表
增加getTransitCompatType方法确定transit类型
// services/core/java/com/android/server/wm/AppTransitionController.java
void handleAppTransitionReady() {
final @TransitionOldType int transit = getTransitCompatType(
mDisplayContent.mAppTransition,
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
mWallpaperControllerLocked.getWallpaperTarget(), getOldWallpaper(),
mDisplayContent.mSkipAppTransitionAnimation);
}
int goodToGo(@TransitionOldType int transit, ActivityRecord topOpeningApp) {
mNextAppTransitionFlags = 0;
mNextAppTransitionRequests.clear();
...
}
在handleAppTransitionReady中使用getTransitCompatType方法获取将要执行的transit类型;
在goodToGo方法即app transition将要执行前清除mNextAppTransitionRequests列表。
// services/core/java/com/android/server/wm/AppTransitionController.java
/**
* Get old transit type based on the current transit requests.
*
* @param appTransition {@link AppTransition} for managing app transition state.
* @param openingApps {@link ActivityRecord}s which are becoming visible.
* @param closingApps {@link ActivityRecord}s which are becoming invisible.
* @param wallpaperTarget If non-null, this is the currently visible window that is associated
* with the wallpaper.
* @param oldWallpaper The currently visible window that is associated with the wallpaper in
* case we are transitioning from an activity with a wallpaper to one
* without. Otherwise null.
*/
static @TransitionOldType int getTransitCompatType(AppTransition appTransition,
ArraySet<ActivityRecord> openingApps, ArraySet<ActivityRecord> closingApps,
@Nullable WindowState wallpaperTarget, @Nullable WindowState oldWallpaper,
boolean skipAppTransitionAnimation) {
// 1.确定openning app和closing app中是否有能作为wallpapertarget的
final boolean openingAppHasWallpaper = canBeWallpaperTarget(openingApps)
&& wallpaperTarget != null;
final boolean closingAppHasWallpaper = canBeWallpaperTarget(closingApps)
&& wallpaperTarget != null;
// 2. 锁屏动画享有最高优先级
switch (appTransition.getKeyguardTransition()) {
case TRANSIT_KEYGUARD_GOING_AWAY:
return openingAppHasWallpaper ? TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER
: TRANSIT_OLD_KEYGUARD_GOING_AWAY;
case TRANSIT_KEYGUARD_OCCLUDE:
// When there is a closing app, the keyguard has already been occluded by an
// activity, and another activity has started on top of that activity, so normal
// app transition animation should be used.
return closingApps.isEmpty() ? TRANSIT_OLD_KEYGUARD_OCCLUDE
: TRANSIT_OLD_ACTIVITY_OPEN;
case TRANSIT_KEYGUARD_UNOCCLUDE:
return TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
}
// 3. 如果dc设置了mSkipAppTransitionAnimation,将跳过动画
if (skipAppTransitionAnimation) {
return WindowManager.TRANSIT_OLD_UNSET;
}
final @TransitionFlags int flags = appTransition.getTransitFlags();
final @TransitionType int firstTransit = appTransition.getFirstAppTransition();
// 4. 处理几种特殊场景
if (appTransition.containsTransitRequest(TRANSIT_CHANGE)) {
return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
}
if ((flags & TRANSIT_FLAG_APP_CRASHED) != 0) {
return TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
}
if (firstTransit == TRANSIT_NONE) {
return TRANSIT_OLD_NONE;
}
// 5. 在某些场景下我们open/close新的activity或task
// 但实际上,只有在现有activity之上的一个半透明活动才是打开/关闭
// 这种情况下,对半透明的app使用特殊动画
if (isNormalTransit(firstTransit)) {
boolean allOpeningVisible = true;
boolean allTranslucentOpeningApps = !openingApps.isEmpty();
for (int i = openingApps.size() - 1; i >= 0; i--) {
final ActivityRecord activity = openingApps.valueAt(i);
if (!activity.isVisible()) {
allOpeningVisible = false;
if (activity.fillsParent()) {
allTranslucentOpeningApps = false;
}
}
}
boolean allTranslucentClosingApps = !closingApps.isEmpty();
for (int i = closingApps.size() - 1; i >= 0; i--) {
if (closingApps.valueAt(i).fillsParent()) {
allTranslucentClosingApps = false;
break;
}
}
if (allTranslucentClosingApps && allOpeningVisible) {
return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
}
if (allTranslucentOpeningApps && closingApps.isEmpty()) {
return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
}
}
// 6.对WallPaperTarget场景做处理
final ActivityRecord topOpeningApp = getTopApp(openingApps,
false /* ignoreHidden */);
final ActivityRecord topClosingApp = getTopApp(closingApps,
true /* ignoreHidden */);
if (closingAppHasWallpaper && openingAppHasWallpaper) {
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
switch (firstTransit) {
case TRANSIT_OPEN:
case TRANSIT_TO_FRONT:
return TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
case TRANSIT_CLOSE:
case TRANSIT_TO_BACK:
return TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
}
} else if (oldWallpaper != null && !openingApps.isEmpty()
&& !openingApps.contains(oldWallpaper.mActivityRecord)
&& closingApps.contains(oldWallpaper.mActivityRecord)
&& topClosingApp == oldWallpaper.mActivityRecord) {
// We are transitioning from an activity with a wallpaper to one without.
return TRANSIT_OLD_WALLPAPER_CLOSE;
} else if (wallpaperTarget != null && wallpaperTarget.isVisible()做
&& openingApps.contains(wallpaperTarget.mActivityRecord)
&& topOpeningApp == wallpaperTarget.mActivityRecord
/* && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE */) {
// We are transitioning from an activity without
// a wallpaper to now showing the wallpaper
return TRANSIT_OLD_WALLPAPER_OPEN;
}
// 7.处理一般场景,决定使用TASK动画还是ACTIVITY动画
final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
openingApps, closingApps, true /* visible */);
final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
openingApps, closingApps, false /* visible */);
final boolean isActivityOpening = !openingWcs.isEmpty()
&& openingWcs.valueAt(0).asActivityRecord() != null;
final boolean isActivityClosing = !closingWcs.isEmpty()
&& closingWcs.valueAt(0).asActivityRecord() != null;
final boolean isTaskOpening = !openingWcs.isEmpty() && !isActivityOpening;
final boolean isTaskClosing = !closingWcs.isEmpty() && !isActivityClosing;
if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && isTaskOpening) {
return TRANSIT_OLD_TASK_TO_FRONT;
}
if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && isTaskClosing) {
return TRANSIT_OLD_TASK_TO_BACK;
}
if (appTransition.containsTransitRequest(TRANSIT_OPEN)) {
if (isTaskOpening) {
return (appTransition.getTransitFlags() & TRANSIT_FLAG_OPEN_BEHIND) != 0
? TRANSIT_OLD_TASK_OPEN_BEHIND : TRANSIT_OLD_TASK_OPEN;
}
if (isActivityOpening) {
return TRANSIT_OLD_ACTIVITY_OPEN;
}
}
if (appTransition.containsTransitRequest(TRANSIT_CLOSE)) {
if (isTaskClosing) {
return TRANSIT_OLD_TASK_CLOSE;
}
if (isActivityClosing) {
for (int i = closingApps.size() - 1; i >= 0; i--) {
if (closingApps.valueAt(i).visibleIgnoringKeyguard) {
return TRANSIT_OLD_ACTIVITY_CLOSE;
}
}
// Skip close activity transition since no closing app can be visible
return WindowManager.TRANSIT_OLD_UNSET;
}
}
if (appTransition.containsTransitRequest(TRANSIT_RELAUNCH)
&& !openingWcs.isEmpty() && !openingApps.isEmpty()) {
return TRANSIT_OLD_ACTIVITY_RELAUNCH;
}
return TRANSIT_OLD_NONE;
}
getTransitCompatType将会扫描在prepare阶段设置的transit列表(mNextAppTransitionRequests), 最终决定app tranisition的类型,可以看到最终确定的transit都还是TransitionOldType类型的 - -!
总结getTransitionCompatType主要做了以下工作:
- 确定openning app和closing app中是否有能作为WallpaperTarget的, WallpaperTarget是指想要让壁纸显示在其背后的窗口。
- 锁屏动画享有最高优先级,如果transition请求列表中包含锁屏动画类型,将直接返回keyguard transition,这其中包括锁屏解锁(keyguardGoingAway)动画、锁屏被覆盖(occlude)、取消覆盖(unocclude)动画
- 如果没有锁屏动画并且dc设置了mSkipAppTransitionAnimation,将跳过动画。 跳过动画的场景是:假设没有设置锁屏,启动了一个activity后灭屏再亮屏,不需要app transition
- 处理几种特殊的flag或transition请求
- 处理半透明activity场景
- 处理WallPaperTarget场景
- 处理一般场景,决定使用TASK动画还是ACTIVITY动画