102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/* 202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Copyright (C) 2016 The Android Open Source Project 302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * you may not use this file except in compliance with the License. 602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * You may obtain a copy of the License at 702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 1002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Unless required by applicable law or agreed to in writing, software 1102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 1202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * See the License for the specific language governing permissions and 1402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * limitations under the License 1502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */ 1602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 1702886a82d876aa5e31a92444fec70208599c509cJorim Jaggipackage com.android.server.wm; 1802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 1930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.graphics.Color.WHITE; 2030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.graphics.Color.alpha; 2130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.SurfaceControl.HIDDEN; 2230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 23be9be7f8ad3f8a7806c33cbc62a6b3e4bd6aa427Winson Chungimport static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; 2430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 2530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; 2630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE; 2702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 2802886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 2930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 3030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_SCALED; 3130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_SECURE; 3230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; 3330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; 3430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 3530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 3602886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 3730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; 3830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; 3930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static com.android.internal.policy.DecorView.getColorViewLeftInset; 4030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static com.android.internal.policy.DecorView.getColorViewTopInset; 4130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport static com.android.internal.policy.DecorView.getNavigationBarRect; 42e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 4302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 4402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 4502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 46d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggiimport android.annotation.Nullable; 47829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggiimport android.app.ActivityManager.TaskDescription; 4830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport android.app.ActivityManager.TaskSnapshot; 49d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggiimport android.app.ActivityThread; 50d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggiimport android.content.Context; 5102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.Canvas; 5202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.GraphicBuffer; 53829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggiimport android.graphics.Paint; 5402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.Rect; 5502886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.Handler; 56829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggiimport android.os.Looper; 5702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.Message; 5802886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.RemoteException; 5930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport android.os.SystemClock; 60446079600ece83b22cb91865bcbeb694292b0108Andrii Kulianimport android.util.MergedConfiguration; 6102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.util.Slog; 6202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.IWindowSession; 6302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.Surface; 6430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport android.view.SurfaceControl; 6530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport android.view.SurfaceSession; 6602886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.View; 6702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.ViewGroup.LayoutParams; 6802886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManager; 6902886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManagerGlobal; 7002886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManagerPolicy.StartingSurface; 7102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 7230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport com.android.internal.R; 73829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggiimport com.android.internal.annotations.VisibleForTesting; 7430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggiimport com.android.internal.policy.DecorView; 7502886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport com.android.internal.view.BaseIWindow; 7602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 7702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/** 7802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * This class represents a starting window that shows a snapshot. 7902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * <p> 8002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS! 8102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */ 8202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiclass TaskSnapshotSurface implements StartingSurface { 8302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 8430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450; 8530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 8630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi /** 8730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi * When creating the starting window, we use the exact same layout flags such that we end up 8830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi * with a window with the exact same dimensions etc. However, these flags are not used in layout 8930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi * and might cause other side effects so we exclude them. 9030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi */ 9130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE 9230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_NOT_TOUCHABLE 9330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_NOT_TOUCH_MODAL 9430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_ALT_FOCUSABLE_IM 9530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_NOT_FOCUSABLE 9630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_HARDWARE_ACCELERATED 9730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_IGNORE_CHEEK_PRESSES 9830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_LOCAL_FOCUS_MODE 9930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_SLIPPERY 10030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_WATCH_OUTSIDE_TOUCH 10130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_SPLIT_TOUCH 10230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_SCALED 10330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_SECURE; 10430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 105d261632710e822db1f3c94879a15f2821a993384Jorim Jaggi private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 106d261632710e822db1f3c94879a15f2821a993384Jorim Jaggi 10702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM; 10802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private static final int MSG_REPORT_DRAW = 0; 10902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s"; 11002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private final Window mWindow; 11102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private final Surface mSurface; 11230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private SurfaceControl mChildSurfaceControl; 11302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private final IWindowSession mSession; 11402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private final WindowManagerService mService; 11530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Rect mTaskBounds; 11630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Rect mStableInsets = new Rect(); 11730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Rect mContentInsets = new Rect(); 11830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Rect mFrame = new Rect(); 1194448e1ebb2d00f31292abcc7c5161a4e6f050c2eJorim Jaggi private TaskSnapshot mSnapshot; 12030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final CharSequence mTitle; 12102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private boolean mHasDrawn; 12230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private long mShownTime; 12330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Handler mHandler; 12430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private boolean mSizeMismatch; 12530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final Paint mBackgroundPaint = new Paint(); 12630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private final int mStatusBarColor; 127d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter; 12838d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi private final int mOrientationOnCreation; 12902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 13002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token, 13130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi TaskSnapshot snapshot) { 13202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 13302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); 13402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final Window window = new Window(); 13502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final IWindowSession session = WindowManagerGlobal.getWindowSession(); 13602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi window.setSession(session); 13702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final Surface surface = new Surface(); 13802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final Rect tmpRect = new Rect(); 13902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final Rect tmpFrame = new Rect(); 14030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect taskBounds; 14130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect tmpContentInsets = new Rect(); 14230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect tmpStableInsets = new Rect(); 143446079600ece83b22cb91865bcbeb694292b0108Andrii Kulian final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration(); 14430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi int backgroundColor = WHITE; 14530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi int statusBarColor = 0; 14630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi int navigationBarColor = 0; 14730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final int sysUiVis; 14830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final int windowFlags; 14930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final int windowPrivateFlags; 15038d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi final int currentOrientation; 15102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi synchronized (service.mWindowMap) { 15230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final WindowState mainWindow = token.findMainWindow(); 153e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi final Task task = token.getTask(); 154e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi if (task == null) { 155e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token=" 156e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi + token); 157e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi return null; 158e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi } 159e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken(); 160e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi if (topFullscreenToken == null) { 161e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task=" 162e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi + task); 163e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi return null; 164e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi } 16587fdbcbecb1025b92ad5d48f032b3bb7e228b7bdJorim Jaggi final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow(); 166e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi if (mainWindow == null || topFullscreenWindow == null) { 16730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token=" 16830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi + token); 16930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi return null; 17030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 171e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi sysUiVis = topFullscreenWindow.getSystemUiVisibility(); 172e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi windowFlags = topFullscreenWindow.getAttrs().flags; 173e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags; 17430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 175be9be7f8ad3f8a7806c33cbc62a6b3e4bd6aa427Winson Chung layoutParams.dimAmount = mainWindow.getAttrs().dimAmount; 17602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi layoutParams.type = TYPE_APPLICATION_STARTING; 17730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi layoutParams.format = snapshot.getSnapshot().getFormat(); 17830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES) 17902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi | FLAG_NOT_FOCUSABLE 18030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi | FLAG_NOT_TOUCHABLE; 18101ad4345f92080439a5ccde9cb085f3f90d8709bWale Ogunwale layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS; 18202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi layoutParams.token = token.token; 18302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi layoutParams.width = LayoutParams.MATCH_PARENT; 18402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi layoutParams.height = LayoutParams.MATCH_PARENT; 18530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi layoutParams.systemUiVisibility = sysUiVis; 186e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId)); 1876d41026f1b3dc910c9d34ab89993a280dc9679cfBryce Lee 188e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi final TaskDescription taskDescription = task.getTaskDescription(); 189e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi if (taskDescription != null) { 190e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi backgroundColor = taskDescription.getBackgroundColor(); 191e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi statusBarColor = taskDescription.getStatusBarColor(); 192e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi navigationBarColor = taskDescription.getNavigationBarColor(); 193829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi } 194e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi taskBounds = new Rect(); 195e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi task.getBounds(taskBounds); 196e6c6ecb2b038edaa0828119773857825bc579f86Jorim Jaggi currentOrientation = topFullscreenWindow.getConfiguration().orientation; 19702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 19802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi try { 19902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final int res = session.addToDisplay(window, window.mSeq, layoutParams, 20002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi View.VISIBLE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect, 20102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi tmpRect, null); 20202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi if (res < 0) { 20302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi Slog.w(TAG, "Failed to add snapshot starting window res=" + res); 20402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi return null; 20502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 20602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } catch (RemoteException e) { 20702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi // Local call. 20802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 20902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window, 21030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor, 21138d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds, 21238d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi currentOrientation); 21302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi window.setOuter(snapshotSurface); 21402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi try { 21502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame, 21630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect, 21730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi tmpMergedConfiguration, surface); 21802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } catch (RemoteException e) { 21902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi // Local call. 22002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 22130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets); 22230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi snapshotSurface.drawSnapshot(); 22302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi return snapshotSurface; 22402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 22502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 226829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi @VisibleForTesting 227829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface, 22830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor, 22930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags, 23038d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi Rect taskBounds, int currentOrientation) { 23102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mService = service; 23230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mHandler = new Handler(mService.mH.getLooper()); 23302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mSession = WindowManagerGlobal.getWindowSession(); 23402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mWindow = window; 23502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mSurface = surface; 23630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mSnapshot = snapshot; 23730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mTitle = title; 23830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE); 23930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mTaskBounds = taskBounds; 240d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags, 241d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi windowPrivateFlags, sysUiVis, statusBarColor, navigationBarColor); 242d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mStatusBarColor = statusBarColor; 24338d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi mOrientationOnCreation = currentOrientation; 24402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 24502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 24602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi @Override 24702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi public void remove() { 24830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi synchronized (mService.mWindowMap) { 24930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final long now = SystemClock.uptimeMillis(); 25030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) { 25130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS); 252e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi if (DEBUG_STARTING_WINDOW) { 253e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi Slog.v(TAG, "Defer removing snapshot surface in " + (now - mShownTime) + "ms"); 254e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi } 25530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi return; 25630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 25730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 25802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi try { 259e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing snapshot surface"); 26002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mSession.remove(mWindow); 26102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } catch (RemoteException e) { 26202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi // Local call. 26302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 26402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 26502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 26630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi @VisibleForTesting 26730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) { 26830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mFrame.set(frame); 26930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mContentInsets.set(contentInsets); 27030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mStableInsets.set(stableInsets); 27130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth() 27230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi || mFrame.height() != mSnapshot.getSnapshot().getHeight()); 273d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets); 27430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 27530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 27630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private void drawSnapshot() { 27730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final GraphicBuffer buffer = mSnapshot.getSnapshot(); 278e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch=" 279e4b0f28a47097b7b0c04f3ae80507e2a15e3314fJorim Jaggi + mSizeMismatch); 28030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi if (mSizeMismatch) { 28130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // The dimensions of the buffer and the window don't match, so attaching the buffer 28230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // will fail. Better create a child window with the exact dimensions and fill the parent 28330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // window with the background color! 28430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi drawSizeMismatchSnapshot(buffer); 28530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } else { 28630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi drawSizeMatchSnapshot(buffer); 28730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 28839367cf662f5ba190d0d7627f0e788a367e1d71fJorim Jaggi synchronized (mService.mWindowMap) { 28930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mShownTime = SystemClock.uptimeMillis(); 29039367cf662f5ba190d0d7627f0e788a367e1d71fJorim Jaggi mHasDrawn = true; 29139367cf662f5ba190d0d7627f0e788a367e1d71fJorim Jaggi } 292dc9385aad49bf2ba24c1221a5d4558a1ac69f97aJorim Jaggi reportDrawn(); 2934448e1ebb2d00f31292abcc7c5161a4e6f050c2eJorim Jaggi 2944448e1ebb2d00f31292abcc7c5161a4e6f050c2eJorim Jaggi // In case window manager leaks us, make sure we don't retain the snapshot. 2954448e1ebb2d00f31292abcc7c5161a4e6f050c2eJorim Jaggi mSnapshot = null; 29630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 29730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 29830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private void drawSizeMatchSnapshot(GraphicBuffer buffer) { 29930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mSurface.attachAndQueueBuffer(buffer); 30030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mSurface.release(); 30130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 30230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 30330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi private void drawSizeMismatchSnapshot(GraphicBuffer buffer) { 30430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final SurfaceSession session = new SurfaceSession(mSurface); 30530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 30630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // Keep a reference to it such that it doesn't get destroyed when finalized. 30730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mChildSurfaceControl = new SurfaceControl(session, 30830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mTitle + " - task-snapshot-surface", 30930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN); 31030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi Surface surface = new Surface(); 31130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi surface.copyFrom(mChildSurfaceControl); 31230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 31330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // Clip off ugly navigation bar. 31430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect crop = calculateSnapshotCrop(); 31530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect frame = calculateSnapshotFrame(crop); 31630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi SurfaceControl.openTransaction(); 31730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi try { 31830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // We can just show the surface here as it will still be hidden as the parent is 31930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // still hidden. 32030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mChildSurfaceControl.show(); 32130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mChildSurfaceControl.setWindowCrop(crop); 32230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mChildSurfaceControl.setPosition(frame.left, frame.top); 323cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng 324cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng // Scale the mismatch dimensions to fill the task bounds 325cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng final float scale = 1 / mSnapshot.getScale(); 326cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng mChildSurfaceControl.setMatrix(scale, 0, 0, scale); 32730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } finally { 32830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi SurfaceControl.closeTransaction(); 32930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 33030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi surface.attachAndQueueBuffer(buffer); 33130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi surface.release(); 33230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 33330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Canvas c = mSurface.lockCanvas(null); 33430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi drawBackgroundAndBars(c, frame); 33530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mSurface.unlockCanvasAndPost(c); 3362f24b65075d66c278fa7f279a1a62f7376331900Jorim Jaggi mSurface.release(); 33702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 33802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 339cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng /** 340cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * Calculates the snapshot crop in snapshot coordinate space. 341cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * 342cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * @return crop rect in snapshot coordinate space. 343cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng */ 344829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi @VisibleForTesting 34530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi Rect calculateSnapshotCrop() { 34630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect rect = new Rect(); 34730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight()); 34830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect insets = mSnapshot.getContentInsets(); 34930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 35030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // Let's remove all system decorations except the status bar, but only if the task is at the 35130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // very top of the screen. 352cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng rect.inset((int) (insets.left * mSnapshot.getScale()), 353cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng mTaskBounds.top != 0 ? (int) (insets.top * mSnapshot.getScale()) : 0, 354cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng (int) (insets.right * mSnapshot.getScale()), 355cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng (int) (insets.bottom * mSnapshot.getScale())); 35630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi return rect; 35730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 35830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 359cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng /** 360cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * Calculates the snapshot frame in window coordinate space from crop. 361cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * 362cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng * @param crop rect that is in snapshot coordinate space. 363cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng */ 36430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi @VisibleForTesting 36530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi Rect calculateSnapshotFrame(Rect crop) { 36630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final Rect frame = new Rect(crop); 367cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng final float scale = mSnapshot.getScale(); 368cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng 369cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng // Rescale the frame from snapshot to window coordinate space 370cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng frame.scale(1 / scale); 37130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 37230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // By default, offset it to to top/left corner 373cb7ac679a5c4cdbef7f3fa232ca168d876cd27c5Matthew Ng frame.offsetTo((int) (-crop.left / scale), (int) (-crop.top / scale)); 37430d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 37530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi // However, we also need to make space for the navigation bar on the left side. 37630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left, 37730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mContentInsets.left); 37830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi frame.offset(colorViewLeftInset, 0); 37930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi return frame; 38030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 38130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi 38230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi @VisibleForTesting 38330d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi void drawBackgroundAndBars(Canvas c, Rect frame) { 384d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight(); 38530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final boolean fillHorizontally = c.getWidth() > frame.right; 38630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi final boolean fillVertically = c.getHeight() > frame.bottom; 387829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi if (fillHorizontally) { 38830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0, 38930d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi c.getWidth(), fillVertically 39030d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi ? frame.bottom 39130d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi : c.getHeight(), 39230d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi mBackgroundPaint); 393829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi } 394829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi if (fillVertically) { 39530d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint); 39630d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi } 397d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSystemBarBackgroundPainter.drawDecors(c, frame); 398829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi } 399829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi 40002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private void reportDrawn() { 40102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi try { 40202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mSession.finishDrawing(mWindow); 40302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } catch (RemoteException e) { 40402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi // Local call. 40502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 40602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 40702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 408829b9cd100ddea44fadb9931c0ff11b11aaba059Jorim Jaggi private static Handler sHandler = new Handler(Looper.getMainLooper()) { 40902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 41002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi @Override 41102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi public void handleMessage(Message msg) { 41202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi switch (msg.what) { 41302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi case MSG_REPORT_DRAW: 41402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final boolean hasDrawn; 41502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj; 41602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi synchronized (surface.mService.mWindowMap) { 41702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi hasDrawn = surface.mHasDrawn; 41802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 41902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi if (hasDrawn) { 42002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi surface.reportDrawn(); 42102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 42202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi break; 42302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 42402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 42502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi }; 42602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 42730d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi @VisibleForTesting 42830d64f3a93f5fc5aaf75eeb38d658ef04a884b41Jorim Jaggi static class Window extends BaseIWindow { 42902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 43002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi private TaskSnapshotSurface mOuter; 43138d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi 43202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi public void setOuter(TaskSnapshotSurface outer) { 43302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi mOuter = outer; 43402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 43502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 43602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi @Override 43702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, 438446079600ece83b22cb91865bcbeb694292b0108Andrii Kulian Rect stableInsets, Rect outsets, boolean reportDraw, 439446079600ece83b22cb91865bcbeb694292b0108Andrii Kulian MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, 440446079600ece83b22cb91865bcbeb694292b0108Andrii Kulian boolean alwaysConsumeNavBar, int displayId) { 44138d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi if (mergedConfiguration != null && mOuter != null 44238d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi && mOuter.mOrientationOnCreation 44338d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi != mergedConfiguration.getMergedConfiguration().orientation) { 44438d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi 44538d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi // The orientation of the screen is changing. We better remove the snapshot ASAP as 44638d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi // we are going to wait on the new window in any case to unfreeze the screen, and 44738d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi // the starting window is not needed anymore. 44838d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi sHandler.post(mOuter::remove); 44938d44ec857a75ebc98818743d08addf81ddc923eJorim Jaggi } 45002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi if (reportDraw) { 45102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget(); 45202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 45302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 45402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 455d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 456d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi /** 457d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi * Helper class to draw the background of the system bars in regions the task snapshot isn't 458d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi * filling the window. 459d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi */ 460d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi static class SystemBarBackgroundPainter { 461d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 462d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final Rect mContentInsets = new Rect(); 463d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final Rect mStableInsets = new Rect(); 464d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final Paint mStatusBarPaint = new Paint(); 465d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final Paint mNavigationBarPaint = new Paint(); 466d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final int mStatusBarColor; 467d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final int mNavigationBarColor; 468d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final int mWindowFlags; 469d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final int mWindowPrivateFlags; 470d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private final int mSysUiVis; 471d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 472d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi SystemBarBackgroundPainter( int windowFlags, int windowPrivateFlags, int sysUiVis, 473d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi int statusBarColor, int navigationBarColor) { 474d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mWindowFlags = windowFlags; 475d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mWindowPrivateFlags = windowPrivateFlags; 476d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSysUiVis = sysUiVis; 477d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final Context context = ActivityThread.currentActivityThread().getSystemUiContext(); 478d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags, 479d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi context.getColor(R.color.system_bar_background_semi_transparent), 480d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi statusBarColor); 481d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mNavigationBarColor = navigationBarColor; 482d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mStatusBarPaint.setColor(mStatusBarColor); 483d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mNavigationBarPaint.setColor(navigationBarColor); 484d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 485d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 486d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi void setInsets(Rect contentInsets, Rect stableInsets) { 487d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mContentInsets.set(contentInsets); 488d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mStableInsets.set(stableInsets); 489d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 490d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 491d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi int getStatusBarColorViewHeight() { 492d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final boolean forceStatusBarBackground = 493d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 494d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible( 495d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) { 496d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi return getColorViewTopInset(mStableInsets.top, mContentInsets.top); 497d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } else { 498d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi return 0; 499d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 500d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 501d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 502d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi private boolean isNavigationBarColorViewVisible() { 503d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible( 504d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */); 505d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 506d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 507d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) { 508d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight()); 509d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi drawNavigationBarBackground(c); 510d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 511d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 512d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi @VisibleForTesting 513d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame, 514d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi int statusBarHeight) { 515d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi if (statusBarHeight > 0 516d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) { 517d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right, 518d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi mContentInsets.right); 519d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0; 520d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint); 521d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 522d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 523d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi 524d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi @VisibleForTesting 525d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi void drawNavigationBarBackground(Canvas c) { 526d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final Rect navigationBarRect = new Rect(); 527d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets, 528d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi navigationBarRect); 529d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi final boolean visible = isNavigationBarColorViewVisible(); 530d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi if (visible && !navigationBarRect.isEmpty()) { 531d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi c.drawRect(navigationBarRect, mNavigationBarPaint); 532d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 533d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 534d635a4ae20014b6ff52d8b05e7f4f622808d4efdJorim Jaggi } 53502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi} 536