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