Loading core/java/android/window/TransitionInfo.java +68 −0 Original line number Original line Diff line number Diff line Loading @@ -414,6 +414,53 @@ public final class TransitionInfo implements Parcelable { return false; return false; } } /** * Releases temporary-for-animation surfaces referenced by this to potentially free up memory. * This includes root-leash and snapshots. */ public void releaseAnimSurfaces() { for (int i = mChanges.size() - 1; i >= 0; --i) { final Change c = mChanges.get(i); if (c.mSnapshot != null) { c.mSnapshot.release(); c.mSnapshot = null; } } if (mRootLeash != null) { mRootLeash.release(); } } /** * Releases ALL the surfaces referenced by this to potentially free up memory. Do NOT use this * if the surface-controls get stored and used elsewhere in the process. To just release * temporary-for-animation surfaces, use {@link #releaseAnimSurfaces}. */ public void releaseAllSurfaces() { releaseAnimSurfaces(); for (int i = mChanges.size() - 1; i >= 0; --i) { mChanges.get(i).getLeash().release(); } } /** * Makes a copy of this as if it were parcel'd and unparcel'd. This implies that surfacecontrol * refcounts are incremented which allows the "remote" receiver to release them without breaking * the caller's references. Use this only if you need to "send" this to a local function which * assumes it is being called from a remote caller. */ public TransitionInfo localRemoteCopy() { final TransitionInfo out = new TransitionInfo(mType, mFlags); for (int i = 0; i < mChanges.size(); ++i) { out.mChanges.add(mChanges.get(i).localRemoteCopy()); } out.mRootLeash = mRootLeash != null ? new SurfaceControl(mRootLeash, "localRemote") : null; // Doesn't have any native stuff, so no need for actual copy out.mOptions = mOptions; out.mRootOffset.set(mRootOffset); return out; } /** Represents the change a WindowContainer undergoes during a transition */ /** Represents the change a WindowContainer undergoes during a transition */ public static final class Change implements Parcelable { public static final class Change implements Parcelable { private final WindowContainerToken mContainer; private final WindowContainerToken mContainer; Loading Loading @@ -466,6 +513,27 @@ public final class TransitionInfo implements Parcelable { mSnapshotLuma = in.readFloat(); mSnapshotLuma = in.readFloat(); } } private Change localRemoteCopy() { final Change out = new Change(mContainer, new SurfaceControl(mLeash, "localRemote")); out.mParent = mParent; out.mLastParent = mLastParent; out.mMode = mMode; out.mFlags = mFlags; out.mStartAbsBounds.set(mStartAbsBounds); out.mEndAbsBounds.set(mEndAbsBounds); out.mEndRelOffset.set(mEndRelOffset); out.mTaskInfo = mTaskInfo; out.mAllowEnterPip = mAllowEnterPip; out.mStartRotation = mStartRotation; out.mEndRotation = mEndRotation; out.mEndFixedRotation = mEndFixedRotation; out.mRotationAnimation = mRotationAnimation; out.mBackgroundColor = mBackgroundColor; out.mSnapshot = mSnapshot != null ? new SurfaceControl(mSnapshot, "localRemote") : null; out.mSnapshotLuma = mSnapshotLuma; return out; } /** Sets the parent of this change's container. The parent must be a participant or null. */ /** Sets the parent of this change's container. The parent must be a participant or null. */ public void setParent(@Nullable WindowContainerToken parent) { public void setParent(@Nullable WindowContainerToken parent) { mParent = parent; mParent = parent; Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java +17 −5 Original line number Original line Diff line number Diff line Loading @@ -77,10 +77,10 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { if (mRemote.asBinder() != null) { if (mRemote.asBinder() != null) { mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */); mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */); } } mMainExecutor.execute(() -> { if (sct != null) { if (sct != null) { finishTransaction.merge(sct); finishTransaction.merge(sct); } } mMainExecutor.execute(() -> { finishCallback.onTransitionFinished(wct, null /* wctCB */); finishCallback.onTransitionFinished(wct, null /* wctCB */); }); }); } } Loading @@ -90,7 +90,13 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { if (mRemote.asBinder() != null) { if (mRemote.asBinder() != null) { mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */); mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */); } } mRemote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteStartT = RemoteTransitionHandler.copyIfLocal( startTransaction, mRemote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteStartT == startTransaction ? info : info.localRemoteCopy(); mRemote.getRemoteTransition().startAnimation(transition, remoteInfo, remoteStartT, cb); // assume that remote will apply the start transaction. // assume that remote will apply the start transaction. startTransaction.clear(); startTransaction.clear(); } catch (RemoteException e) { } catch (RemoteException e) { Loading Loading @@ -124,7 +130,13 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { } } }; }; try { try { mRemote.getRemoteTransition().mergeAnimation(transition, info, t, mergeTarget, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteT = RemoteTransitionHandler.copyIfLocal(t, mRemote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteT == t ? info : info.localRemoteCopy(); mRemote.getRemoteTransition().mergeAnimation( transition, remoteInfo, remoteT, mergeTarget, cb); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(Transitions.TAG, "Error merging remote transition.", e); Log.e(Transitions.TAG, "Error merging remote transition.", e); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +38 −5 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.os.IBinder; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.os.RemoteException; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.Log; import android.util.Log; Loading Loading @@ -120,10 +121,10 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { public void onTransitionFinished(WindowContainerTransaction wct, public void onTransitionFinished(WindowContainerTransaction wct, SurfaceControl.Transaction sct) { SurfaceControl.Transaction sct) { unhandleDeath(remote.asBinder(), finishCallback); unhandleDeath(remote.asBinder(), finishCallback); mMainExecutor.execute(() -> { if (sct != null) { if (sct != null) { finishTransaction.merge(sct); finishTransaction.merge(sct); } } mMainExecutor.execute(() -> { mRequestedRemotes.remove(transition); mRequestedRemotes.remove(transition); finishCallback.onTransitionFinished(wct, null /* wctCB */); finishCallback.onTransitionFinished(wct, null /* wctCB */); }); }); Loading @@ -131,8 +132,14 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { }; }; Transitions.setRunningRemoteTransitionDelegate(remote.getAppThread()); Transitions.setRunningRemoteTransitionDelegate(remote.getAppThread()); try { try { // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteStartT = copyIfLocal(startTransaction, remote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteStartT == startTransaction ? info : info.localRemoteCopy(); handleDeath(remote.asBinder(), finishCallback); handleDeath(remote.asBinder(), finishCallback); remote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); remote.getRemoteTransition().startAnimation(transition, remoteInfo, remoteStartT, cb); // assume that remote will apply the start transaction. // assume that remote will apply the start transaction. startTransaction.clear(); startTransaction.clear(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -145,6 +152,28 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { return true; return true; } } static SurfaceControl.Transaction copyIfLocal(SurfaceControl.Transaction t, IRemoteTransition remote) { // We care more about parceling than local (though they should be the same); so, use // queryLocalInterface since that's what Binder uses to decide if it needs to parcel. if (remote.asBinder().queryLocalInterface(IRemoteTransition.DESCRIPTOR) == null) { // No local interface, so binder itself will parcel and thus we don't need to. return t; } // Binder won't be parceling; however, the remotes assume they have their own native // objects (and don't know if caller is local or not), so we need to make a COPY here so // that the remote can clean it up without clearing the original transaction. // Since there's no direct `copy` for Transaction, we have to parcel/unparcel instead. final Parcel p = Parcel.obtain(); try { t.writeToParcel(p, 0); p.setDataPosition(0); return SurfaceControl.Transaction.CREATOR.createFromParcel(p); } finally { p.recycle(); } } @Override @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, Loading Loading @@ -175,7 +204,11 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { } } }; }; try { try { remote.mergeAnimation(transition, info, t, mergeTarget, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteT = copyIfLocal(t, remote); final TransitionInfo remoteInfo = remoteT == t ? info : info.localRemoteCopy(); remote.mergeAnimation(transition, remoteInfo, remoteT, mergeTarget, cb); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(Transitions.TAG, "Error attempting to merge remote transition.", e); Log.e(Transitions.TAG, "Error attempting to merge remote transition.", e); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +19 −1 Original line number Original line Diff line number Diff line Loading @@ -500,6 +500,7 @@ public class Transitions implements RemoteCallable<Transitions> { // Treat this as an abort since we are bypassing any merge logic and effectively // Treat this as an abort since we are bypassing any merge logic and effectively // finishing immediately. // finishing immediately. onAbort(transitionToken); onAbort(transitionToken); releaseSurfaces(info); return; return; } } Loading Loading @@ -604,6 +605,15 @@ public class Transitions implements RemoteCallable<Transitions> { onFinish(transition, wct, wctCB, false /* abort */); onFinish(transition, wct, wctCB, false /* abort */); } } /** * Releases an info's animation-surfaces. These don't need to persist and we need to release * them asap so that SF can free memory sooner. */ private void releaseSurfaces(@Nullable TransitionInfo info) { if (info == null) return; info.releaseAnimSurfaces(); } private void onFinish(IBinder transition, private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB, @Nullable WindowContainerTransactionCallback wctCB, Loading Loading @@ -642,6 +652,11 @@ public class Transitions implements RemoteCallable<Transitions> { } } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished (abort=%b), notifying core %s", abort, transition); "Transition animation finished (abort=%b), notifying core %s", abort, transition); if (active.mStartT != null) { // Applied by now, so close immediately. Do not set to null yet, though, since nullness // is used later to disambiguate malformed transitions. active.mStartT.close(); } // Merge all relevant transactions together // Merge all relevant transactions together SurfaceControl.Transaction fullFinish = active.mFinishT; SurfaceControl.Transaction fullFinish = active.mFinishT; for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { Loading @@ -661,12 +676,14 @@ public class Transitions implements RemoteCallable<Transitions> { fullFinish.apply(); fullFinish.apply(); } } // Now perform all the finishes. // Now perform all the finishes. releaseSurfaces(active.mInfo); mActiveTransitions.remove(activeIdx); mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, wct, wctCB); mOrganizer.finishTransition(transition, wct, wctCB); while (activeIdx < mActiveTransitions.size()) { while (activeIdx < mActiveTransitions.size()) { if (!mActiveTransitions.get(activeIdx).mMerged) break; if (!mActiveTransitions.get(activeIdx).mMerged) break; ActiveTransition merged = mActiveTransitions.remove(activeIdx); ActiveTransition merged = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); releaseSurfaces(merged.mInfo); } } // sift through aborted transitions // sift through aborted transitions while (mActiveTransitions.size() > activeIdx while (mActiveTransitions.size() > activeIdx Loading @@ -679,8 +696,9 @@ public class Transitions implements RemoteCallable<Transitions> { } } mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); for (int i = 0; i < mObservers.size(); ++i) { for (int i = 0; i < mObservers.size(); ++i) { mObservers.get(i).onTransitionFinished(active.mToken, true); mObservers.get(i).onTransitionFinished(aborted.mToken, true); } } releaseSurfaces(aborted.mInfo); } } if (mActiveTransitions.size() <= activeIdx) { if (mActiveTransitions.size() <= activeIdx) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " Loading packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt +5 −3 Original line number Original line Diff line number Diff line Loading @@ -320,9 +320,7 @@ class RemoteTransitionAdapter { counterWallpaper.cleanUp(finishTransaction) counterWallpaper.cleanUp(finishTransaction) // Release surface references now. This is apparently to free GPU // Release surface references now. This is apparently to free GPU // memory while doing quick operations (eg. during CTS). // memory while doing quick operations (eg. during CTS). for (i in info.changes.indices.reversed()) { info.releaseAllSurfaces() info.changes[i].leash.release() } for (i in leashMap.size - 1 downTo 0) { for (i in leashMap.size - 1 downTo 0) { leashMap.valueAt(i).release() leashMap.valueAt(i).release() } } Loading @@ -331,6 +329,7 @@ class RemoteTransitionAdapter { null /* wct */, null /* wct */, finishTransaction finishTransaction ) ) finishTransaction.close() } catch (e: RemoteException) { } catch (e: RemoteException) { Log.e( Log.e( "ActivityOptionsCompat", "ActivityOptionsCompat", Loading Loading @@ -364,6 +363,9 @@ class RemoteTransitionAdapter { ) { ) { // TODO: hook up merge to recents onTaskAppeared if applicable. Until then, // TODO: hook up merge to recents onTaskAppeared if applicable. Until then, // ignore any incoming merges. // ignore any incoming merges. // Clean up stuff though cuz GC takes too long for benchmark tests. t.close() info.releaseAllSurfaces() } } } } } } Loading Loading
core/java/android/window/TransitionInfo.java +68 −0 Original line number Original line Diff line number Diff line Loading @@ -414,6 +414,53 @@ public final class TransitionInfo implements Parcelable { return false; return false; } } /** * Releases temporary-for-animation surfaces referenced by this to potentially free up memory. * This includes root-leash and snapshots. */ public void releaseAnimSurfaces() { for (int i = mChanges.size() - 1; i >= 0; --i) { final Change c = mChanges.get(i); if (c.mSnapshot != null) { c.mSnapshot.release(); c.mSnapshot = null; } } if (mRootLeash != null) { mRootLeash.release(); } } /** * Releases ALL the surfaces referenced by this to potentially free up memory. Do NOT use this * if the surface-controls get stored and used elsewhere in the process. To just release * temporary-for-animation surfaces, use {@link #releaseAnimSurfaces}. */ public void releaseAllSurfaces() { releaseAnimSurfaces(); for (int i = mChanges.size() - 1; i >= 0; --i) { mChanges.get(i).getLeash().release(); } } /** * Makes a copy of this as if it were parcel'd and unparcel'd. This implies that surfacecontrol * refcounts are incremented which allows the "remote" receiver to release them without breaking * the caller's references. Use this only if you need to "send" this to a local function which * assumes it is being called from a remote caller. */ public TransitionInfo localRemoteCopy() { final TransitionInfo out = new TransitionInfo(mType, mFlags); for (int i = 0; i < mChanges.size(); ++i) { out.mChanges.add(mChanges.get(i).localRemoteCopy()); } out.mRootLeash = mRootLeash != null ? new SurfaceControl(mRootLeash, "localRemote") : null; // Doesn't have any native stuff, so no need for actual copy out.mOptions = mOptions; out.mRootOffset.set(mRootOffset); return out; } /** Represents the change a WindowContainer undergoes during a transition */ /** Represents the change a WindowContainer undergoes during a transition */ public static final class Change implements Parcelable { public static final class Change implements Parcelable { private final WindowContainerToken mContainer; private final WindowContainerToken mContainer; Loading Loading @@ -466,6 +513,27 @@ public final class TransitionInfo implements Parcelable { mSnapshotLuma = in.readFloat(); mSnapshotLuma = in.readFloat(); } } private Change localRemoteCopy() { final Change out = new Change(mContainer, new SurfaceControl(mLeash, "localRemote")); out.mParent = mParent; out.mLastParent = mLastParent; out.mMode = mMode; out.mFlags = mFlags; out.mStartAbsBounds.set(mStartAbsBounds); out.mEndAbsBounds.set(mEndAbsBounds); out.mEndRelOffset.set(mEndRelOffset); out.mTaskInfo = mTaskInfo; out.mAllowEnterPip = mAllowEnterPip; out.mStartRotation = mStartRotation; out.mEndRotation = mEndRotation; out.mEndFixedRotation = mEndFixedRotation; out.mRotationAnimation = mRotationAnimation; out.mBackgroundColor = mBackgroundColor; out.mSnapshot = mSnapshot != null ? new SurfaceControl(mSnapshot, "localRemote") : null; out.mSnapshotLuma = mSnapshotLuma; return out; } /** Sets the parent of this change's container. The parent must be a participant or null. */ /** Sets the parent of this change's container. The parent must be a participant or null. */ public void setParent(@Nullable WindowContainerToken parent) { public void setParent(@Nullable WindowContainerToken parent) { mParent = parent; mParent = parent; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java +17 −5 Original line number Original line Diff line number Diff line Loading @@ -77,10 +77,10 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { if (mRemote.asBinder() != null) { if (mRemote.asBinder() != null) { mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */); mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */); } } mMainExecutor.execute(() -> { if (sct != null) { if (sct != null) { finishTransaction.merge(sct); finishTransaction.merge(sct); } } mMainExecutor.execute(() -> { finishCallback.onTransitionFinished(wct, null /* wctCB */); finishCallback.onTransitionFinished(wct, null /* wctCB */); }); }); } } Loading @@ -90,7 +90,13 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { if (mRemote.asBinder() != null) { if (mRemote.asBinder() != null) { mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */); mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */); } } mRemote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteStartT = RemoteTransitionHandler.copyIfLocal( startTransaction, mRemote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteStartT == startTransaction ? info : info.localRemoteCopy(); mRemote.getRemoteTransition().startAnimation(transition, remoteInfo, remoteStartT, cb); // assume that remote will apply the start transaction. // assume that remote will apply the start transaction. startTransaction.clear(); startTransaction.clear(); } catch (RemoteException e) { } catch (RemoteException e) { Loading Loading @@ -124,7 +130,13 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { } } }; }; try { try { mRemote.getRemoteTransition().mergeAnimation(transition, info, t, mergeTarget, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteT = RemoteTransitionHandler.copyIfLocal(t, mRemote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteT == t ? info : info.localRemoteCopy(); mRemote.getRemoteTransition().mergeAnimation( transition, remoteInfo, remoteT, mergeTarget, cb); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(Transitions.TAG, "Error merging remote transition.", e); Log.e(Transitions.TAG, "Error merging remote transition.", e); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +38 −5 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.os.IBinder; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.os.RemoteException; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.Log; import android.util.Log; Loading Loading @@ -120,10 +121,10 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { public void onTransitionFinished(WindowContainerTransaction wct, public void onTransitionFinished(WindowContainerTransaction wct, SurfaceControl.Transaction sct) { SurfaceControl.Transaction sct) { unhandleDeath(remote.asBinder(), finishCallback); unhandleDeath(remote.asBinder(), finishCallback); mMainExecutor.execute(() -> { if (sct != null) { if (sct != null) { finishTransaction.merge(sct); finishTransaction.merge(sct); } } mMainExecutor.execute(() -> { mRequestedRemotes.remove(transition); mRequestedRemotes.remove(transition); finishCallback.onTransitionFinished(wct, null /* wctCB */); finishCallback.onTransitionFinished(wct, null /* wctCB */); }); }); Loading @@ -131,8 +132,14 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { }; }; Transitions.setRunningRemoteTransitionDelegate(remote.getAppThread()); Transitions.setRunningRemoteTransitionDelegate(remote.getAppThread()); try { try { // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteStartT = copyIfLocal(startTransaction, remote.getRemoteTransition()); final TransitionInfo remoteInfo = remoteStartT == startTransaction ? info : info.localRemoteCopy(); handleDeath(remote.asBinder(), finishCallback); handleDeath(remote.asBinder(), finishCallback); remote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); remote.getRemoteTransition().startAnimation(transition, remoteInfo, remoteStartT, cb); // assume that remote will apply the start transaction. // assume that remote will apply the start transaction. startTransaction.clear(); startTransaction.clear(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -145,6 +152,28 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { return true; return true; } } static SurfaceControl.Transaction copyIfLocal(SurfaceControl.Transaction t, IRemoteTransition remote) { // We care more about parceling than local (though they should be the same); so, use // queryLocalInterface since that's what Binder uses to decide if it needs to parcel. if (remote.asBinder().queryLocalInterface(IRemoteTransition.DESCRIPTOR) == null) { // No local interface, so binder itself will parcel and thus we don't need to. return t; } // Binder won't be parceling; however, the remotes assume they have their own native // objects (and don't know if caller is local or not), so we need to make a COPY here so // that the remote can clean it up without clearing the original transaction. // Since there's no direct `copy` for Transaction, we have to parcel/unparcel instead. final Parcel p = Parcel.obtain(); try { t.writeToParcel(p, 0); p.setDataPosition(0); return SurfaceControl.Transaction.CREATOR.createFromParcel(p); } finally { p.recycle(); } } @Override @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, Loading Loading @@ -175,7 +204,11 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { } } }; }; try { try { remote.mergeAnimation(transition, info, t, mergeTarget, cb); // If the remote is actually in the same process, then make a copy of parameters since // remote impls assume that they have to clean-up native references. final SurfaceControl.Transaction remoteT = copyIfLocal(t, remote); final TransitionInfo remoteInfo = remoteT == t ? info : info.localRemoteCopy(); remote.mergeAnimation(transition, remoteInfo, remoteT, mergeTarget, cb); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(Transitions.TAG, "Error attempting to merge remote transition.", e); Log.e(Transitions.TAG, "Error attempting to merge remote transition.", e); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +19 −1 Original line number Original line Diff line number Diff line Loading @@ -500,6 +500,7 @@ public class Transitions implements RemoteCallable<Transitions> { // Treat this as an abort since we are bypassing any merge logic and effectively // Treat this as an abort since we are bypassing any merge logic and effectively // finishing immediately. // finishing immediately. onAbort(transitionToken); onAbort(transitionToken); releaseSurfaces(info); return; return; } } Loading Loading @@ -604,6 +605,15 @@ public class Transitions implements RemoteCallable<Transitions> { onFinish(transition, wct, wctCB, false /* abort */); onFinish(transition, wct, wctCB, false /* abort */); } } /** * Releases an info's animation-surfaces. These don't need to persist and we need to release * them asap so that SF can free memory sooner. */ private void releaseSurfaces(@Nullable TransitionInfo info) { if (info == null) return; info.releaseAnimSurfaces(); } private void onFinish(IBinder transition, private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB, @Nullable WindowContainerTransactionCallback wctCB, Loading Loading @@ -642,6 +652,11 @@ public class Transitions implements RemoteCallable<Transitions> { } } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished (abort=%b), notifying core %s", abort, transition); "Transition animation finished (abort=%b), notifying core %s", abort, transition); if (active.mStartT != null) { // Applied by now, so close immediately. Do not set to null yet, though, since nullness // is used later to disambiguate malformed transitions. active.mStartT.close(); } // Merge all relevant transactions together // Merge all relevant transactions together SurfaceControl.Transaction fullFinish = active.mFinishT; SurfaceControl.Transaction fullFinish = active.mFinishT; for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { Loading @@ -661,12 +676,14 @@ public class Transitions implements RemoteCallable<Transitions> { fullFinish.apply(); fullFinish.apply(); } } // Now perform all the finishes. // Now perform all the finishes. releaseSurfaces(active.mInfo); mActiveTransitions.remove(activeIdx); mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, wct, wctCB); mOrganizer.finishTransition(transition, wct, wctCB); while (activeIdx < mActiveTransitions.size()) { while (activeIdx < mActiveTransitions.size()) { if (!mActiveTransitions.get(activeIdx).mMerged) break; if (!mActiveTransitions.get(activeIdx).mMerged) break; ActiveTransition merged = mActiveTransitions.remove(activeIdx); ActiveTransition merged = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); releaseSurfaces(merged.mInfo); } } // sift through aborted transitions // sift through aborted transitions while (mActiveTransitions.size() > activeIdx while (mActiveTransitions.size() > activeIdx Loading @@ -679,8 +696,9 @@ public class Transitions implements RemoteCallable<Transitions> { } } mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); for (int i = 0; i < mObservers.size(); ++i) { for (int i = 0; i < mObservers.size(); ++i) { mObservers.get(i).onTransitionFinished(active.mToken, true); mObservers.get(i).onTransitionFinished(aborted.mToken, true); } } releaseSurfaces(aborted.mInfo); } } if (mActiveTransitions.size() <= activeIdx) { if (mActiveTransitions.size() <= activeIdx) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " Loading
packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt +5 −3 Original line number Original line Diff line number Diff line Loading @@ -320,9 +320,7 @@ class RemoteTransitionAdapter { counterWallpaper.cleanUp(finishTransaction) counterWallpaper.cleanUp(finishTransaction) // Release surface references now. This is apparently to free GPU // Release surface references now. This is apparently to free GPU // memory while doing quick operations (eg. during CTS). // memory while doing quick operations (eg. during CTS). for (i in info.changes.indices.reversed()) { info.releaseAllSurfaces() info.changes[i].leash.release() } for (i in leashMap.size - 1 downTo 0) { for (i in leashMap.size - 1 downTo 0) { leashMap.valueAt(i).release() leashMap.valueAt(i).release() } } Loading @@ -331,6 +329,7 @@ class RemoteTransitionAdapter { null /* wct */, null /* wct */, finishTransaction finishTransaction ) ) finishTransaction.close() } catch (e: RemoteException) { } catch (e: RemoteException) { Log.e( Log.e( "ActivityOptionsCompat", "ActivityOptionsCompat", Loading Loading @@ -364,6 +363,9 @@ class RemoteTransitionAdapter { ) { ) { // TODO: hook up merge to recents onTaskAppeared if applicable. Until then, // TODO: hook up merge to recents onTaskAppeared if applicable. Until then, // ignore any incoming merges. // ignore any incoming merges. // Clean up stuff though cuz GC takes too long for benchmark tests. t.close() info.releaseAllSurfaces() } } } } } } Loading