Loading core/java/android/window/IWindowOrganizerController.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -93,11 +93,17 @@ interface IWindowOrganizerController { ITaskFragmentOrganizerController getTaskFragmentOrganizerController(); /** * Registers a transition player with Core. There is only one of these at a time and calling * this will replace the existing one if set. * Registers a transition player with Core. There is only one of these active at a time so * calling this will replace the existing one (if set) until it is unregistered. */ void registerTransitionPlayer(in ITransitionPlayer player); /** * Un-registers a transition player from Core. This will restore whichever player was active * prior to registering this one. */ void unregisterTransitionPlayer(in ITransitionPlayer player); /** @return An interface enabling the transition players to report its metrics. */ ITransitionMetricsReporter getTransitionMetricsReporter(); Loading core/java/android/window/WindowOrganizer.java +14 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,7 @@ public class WindowOrganizer { * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void registerTransitionPlayer(@Nullable ITransitionPlayer player) { public void registerTransitionPlayer(@NonNull ITransitionPlayer player) { try { getWindowOrganizerController().registerTransitionPlayer(player); } catch (RemoteException e) { Loading @@ -163,6 +163,19 @@ public class WindowOrganizer { } } /** * Unregister a previously-registered ITransitionPlayer. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void unregisterTransitionPlayer(@NonNull ITransitionPlayer player) { try { getWindowOrganizerController().unregisterTransitionPlayer(player); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @see TransitionMetrics * @hide Loading data/etc/core.protolog.pb +284 B (53 KiB) File changed.No diff preview for this file type. View original file View changed file data/etc/services.core.protolog.json +30 −0 Original line number Diff line number Diff line Loading @@ -3223,6 +3223,36 @@ "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4546322749928357965": { "message": "Registering transition player %s over %d other players", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4250307779892136611": { "message": "Registering transition player %s ", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "3242771541905259983": { "message": "Attempt to unregister transition player %s but it isn't registered", "level": "WARN", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "3691912781236221027": { "message": "Unregistering active transition player %s at index=%d leaving %d in stack", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-2879980134100946679": { "message": "Unregistering transition player %s at index=%d leaving %d in stack", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4235778637051052061": { "message": "Disabling player for transition #%d because display isn't enabled yet", "level": "VERBOSE", Loading services/core/java/com/android/server/wm/TransitionController.java +97 −42 Original line number Diff line number Diff line Loading @@ -113,10 +113,9 @@ class TransitionController { private static final int LEGACY_STATE_READY = 1; private static final int LEGACY_STATE_RUNNING = 2; private ITransitionPlayer mTransitionPlayer; private final ArrayList<TransitionPlayerRecord> mTransitionPlayers = new ArrayList<>(); final TransitionMetricsReporter mTransitionMetricsReporter = new TransitionMetricsReporter(); private WindowProcessController mTransitionPlayerProc; final ActivityTaskManagerService mAtm; BLASTSyncEngine mSyncEngine; Loading Loading @@ -175,8 +174,6 @@ class TransitionController { final Lock mRunningLock = new Lock(); private final IBinder.DeathRecipient mTransitionPlayerDeath; static class QueuedTransition { final Transition mTransition; final OnStartCollect mOnStartCollect; Loading Loading @@ -243,11 +240,6 @@ class TransitionController { TransitionController(ActivityTaskManagerService atm) { mAtm = atm; mRemotePlayer = new RemotePlayer(atm); mTransitionPlayerDeath = () -> { synchronized (mAtm.mGlobalLock) { detachPlayer(); } }; } void setWindowManager(WindowManagerService wms) { Loading @@ -266,11 +258,10 @@ class TransitionController { mSyncEngine.addOnIdleListener(this::tryStartCollectFromQueue); } @VisibleForTesting void detachPlayer() { if (mTransitionPlayer == null) return; // Immediately set to null so that nothing inadvertently starts/queues. mTransitionPlayer = null; void flushRunningTransitions() { // Temporarily clear so that nothing gets started/queued while flushing final ArrayList<TransitionPlayerRecord> temp = new ArrayList<>(mTransitionPlayers); mTransitionPlayers.clear(); // Clean-up/finish any playing transitions. Backwards since they can remove themselves. for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) { mPlayingTransitions.get(i).cleanUpOnFailure(); Loading @@ -285,9 +276,10 @@ class TransitionController { if (mCollectingTransition != null) { mCollectingTransition.abort(); } mTransitionPlayerProc = null; mRemotePlayer.clear(); mRunningLock.doNotifyLocked(); // Restore the rest of the player stack mTransitionPlayers.addAll(temp); } /** @see #createTransition(int, int) */ Loading @@ -302,7 +294,7 @@ class TransitionController { @NonNull Transition createTransition(@WindowManager.TransitionType int type, @WindowManager.TransitionFlags int flags) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { throw new IllegalStateException("Shell Transitions not enabled"); } if (mCollectingTransition != null) { Loading @@ -321,7 +313,7 @@ class TransitionController { if (mCollectingTransition != null) { throw new IllegalStateException("Simultaneous transition collection not supported."); } if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { // If sysui has been killed (by a test) or crashed, we can temporarily have no player // In this case, abort the transition. transition.abort(); Loading @@ -339,30 +331,56 @@ class TransitionController { void registerTransitionPlayer(@Nullable ITransitionPlayer player, @Nullable WindowProcessController playerProc) { try { // Note: asBinder() can be null if player is same process (likely in a test). if (mTransitionPlayer != null) { if (mTransitionPlayer.asBinder() != null) { mTransitionPlayer.asBinder().unlinkToDeath(mTransitionPlayerDeath, 0); if (!mTransitionPlayers.isEmpty()) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition " + "player %s over %d other players", player.asBinder(), mTransitionPlayers.size()); // flush currently running transitions so that the new player doesn't get // intermediate state flushRunningTransitions(); } else { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition " + "player %s ", player.asBinder()); } detachPlayer(); mTransitionPlayers.add(new TransitionPlayerRecord(player, playerProc)); } if (player.asBinder() != null) { player.asBinder().linkToDeath(mTransitionPlayerDeath, 0); @VisibleForTesting void unregisterTransitionPlayer(@NonNull ITransitionPlayer player) { int idx = mTransitionPlayers.size() - 1; for (; idx >= 0; --idx) { if (mTransitionPlayers.get(idx).mPlayer.asBinder() == player.asBinder()) break; } if (idx < 0) { ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Attempt to unregister " + "transition player %s but it isn't registered", player.asBinder()); return; } mTransitionPlayer = player; mTransitionPlayerProc = playerProc; } catch (RemoteException e) { throw new RuntimeException("Unable to set transition player"); final boolean needsFlush = idx == (mTransitionPlayers.size() - 1); final TransitionPlayerRecord record = mTransitionPlayers.remove(idx); if (needsFlush) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Unregistering active " + "transition player %s at index=%d leaving %d in stack", player.asBinder(), idx, mTransitionPlayers.size()); } else { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Unregistering transition " + "player %s at index=%d leaving %d in stack", player.asBinder(), idx, mTransitionPlayers.size()); } record.unlinkToDeath(); if (!needsFlush) { // Not the active player, so no need to flush transitions. return; } flushRunningTransitions(); } @Nullable ITransitionPlayer getTransitionPlayer() { return mTransitionPlayer; return mTransitionPlayers.isEmpty() ? null : mTransitionPlayers.getLast().mPlayer; } boolean isShellTransitionsEnabled() { return mTransitionPlayer != null; return !mTransitionPlayers.isEmpty(); } /** @return {@code true} if using shell-transitions rotation instead of fixed-rotation. */ Loading Loading @@ -677,7 +695,7 @@ class TransitionController { Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger, @NonNull WindowContainer readyGroupRef) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { return null; } Transition newTransition = null; Loading Loading @@ -728,7 +746,7 @@ class TransitionController { transition.getToken(), null)); return transition; } if (mTransitionPlayer == null || transition.isAborted()) { if (mTransitionPlayers.isEmpty() || transition.isAborted()) { // Apparently, some tests will kill(and restart) systemui, so there is a chance that // the player might be transiently null. if (transition.isCollecting()) { Loading Loading @@ -757,7 +775,8 @@ class TransitionController { transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos(); transition.mLogger.mRequest = request; mTransitionPlayer.requestStartTransition(transition.getToken(), request); mTransitionPlayers.getLast().mPlayer.requestStartTransition( transition.getToken(), request); if (remoteTransition != null) { transition.setRemoteAnimationApp(remoteTransition.getAppThread()); } Loading @@ -773,7 +792,7 @@ class TransitionController { * @return the new transition if it was created for this request, `null` otherwise. */ Transition requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) { if (mTransitionPlayer == null || isCollecting()) return null; if (mTransitionPlayers.isEmpty() || isCollecting()) return null; if (!wc.isVisibleRequested()) return null; return requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */), wc.asTask(), null /* remoteTransition */, null /* displayChange */); Loading Loading @@ -1250,11 +1269,13 @@ class TransitionController { /** Updates the process state of animation player. */ private void updateRunningRemoteAnimation(Transition transition, boolean isPlaying) { if (mTransitionPlayerProc == null) return; if (mTransitionPlayers.isEmpty()) return; final TransitionPlayerRecord record = mTransitionPlayers.getLast(); if (record.mPlayerProc == null) return; if (isPlaying) { mTransitionPlayerProc.setRunningRemoteAnimation(true); record.mPlayerProc.setRunningRemoteAnimation(true); } else if (mPlayingTransitions.isEmpty()) { mTransitionPlayerProc.setRunningRemoteAnimation(false); record.mPlayerProc.setRunningRemoteAnimation(false); mRemotePlayer.clear(); } } Loading Loading @@ -1416,7 +1437,7 @@ class TransitionController { */ @NonNull Transition createAndStartCollecting(int type) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { return null; } if (!mQueuedTransitions.isEmpty()) { Loading Loading @@ -1477,6 +1498,40 @@ class TransitionController { void onCollectStarted(boolean deferred); } private class TransitionPlayerRecord { final ITransitionPlayer mPlayer; IBinder.DeathRecipient mDeath = null; private WindowProcessController mPlayerProc; TransitionPlayerRecord(@NonNull ITransitionPlayer player, @Nullable WindowProcessController playerProc) { mPlayer = player; mPlayerProc = playerProc; try { linkToDeath(); } catch (RemoteException e) { throw new RuntimeException("Unable to set transition player"); } } private void linkToDeath() throws RemoteException { // Note: asBinder() can be null if player is same process (likely in a test). if (mPlayer.asBinder() == null) return; mDeath = () -> { synchronized (mAtm.mGlobalLock) { unregisterTransitionPlayer(mPlayer); } }; mPlayer.asBinder().linkToDeath(mDeath, 0); } void unlinkToDeath() { if (mPlayer.asBinder() == null || mDeath == null) return; mPlayer.asBinder().unlinkToDeath(mDeath, 0); mDeath = null; } } /** * This manages the animating state of processes that are running remote animations for * {@link #mTransitionPlayerProc}. Loading Loading
core/java/android/window/IWindowOrganizerController.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -93,11 +93,17 @@ interface IWindowOrganizerController { ITaskFragmentOrganizerController getTaskFragmentOrganizerController(); /** * Registers a transition player with Core. There is only one of these at a time and calling * this will replace the existing one if set. * Registers a transition player with Core. There is only one of these active at a time so * calling this will replace the existing one (if set) until it is unregistered. */ void registerTransitionPlayer(in ITransitionPlayer player); /** * Un-registers a transition player from Core. This will restore whichever player was active * prior to registering this one. */ void unregisterTransitionPlayer(in ITransitionPlayer player); /** @return An interface enabling the transition players to report its metrics. */ ITransitionMetricsReporter getTransitionMetricsReporter(); Loading
core/java/android/window/WindowOrganizer.java +14 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,7 @@ public class WindowOrganizer { * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void registerTransitionPlayer(@Nullable ITransitionPlayer player) { public void registerTransitionPlayer(@NonNull ITransitionPlayer player) { try { getWindowOrganizerController().registerTransitionPlayer(player); } catch (RemoteException e) { Loading @@ -163,6 +163,19 @@ public class WindowOrganizer { } } /** * Unregister a previously-registered ITransitionPlayer. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void unregisterTransitionPlayer(@NonNull ITransitionPlayer player) { try { getWindowOrganizerController().unregisterTransitionPlayer(player); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @see TransitionMetrics * @hide Loading
data/etc/core.protolog.pb +284 B (53 KiB) File changed.No diff preview for this file type. View original file View changed file
data/etc/services.core.protolog.json +30 −0 Original line number Diff line number Diff line Loading @@ -3223,6 +3223,36 @@ "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4546322749928357965": { "message": "Registering transition player %s over %d other players", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4250307779892136611": { "message": "Registering transition player %s ", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "3242771541905259983": { "message": "Attempt to unregister transition player %s but it isn't registered", "level": "WARN", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "3691912781236221027": { "message": "Unregistering active transition player %s at index=%d leaving %d in stack", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-2879980134100946679": { "message": "Unregistering transition player %s at index=%d leaving %d in stack", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", "at": "com\/android\/server\/wm\/TransitionController.java" }, "-4235778637051052061": { "message": "Disabling player for transition #%d because display isn't enabled yet", "level": "VERBOSE", Loading
services/core/java/com/android/server/wm/TransitionController.java +97 −42 Original line number Diff line number Diff line Loading @@ -113,10 +113,9 @@ class TransitionController { private static final int LEGACY_STATE_READY = 1; private static final int LEGACY_STATE_RUNNING = 2; private ITransitionPlayer mTransitionPlayer; private final ArrayList<TransitionPlayerRecord> mTransitionPlayers = new ArrayList<>(); final TransitionMetricsReporter mTransitionMetricsReporter = new TransitionMetricsReporter(); private WindowProcessController mTransitionPlayerProc; final ActivityTaskManagerService mAtm; BLASTSyncEngine mSyncEngine; Loading Loading @@ -175,8 +174,6 @@ class TransitionController { final Lock mRunningLock = new Lock(); private final IBinder.DeathRecipient mTransitionPlayerDeath; static class QueuedTransition { final Transition mTransition; final OnStartCollect mOnStartCollect; Loading Loading @@ -243,11 +240,6 @@ class TransitionController { TransitionController(ActivityTaskManagerService atm) { mAtm = atm; mRemotePlayer = new RemotePlayer(atm); mTransitionPlayerDeath = () -> { synchronized (mAtm.mGlobalLock) { detachPlayer(); } }; } void setWindowManager(WindowManagerService wms) { Loading @@ -266,11 +258,10 @@ class TransitionController { mSyncEngine.addOnIdleListener(this::tryStartCollectFromQueue); } @VisibleForTesting void detachPlayer() { if (mTransitionPlayer == null) return; // Immediately set to null so that nothing inadvertently starts/queues. mTransitionPlayer = null; void flushRunningTransitions() { // Temporarily clear so that nothing gets started/queued while flushing final ArrayList<TransitionPlayerRecord> temp = new ArrayList<>(mTransitionPlayers); mTransitionPlayers.clear(); // Clean-up/finish any playing transitions. Backwards since they can remove themselves. for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) { mPlayingTransitions.get(i).cleanUpOnFailure(); Loading @@ -285,9 +276,10 @@ class TransitionController { if (mCollectingTransition != null) { mCollectingTransition.abort(); } mTransitionPlayerProc = null; mRemotePlayer.clear(); mRunningLock.doNotifyLocked(); // Restore the rest of the player stack mTransitionPlayers.addAll(temp); } /** @see #createTransition(int, int) */ Loading @@ -302,7 +294,7 @@ class TransitionController { @NonNull Transition createTransition(@WindowManager.TransitionType int type, @WindowManager.TransitionFlags int flags) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { throw new IllegalStateException("Shell Transitions not enabled"); } if (mCollectingTransition != null) { Loading @@ -321,7 +313,7 @@ class TransitionController { if (mCollectingTransition != null) { throw new IllegalStateException("Simultaneous transition collection not supported."); } if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { // If sysui has been killed (by a test) or crashed, we can temporarily have no player // In this case, abort the transition. transition.abort(); Loading @@ -339,30 +331,56 @@ class TransitionController { void registerTransitionPlayer(@Nullable ITransitionPlayer player, @Nullable WindowProcessController playerProc) { try { // Note: asBinder() can be null if player is same process (likely in a test). if (mTransitionPlayer != null) { if (mTransitionPlayer.asBinder() != null) { mTransitionPlayer.asBinder().unlinkToDeath(mTransitionPlayerDeath, 0); if (!mTransitionPlayers.isEmpty()) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition " + "player %s over %d other players", player.asBinder(), mTransitionPlayers.size()); // flush currently running transitions so that the new player doesn't get // intermediate state flushRunningTransitions(); } else { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition " + "player %s ", player.asBinder()); } detachPlayer(); mTransitionPlayers.add(new TransitionPlayerRecord(player, playerProc)); } if (player.asBinder() != null) { player.asBinder().linkToDeath(mTransitionPlayerDeath, 0); @VisibleForTesting void unregisterTransitionPlayer(@NonNull ITransitionPlayer player) { int idx = mTransitionPlayers.size() - 1; for (; idx >= 0; --idx) { if (mTransitionPlayers.get(idx).mPlayer.asBinder() == player.asBinder()) break; } if (idx < 0) { ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Attempt to unregister " + "transition player %s but it isn't registered", player.asBinder()); return; } mTransitionPlayer = player; mTransitionPlayerProc = playerProc; } catch (RemoteException e) { throw new RuntimeException("Unable to set transition player"); final boolean needsFlush = idx == (mTransitionPlayers.size() - 1); final TransitionPlayerRecord record = mTransitionPlayers.remove(idx); if (needsFlush) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Unregistering active " + "transition player %s at index=%d leaving %d in stack", player.asBinder(), idx, mTransitionPlayers.size()); } else { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Unregistering transition " + "player %s at index=%d leaving %d in stack", player.asBinder(), idx, mTransitionPlayers.size()); } record.unlinkToDeath(); if (!needsFlush) { // Not the active player, so no need to flush transitions. return; } flushRunningTransitions(); } @Nullable ITransitionPlayer getTransitionPlayer() { return mTransitionPlayer; return mTransitionPlayers.isEmpty() ? null : mTransitionPlayers.getLast().mPlayer; } boolean isShellTransitionsEnabled() { return mTransitionPlayer != null; return !mTransitionPlayers.isEmpty(); } /** @return {@code true} if using shell-transitions rotation instead of fixed-rotation. */ Loading Loading @@ -677,7 +695,7 @@ class TransitionController { Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger, @NonNull WindowContainer readyGroupRef) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { return null; } Transition newTransition = null; Loading Loading @@ -728,7 +746,7 @@ class TransitionController { transition.getToken(), null)); return transition; } if (mTransitionPlayer == null || transition.isAborted()) { if (mTransitionPlayers.isEmpty() || transition.isAborted()) { // Apparently, some tests will kill(and restart) systemui, so there is a chance that // the player might be transiently null. if (transition.isCollecting()) { Loading Loading @@ -757,7 +775,8 @@ class TransitionController { transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos(); transition.mLogger.mRequest = request; mTransitionPlayer.requestStartTransition(transition.getToken(), request); mTransitionPlayers.getLast().mPlayer.requestStartTransition( transition.getToken(), request); if (remoteTransition != null) { transition.setRemoteAnimationApp(remoteTransition.getAppThread()); } Loading @@ -773,7 +792,7 @@ class TransitionController { * @return the new transition if it was created for this request, `null` otherwise. */ Transition requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) { if (mTransitionPlayer == null || isCollecting()) return null; if (mTransitionPlayers.isEmpty() || isCollecting()) return null; if (!wc.isVisibleRequested()) return null; return requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */), wc.asTask(), null /* remoteTransition */, null /* displayChange */); Loading Loading @@ -1250,11 +1269,13 @@ class TransitionController { /** Updates the process state of animation player. */ private void updateRunningRemoteAnimation(Transition transition, boolean isPlaying) { if (mTransitionPlayerProc == null) return; if (mTransitionPlayers.isEmpty()) return; final TransitionPlayerRecord record = mTransitionPlayers.getLast(); if (record.mPlayerProc == null) return; if (isPlaying) { mTransitionPlayerProc.setRunningRemoteAnimation(true); record.mPlayerProc.setRunningRemoteAnimation(true); } else if (mPlayingTransitions.isEmpty()) { mTransitionPlayerProc.setRunningRemoteAnimation(false); record.mPlayerProc.setRunningRemoteAnimation(false); mRemotePlayer.clear(); } } Loading Loading @@ -1416,7 +1437,7 @@ class TransitionController { */ @NonNull Transition createAndStartCollecting(int type) { if (mTransitionPlayer == null) { if (mTransitionPlayers.isEmpty()) { return null; } if (!mQueuedTransitions.isEmpty()) { Loading Loading @@ -1477,6 +1498,40 @@ class TransitionController { void onCollectStarted(boolean deferred); } private class TransitionPlayerRecord { final ITransitionPlayer mPlayer; IBinder.DeathRecipient mDeath = null; private WindowProcessController mPlayerProc; TransitionPlayerRecord(@NonNull ITransitionPlayer player, @Nullable WindowProcessController playerProc) { mPlayer = player; mPlayerProc = playerProc; try { linkToDeath(); } catch (RemoteException e) { throw new RuntimeException("Unable to set transition player"); } } private void linkToDeath() throws RemoteException { // Note: asBinder() can be null if player is same process (likely in a test). if (mPlayer.asBinder() == null) return; mDeath = () -> { synchronized (mAtm.mGlobalLock) { unregisterTransitionPlayer(mPlayer); } }; mPlayer.asBinder().linkToDeath(mDeath, 0); } void unlinkToDeath() { if (mPlayer.asBinder() == null || mDeath == null) return; mPlayer.asBinder().unlinkToDeath(mDeath, 0); mDeath = null; } } /** * This manages the animating state of processes that are running remote animations for * {@link #mTransitionPlayerProc}. Loading