Expose the system ui visibility flags and translucent state with snapshot

- Allow SystemUI/Launcher to determine whether the snapshot is of a
  translucent activity (to reduce overdraw by skipping drawing task
  background) and also the sysui visibility flags are (to determine how
  to update the nav bar while animating before the app is started.
- Fixing issue where the recents animation was reporting task fillsparent
  state instead of the app's fillsparent state (as we do in normal remote
  animations)

Bug: 79228291
Bug: 77984778
Bug: 78659249
Test: atest FrameworksServicesTests:TaskSnapshotPersisterLoaderTest
Change-Id: I19bdf7f780e7d94014d6a115bf84fa614b1dffa0
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 539a010..3c7541f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2110,9 +2110,12 @@
         private final boolean mIsRealSnapshot;
         private final int mWindowingMode;
         private final float mScale;
+        private final int mSystemUiVisibility;
+        private final boolean mIsTranslucent;
 
         public TaskSnapshot(GraphicBuffer snapshot, int orientation, Rect contentInsets,
-                boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode) {
+                boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
+                int systemUiVisibility, boolean isTranslucent) {
             mSnapshot = snapshot;
             mOrientation = orientation;
             mContentInsets = new Rect(contentInsets);
@@ -2120,6 +2123,8 @@
             mScale = scale;
             mIsRealSnapshot = isRealSnapshot;
             mWindowingMode = windowingMode;
+            mSystemUiVisibility = systemUiVisibility;
+            mIsTranslucent = isTranslucent;
         }
 
         private TaskSnapshot(Parcel source) {
@@ -2130,6 +2135,8 @@
             mScale = source.readFloat();
             mIsRealSnapshot = source.readBoolean();
             mWindowingMode = source.readInt();
+            mSystemUiVisibility = source.readInt();
+            mIsTranslucent = source.readBoolean();
         }
 
         /**
@@ -2170,6 +2177,13 @@
         }
 
         /**
+         * @return Whether or not the snapshot is of a translucent app window.
+         */
+        public boolean isTranslucent() {
+            return mIsTranslucent;
+        }
+
+        /**
          * @return The windowing mode of the task when this snapshot was taken.
          */
         public int getWindowingMode() {
@@ -2177,6 +2191,14 @@
         }
 
         /**
+         * @return The system ui visibility flags for the top most visible fullscreen window at the
+         *         time that the snapshot was taken.
+         */
+        public int getSystemUiVisibility() {
+            return mSystemUiVisibility;
+        }
+
+        /**
          * @return The scale this snapshot was taken in.
          */
         public float getScale() {
@@ -2197,6 +2219,8 @@
             dest.writeFloat(mScale);
             dest.writeBoolean(mIsRealSnapshot);
             dest.writeInt(mWindowingMode);
+            dest.writeInt(mSystemUiVisibility);
+            dest.writeBoolean(mIsTranslucent);
         }
 
         @Override
@@ -2207,7 +2231,9 @@
                     + " mOrientation=" + mOrientation
                     + " mContentInsets=" + mContentInsets.toShortString()
                     + " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
-                    + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode;
+                    + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode
+                    + " mSystemUiVisibility=" + mSystemUiVisibility
+                    + " mIsTranslucent=" + mIsTranslucent;
         }
 
         public static final Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 7429cb5..f84c72e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -33,7 +33,9 @@
     public Rect insets;
     public boolean reducedResolution;
     public boolean isRealSnapshot;
+    public boolean isTranslucent;
     public int windowingMode;
+    public int systemUiVisibility;
     public float scale;
 
     public ThumbnailData() {
@@ -43,7 +45,9 @@
         reducedResolution = false;
         scale = 1f;
         isRealSnapshot = true;
+        isTranslucent = false;
         windowingMode = WINDOWING_MODE_UNDEFINED;
+        systemUiVisibility = 0;
     }
 
     public ThumbnailData(TaskSnapshot snapshot) {
@@ -53,6 +57,8 @@
         reducedResolution = snapshot.isReducedResolution();
         scale = snapshot.getScale();
         isRealSnapshot = snapshot.isRealSnapshot();
+        isTranslucent = snapshot.isTranslucent();
         windowingMode = snapshot.getWindowingMode();
+        systemUiVisibility = snapshot.getSystemUiVisibility();
     }
 }
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 27febef..65d6256 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -29,4 +29,6 @@
      int32 inset_bottom = 5;
      bool is_real_snapshot = 6;
      int32 windowing_mode = 7;
+     int32 system_ui_visibility = 8;
+     bool is_translucent = 9;
  }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 553b4fe..096ab0b 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -558,14 +558,17 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationApp() {
-            final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
+            final AppWindowToken topApp = mTask.getTopVisibleAppToken();
+            final WindowState mainWindow = topApp != null
+                    ? topApp.findMainWindow()
+                    : null;
             if (mainWindow == null) {
                 return null;
             }
             final Rect insets = new Rect(mainWindow.mContentInsets);
             InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
-                    !mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
+                    !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
                     insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
                     mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
             return mTarget;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index efc4e73..f17bbb9 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -37,6 +37,7 @@
 import android.view.RenderNode;
 import android.view.SurfaceControl;
 import android.view.ThreadedRenderer;
+import android.view.View;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -274,7 +275,8 @@
         }
         return new TaskSnapshot(buffer, top.getConfiguration().orientation,
                 getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
-                true /* isRealSnapshot */, task.getWindowingMode());
+                true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
+                !top.fillsParent());
     }
 
     private boolean shouldDisableSnapshots() {
@@ -364,7 +366,8 @@
         return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
                 topChild.getConfiguration().orientation, mainWindow.mStableInsets,
                 ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
-                false /* isRealSnapshot */, task.getWindowingMode());
+                false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
+                !topChild.fillsParent());
     }
 
     /**
@@ -429,6 +432,21 @@
         });
     }
 
+    /**
+     * @return The SystemUI visibility flags for the top fullscreen window in the given
+     *         {@param task}.
+     */
+    private int getSystemUiVisibility(Task task) {
+        final AppWindowToken topFullscreenToken = task.getTopFullscreenAppToken();
+        final WindowState topFullscreenWindow = topFullscreenToken != null
+                ? topFullscreenToken.getTopFullscreenWindow()
+                : null;
+        if (topFullscreenWindow != null) {
+            return topFullscreenWindow.getSystemUiVisibility();
+        }
+        return 0;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         mCache.dump(pw, prefix);
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index b682a32..1410c21 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -90,7 +90,8 @@
             return new TaskSnapshot(buffer, proto.orientation,
                     new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
                     reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
-                    proto.isRealSnapshot, proto.windowingMode);
+                    proto.isRealSnapshot, proto.windowingMode, proto.systemUiVisibility,
+                    proto.isTranslucent);
         } catch (IOException e) {
             Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
             return null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 408fb3c..a642e6a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -317,6 +317,8 @@
             proto.insetBottom = mSnapshot.getContentInsets().bottom;
             proto.isRealSnapshot = mSnapshot.isRealSnapshot();
             proto.windowingMode = mSnapshot.getWindowingMode();
+            proto.systemUiVisibility = mSnapshot.getSystemUiVisibility();
+            proto.isTranslucent = mSnapshot.isTranslucent();
             final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
             final File file = getProtoFile(mTaskId, mUserId);
             final AtomicFile atomicFile = new AtomicFile(file);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 13478df..325d42a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -34,6 +34,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import android.view.View;
 import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
 
 import org.junit.Test;
@@ -166,10 +167,12 @@
 
     @Test
     public void testIsRealSnapshotPersistAndLoadSnapshot() {
-        TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
-                WINDOWING_MODE_FULLSCREEN);
-        TaskSnapshot b = createSnapshot(1f /* scale */, false /* isRealSnapshot */,
-                WINDOWING_MODE_FULLSCREEN);
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setIsRealSnapshot(true)
+                .build();
+        TaskSnapshot b = new TaskSnapshotBuilder()
+                .setIsRealSnapshot(false)
+                .build();
         assertTrue(a.isRealSnapshot());
         assertFalse(b.isRealSnapshot());
         mPersister.persistSnapshot(1, mTestUserId, a);
@@ -185,10 +188,12 @@
 
     @Test
     public void testWindowingModePersistAndLoadSnapshot() {
-        TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
-                WINDOWING_MODE_FULLSCREEN);
-        TaskSnapshot b = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
-                WINDOWING_MODE_PINNED);
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .build();
+        TaskSnapshot b = new TaskSnapshotBuilder()
+                .setWindowingMode(WINDOWING_MODE_PINNED)
+                .build();
         assertTrue(a.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
         assertTrue(b.getWindowingMode() == WINDOWING_MODE_PINNED);
         mPersister.persistSnapshot(1, mTestUserId, a);
@@ -203,6 +208,50 @@
     }
 
     @Test
+    public void testIsTranslucentPersistAndLoadSnapshot() {
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setIsTranslucent(true)
+                .build();
+        TaskSnapshot b = new TaskSnapshotBuilder()
+                .setIsTranslucent(false)
+                .build();
+        assertTrue(a.isTranslucent());
+        assertFalse(b.isTranslucent());
+        mPersister.persistSnapshot(1, mTestUserId, a);
+        mPersister.persistSnapshot(2, mTestUserId, b);
+        mPersister.waitForQueueEmpty();
+        final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+        final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+        assertNotNull(snapshotA);
+        assertNotNull(snapshotB);
+        assertTrue(snapshotA.isTranslucent());
+        assertFalse(snapshotB.isTranslucent());
+    }
+
+    @Test
+    public void testSystemUiVisibilityPersistAndLoadSnapshot() {
+        final int lightBarFlags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+                | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setSystemUiVisibility(0)
+                .build();
+        TaskSnapshot b = new TaskSnapshotBuilder()
+                .setSystemUiVisibility(lightBarFlags)
+                .build();
+        assertTrue(a.getSystemUiVisibility() == 0);
+        assertTrue(b.getSystemUiVisibility() == lightBarFlags);
+        mPersister.persistSnapshot(1, mTestUserId, a);
+        mPersister.persistSnapshot(2, mTestUserId, b);
+        mPersister.waitForQueueEmpty();
+        final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+        final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+        assertNotNull(snapshotA);
+        assertNotNull(snapshotB);
+        assertTrue(snapshotA.getSystemUiVisibility() == 0);
+        assertTrue(snapshotB.getSystemUiVisibility() == lightBarFlags);
+    }
+
+    @Test
     public void testRemoveObsoleteFiles() {
         mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
         mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 6a4acbe..8b86043 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -85,16 +85,57 @@
     }
 
     TaskSnapshot createSnapshot(float scale) {
-        return createSnapshot(scale, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN);
+        return new TaskSnapshotBuilder()
+                .setScale(scale)
+                .build();
     }
 
-    TaskSnapshot createSnapshot(float scale, boolean isRealSnapshot, int windowingMode) {
-        final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
-                USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
-        Canvas c = buffer.lockCanvas();
-        c.drawColor(Color.RED);
-        buffer.unlockCanvasAndPost(c);
-        return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
-                scale < 1f /* reducedResolution */, scale, isRealSnapshot, windowingMode);
+    /**
+     * Builds a TaskSnapshot.
+     */
+    class TaskSnapshotBuilder {
+
+        private float mScale = 1f;
+        private boolean mIsRealSnapshot = true;
+        private boolean mIsTranslucent = false;
+        private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+        private int mSystemUiVisibility = 0;
+
+        public TaskSnapshotBuilder setScale(float scale) {
+            mScale = scale;
+            return this;
+        }
+
+        public TaskSnapshotBuilder setIsRealSnapshot(boolean isRealSnapshot) {
+            mIsRealSnapshot = isRealSnapshot;
+            return this;
+        }
+
+        public TaskSnapshotBuilder setIsTranslucent(boolean isTranslucent) {
+            mIsTranslucent = isTranslucent;
+            return this;
+        }
+
+        public TaskSnapshotBuilder setWindowingMode(int windowingMode) {
+            mWindowingMode = windowingMode;
+            return this;
+        }
+
+        public TaskSnapshotBuilder setSystemUiVisibility(int systemUiVisibility) {
+            mSystemUiVisibility = systemUiVisibility;
+            return this;
+        }
+
+        public TaskSnapshot build() {
+            final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
+                    USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
+            Canvas c = buffer.lockCanvas();
+            c.drawColor(Color.RED);
+            buffer.unlockCanvasAndPost(c);
+            return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
+                    mScale < 1f /* reducedResolution */, mScale, mIsRealSnapshot, mWindowingMode,
+                    mSystemUiVisibility, mIsTranslucent);
+        }
+
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 54d02d4..b19373e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -62,7 +62,7 @@
                 GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
         final TaskSnapshot snapshot = new TaskSnapshot(buffer,
                 ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
-                WINDOWING_MODE_FULLSCREEN);
+                WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */);
         mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
                 Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds,
                 ORIENTATION_PORTRAIT);