Lock free app animations (4/n): Implement thubmnail
Bug: 64674361
Test: go/wm-smoke
Change-Id: I8f25dae04b69613c93ccb5416c2cda2df6373103
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index dcf2a87..de4b426 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -55,6 +55,7 @@
import android.annotation.NonNull;
import android.app.Activity;
import android.content.res.Configuration;
+import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -208,6 +209,8 @@
/** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
private boolean mLastSurfaceShowing;
+ private AppWindowThumbnail mThumbnail;
+
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
@@ -1618,6 +1621,8 @@
setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
"AppWindowToken");
+ clearThumbnail();
+
if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
getDisplayContent().computeImeTarget(true /* updateImeTarget */);
}
@@ -1657,6 +1662,12 @@
return super.isSelfAnimating();
}
+ @Override
+ void cancelAnimation() {
+ super.cancelAnimation();
+ clearThumbnail();
+ }
+
boolean isWaitingForTransitionStart() {
return mService.mAppTransition.isTransitionSet()
&& (mService.mOpeningApps.contains(this) || mService.mClosingApps.contains(this));
@@ -1670,8 +1681,44 @@
return mTransitFlags;
}
- void clearThumbnail() {
- // TODO
+ void attachThumbnailAnimation() {
+ if (!isReallyAnimating()) {
+ return;
+ }
+ final int taskId = getTask().mTaskId;
+ final GraphicBuffer thumbnailHeader =
+ mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
+ if (thumbnailHeader == null) {
+ if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
+ return;
+ }
+ clearThumbnail();
+ mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
+ mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
+ }
+
+ private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+
+ // If this is a multi-window scenario, we use the windows frame as
+ // destination of the thumbnail header animation. If this is a full screen
+ // window scenario, we use the whole display as the target.
+ WindowState win = findMainWindow();
+ Rect appRect = win != null ? win.getContentFrameLw() :
+ new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+ Rect insets = win != null ? win.mContentInsets : null;
+ final Configuration displayConfig = mDisplayContent.getConfiguration();
+ return mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(
+ appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
+ displayConfig.orientation);
+ }
+
+ private void clearThumbnail() {
+ if (mThumbnail == null) {
+ return;
+ }
+ mThumbnail.destroy();
+ mThumbnail = null;
}
@Override
@@ -1753,6 +1800,9 @@
} else if (!show && mLastSurfaceShowing) {
mPendingTransaction.hide(mSurfaceControl);
}
+ if (mThumbnail != null) {
+ mThumbnail.setShowing(mPendingTransaction, show);
+ }
mLastSurfaceShowing = show;
super.prepareSurfaces();
}