Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +61 −25 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; Loading Loading @@ -1277,42 +1278,42 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } // Copy initial changes to final transition final TransitionInfo init = mOpenTransitionInfo; // find prepare open target // Find prepare open target boolean openShowWallpaper = false; ComponentName openComponent = null; final ArrayList<OpenChangeInfo> targets = new ArrayList<>(); int tmpSize; int openTaskId = INVALID_TASK_ID; WindowContainerToken openToken = null; for (int j = init.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = init.getChanges().get(j); if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { openComponent = findComponentName(change); openTaskId = findTaskId(change); openToken = findToken(change); if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED) && TransitionUtil.isOpeningMode(change.getMode())) { final ComponentName openComponent = findComponentName(change); final int openTaskId = findTaskId(change); final WindowContainerToken openToken = findToken(change); if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) { continue; } targets.add(new OpenChangeInfo(openComponent, openTaskId, openToken)); if (change.hasFlags(FLAG_SHOW_WALLPAPER)) { openShowWallpaper = true; } break; } } if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) { if (targets.isEmpty()) { // This shouldn't happen, but if that happen, consume the initial transition anyway. Log.e(TAG, "Unable to merge following transition, cannot find the gesture " + "animated target from the open transition=" + mOpenTransitionInfo); mOpenTransitionInfo = null; return; } // find first non-prepare open target // Find first non-prepare open target boolean isOpen = false; tmpSize = info.getChanges().size(); for (int j = 0; j < tmpSize; ++j) { final TransitionInfo.Change change = info.getChanges().get(j); final ComponentName firstNonOpen = findComponentName(change); final int firstTaskId = findTaskId(change); if ((firstNonOpen != null && firstNonOpen != openComponent) || (firstTaskId != INVALID_TASK_ID && firstTaskId != openTaskId)) { // this is original close target, potential be close, but cannot determine from // it if (isOpenChangeMatched(targets, change)) { // This is original close target, potential be close, but cannot determine // from it. if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { isOpen = !TransitionUtil.isClosingMode(change.getMode()); } else { Loading @@ -1321,33 +1322,44 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } if (!isOpen) { // Close transition, the transition info should be: // init info(open A & wallpaper) // current info(close B target) // remove init info(open/change A target & wallpaper) boolean moveToTop = false; boolean excludeOpenTarget = false; boolean mergePredictive = false; for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { if (isOpenChangeMatched(targets, change)) { if (TransitionUtil.isClosingMode(change.getMode())) { excludeOpenTarget = true; } moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP); info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER)) || !change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { info.getChanges().remove(j); } else if (!mergePredictive && TransitionUtil.isClosingMode(change.getMode())) { mergePredictive = true; } } // Ignore merge if there is no close target if (!info.getChanges().isEmpty()) { if (!info.getChanges().isEmpty() && mergePredictive) { tmpSize = init.getChanges().size(); for (int i = 0; i < tmpSize; ++i) { final TransitionInfo.Change change = init.getChanges().get(i); if (change.hasFlags(FLAG_IS_WALLPAPER)) { continue; } if (isOpenChangeMatched(targets, change)) { if (excludeOpenTarget) { // App has triggered another change during predictive back // transition, filter out predictive back target. continue; } if (moveToTop) { if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); } } Loading Loading @@ -1376,7 +1388,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont if (nonBackClose && nonBackOpen) { for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { if (isOpenChangeMatched(targets, change)) { info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) { info.getChanges().remove(j); Loading Loading @@ -1659,9 +1671,21 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont final ComponentName openChange = findComponentName(change); final int firstTaskId = findTaskId(change); final WindowContainerToken openToken = findToken(change); return (openChange != null && openChange == topActivity) return (openChange != null && openChange.equals(topActivity)) || (firstTaskId != INVALID_TASK_ID && firstTaskId == taskId) || (openToken != null && token == openToken); || (openToken != null && openToken.equals(token)); } static boolean isOpenChangeMatched(@NonNull ArrayList<OpenChangeInfo> targets, TransitionInfo.Change change) { for (int i = targets.size() - 1; i >= 0; --i) { final OpenChangeInfo next = targets.get(i); if (isSameChangeTarget(next.mOpenComponent, next.mOpenTaskId, next.mOpenToken, change)) { return true; } } return false; } private static boolean canBeTransitionTarget(TransitionInfo.Change change) { Loading Loading @@ -1721,4 +1745,16 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } static class OpenChangeInfo { final ComponentName mOpenComponent; final int mOpenTaskId; final WindowContainerToken mOpenToken; OpenChangeInfo(ComponentName openComponent, int openTaskId, WindowContainerToken openToken) { mOpenComponent = openComponent; mOpenTaskId = openTaskId; mOpenToken = openToken; } } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.content.pm.ApplicationInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.input.InputManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -812,7 +813,10 @@ public class BackAnimationControllerTest extends ShellTestCase { if (taskId != INVALID_TASK_ID) { final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); final IWindowContainerToken mockT = mock(IWindowContainerToken.class); Binder binder = new Binder(); doReturn(binder).when(mockT).asBinder(); taskInfo.token = new WindowContainerToken(mockT); change = new TransitionInfo.Change( taskInfo.token, b.build()); change.setTaskInfo(taskInfo); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +61 −25 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; Loading Loading @@ -1277,42 +1278,42 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } // Copy initial changes to final transition final TransitionInfo init = mOpenTransitionInfo; // find prepare open target // Find prepare open target boolean openShowWallpaper = false; ComponentName openComponent = null; final ArrayList<OpenChangeInfo> targets = new ArrayList<>(); int tmpSize; int openTaskId = INVALID_TASK_ID; WindowContainerToken openToken = null; for (int j = init.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = init.getChanges().get(j); if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { openComponent = findComponentName(change); openTaskId = findTaskId(change); openToken = findToken(change); if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED) && TransitionUtil.isOpeningMode(change.getMode())) { final ComponentName openComponent = findComponentName(change); final int openTaskId = findTaskId(change); final WindowContainerToken openToken = findToken(change); if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) { continue; } targets.add(new OpenChangeInfo(openComponent, openTaskId, openToken)); if (change.hasFlags(FLAG_SHOW_WALLPAPER)) { openShowWallpaper = true; } break; } } if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) { if (targets.isEmpty()) { // This shouldn't happen, but if that happen, consume the initial transition anyway. Log.e(TAG, "Unable to merge following transition, cannot find the gesture " + "animated target from the open transition=" + mOpenTransitionInfo); mOpenTransitionInfo = null; return; } // find first non-prepare open target // Find first non-prepare open target boolean isOpen = false; tmpSize = info.getChanges().size(); for (int j = 0; j < tmpSize; ++j) { final TransitionInfo.Change change = info.getChanges().get(j); final ComponentName firstNonOpen = findComponentName(change); final int firstTaskId = findTaskId(change); if ((firstNonOpen != null && firstNonOpen != openComponent) || (firstTaskId != INVALID_TASK_ID && firstTaskId != openTaskId)) { // this is original close target, potential be close, but cannot determine from // it if (isOpenChangeMatched(targets, change)) { // This is original close target, potential be close, but cannot determine // from it. if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { isOpen = !TransitionUtil.isClosingMode(change.getMode()); } else { Loading @@ -1321,33 +1322,44 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } if (!isOpen) { // Close transition, the transition info should be: // init info(open A & wallpaper) // current info(close B target) // remove init info(open/change A target & wallpaper) boolean moveToTop = false; boolean excludeOpenTarget = false; boolean mergePredictive = false; for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { if (isOpenChangeMatched(targets, change)) { if (TransitionUtil.isClosingMode(change.getMode())) { excludeOpenTarget = true; } moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP); info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER)) || !change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { info.getChanges().remove(j); } else if (!mergePredictive && TransitionUtil.isClosingMode(change.getMode())) { mergePredictive = true; } } // Ignore merge if there is no close target if (!info.getChanges().isEmpty()) { if (!info.getChanges().isEmpty() && mergePredictive) { tmpSize = init.getChanges().size(); for (int i = 0; i < tmpSize; ++i) { final TransitionInfo.Change change = init.getChanges().get(i); if (change.hasFlags(FLAG_IS_WALLPAPER)) { continue; } if (isOpenChangeMatched(targets, change)) { if (excludeOpenTarget) { // App has triggered another change during predictive back // transition, filter out predictive back target. continue; } if (moveToTop) { if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); } } Loading Loading @@ -1376,7 +1388,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont if (nonBackClose && nonBackOpen) { for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { if (isOpenChangeMatched(targets, change)) { info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) { info.getChanges().remove(j); Loading Loading @@ -1659,9 +1671,21 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont final ComponentName openChange = findComponentName(change); final int firstTaskId = findTaskId(change); final WindowContainerToken openToken = findToken(change); return (openChange != null && openChange == topActivity) return (openChange != null && openChange.equals(topActivity)) || (firstTaskId != INVALID_TASK_ID && firstTaskId == taskId) || (openToken != null && token == openToken); || (openToken != null && openToken.equals(token)); } static boolean isOpenChangeMatched(@NonNull ArrayList<OpenChangeInfo> targets, TransitionInfo.Change change) { for (int i = targets.size() - 1; i >= 0; --i) { final OpenChangeInfo next = targets.get(i); if (isSameChangeTarget(next.mOpenComponent, next.mOpenTaskId, next.mOpenToken, change)) { return true; } } return false; } private static boolean canBeTransitionTarget(TransitionInfo.Change change) { Loading Loading @@ -1721,4 +1745,16 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } static class OpenChangeInfo { final ComponentName mOpenComponent; final int mOpenTaskId; final WindowContainerToken mOpenToken; OpenChangeInfo(ComponentName openComponent, int openTaskId, WindowContainerToken openToken) { mOpenComponent = openComponent; mOpenTaskId = openTaskId; mOpenToken = openToken; } } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.content.pm.ApplicationInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.input.InputManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -812,7 +813,10 @@ public class BackAnimationControllerTest extends ShellTestCase { if (taskId != INVALID_TASK_ID) { final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); final IWindowContainerToken mockT = mock(IWindowContainerToken.class); Binder binder = new Binder(); doReturn(binder).when(mockT).asBinder(); taskInfo.token = new WindowContainerToken(mockT); change = new TransitionInfo.Change( taskInfo.token, b.build()); change.setTaskInfo(taskInfo); Loading