blob: 392557045b4a4708651c2581c60a2e89a7cc644a [file] [log] [blame]
Jorim Jaggi02886a82016-12-06 09:10:06 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
Jorim Jaggi30d64f32017-04-07 16:33:17 +020019import static android.graphics.Color.WHITE;
20import static android.graphics.Color.alpha;
Adrian Roos4c864592019-04-10 14:47:57 +020021import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
22import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020023import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
24import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
25import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
26import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
Jorim Jaggi02886a82016-12-06 09:10:06 -080027import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
28import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020029import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
30import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
31import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
32import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
33import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
Jorim Jaggia6aabac2019-03-11 14:23:16 -070034import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
35import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020036import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
Jorim Jaggia6aabac2019-03-11 14:23:16 -070037import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
Jorim Jaggi02886a82016-12-06 09:10:06 -080038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -080039
Jorim Jaggi30d64f32017-04-07 16:33:17 +020040import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
41import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
42import static com.android.internal.policy.DecorView.getColorViewLeftInset;
43import static com.android.internal.policy.DecorView.getColorViewTopInset;
44import static com.android.internal.policy.DecorView.getNavigationBarRect;
Adrian Roosb125e0b2019-10-02 14:55:14 +020045import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
Jorim Jaggi02886a82016-12-06 09:10:06 -080046import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
47import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
48
Jorim Jaggid635a4a2017-05-03 15:21:26 +020049import android.annotation.Nullable;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010050import android.app.ActivityManager.TaskDescription;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020051import android.app.ActivityManager.TaskSnapshot;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020052import android.app.ActivityThread;
53import android.content.Context;
Jorim Jaggi02886a82016-12-06 09:10:06 -080054import android.graphics.Canvas;
Winson Chung51f42d22018-02-01 14:59:38 -080055import android.graphics.Color;
Jorim Jaggi02886a82016-12-06 09:10:06 -080056import android.graphics.GraphicBuffer;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -080057import android.graphics.Matrix;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010058import android.graphics.Paint;
Valerie Hau30360552020-01-14 16:12:01 -080059import android.graphics.Point;
Jorim Jaggi02886a82016-12-06 09:10:06 -080060import android.graphics.Rect;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -080061import android.graphics.RectF;
Jorim Jaggi02886a82016-12-06 09:10:06 -080062import android.os.Handler;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010063import android.os.Looper;
Jorim Jaggi02886a82016-12-06 09:10:06 -080064import android.os.Message;
65import android.os.RemoteException;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020066import android.os.SystemClock;
Andrii Kulian44607962017-03-16 11:06:24 -070067import android.util.MergedConfiguration;
Jorim Jaggi02886a82016-12-06 09:10:06 -080068import android.util.Slog;
Adrian Roos5c6b6222017-11-07 17:36:10 +010069import android.view.DisplayCutout;
Jorim Jaggi02886a82016-12-06 09:10:06 -080070import android.view.IWindowSession;
Tiger Huang0426a332020-03-29 01:17:08 +080071import android.view.InsetsSourceControl;
Chavi Weingarten6ef9cc62019-02-07 16:28:45 +000072import android.view.InsetsState;
Jorim Jaggi02886a82016-12-06 09:10:06 -080073import android.view.Surface;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020074import android.view.SurfaceControl;
75import android.view.SurfaceSession;
Jorim Jaggi02886a82016-12-06 09:10:06 -080076import android.view.View;
77import android.view.ViewGroup.LayoutParams;
Tiger Huang4a7835f2019-11-06 00:07:56 +080078import android.view.ViewRootImpl;
Jorim Jaggi02886a82016-12-06 09:10:06 -080079import android.view.WindowManager;
80import android.view.WindowManagerGlobal;
Jorim Jaggi02886a82016-12-06 09:10:06 -080081
Jorim Jaggi30d64f32017-04-07 16:33:17 +020082import com.android.internal.R;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010083import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020084import com.android.internal.policy.DecorView;
Jorim Jaggi02886a82016-12-06 09:10:06 -080085import com.android.internal.view.BaseIWindow;
Adrian Roose99bc052017-11-20 17:55:31 +010086import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Adrian Roosb125e0b2019-10-02 14:55:14 +020087import com.android.server.protolog.common.ProtoLog;
Jorim Jaggi02886a82016-12-06 09:10:06 -080088
89/**
90 * This class represents a starting window that shows a snapshot.
91 * <p>
92 * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
93 */
94class TaskSnapshotSurface implements StartingSurface {
95
Jorim Jaggi30d64f32017-04-07 16:33:17 +020096 private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
97
98 /**
99 * When creating the starting window, we use the exact same layout flags such that we end up
100 * with a window with the exact same dimensions etc. However, these flags are not used in layout
101 * and might cause other side effects so we exclude them.
102 */
103 private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
104 | FLAG_NOT_TOUCHABLE
105 | FLAG_NOT_TOUCH_MODAL
106 | FLAG_ALT_FOCUSABLE_IM
107 | FLAG_NOT_FOCUSABLE
108 | FLAG_HARDWARE_ACCELERATED
109 | FLAG_IGNORE_CHEEK_PRESSES
110 | FLAG_LOCAL_FOCUS_MODE
111 | FLAG_SLIPPERY
112 | FLAG_WATCH_OUTSIDE_TOUCH
113 | FLAG_SPLIT_TOUCH
114 | FLAG_SCALED
115 | FLAG_SECURE;
116
Jorim Jaggia6aabac2019-03-11 14:23:16 -0700117 private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
Jorim Jaggid2616322017-06-07 12:38:19 -0700118
Jorim Jaggi02886a82016-12-06 09:10:06 -0800119 private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
120 private static final int MSG_REPORT_DRAW = 0;
121 private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
Robert Carr2e20bcd2020-01-22 13:32:38 -0800122
123 //tmp vars for unused relayout params
124 private static final Point sTmpSurfaceSize = new Point();
125 private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl();
126
Jorim Jaggi02886a82016-12-06 09:10:06 -0800127 private final Window mWindow;
128 private final Surface mSurface;
Robert Carr5fea55b2018-12-10 13:05:52 -0800129 private SurfaceControl mSurfaceControl;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200130 private SurfaceControl mChildSurfaceControl;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800131 private final IWindowSession mSession;
132 private final WindowManagerService mService;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200133 private final Rect mTaskBounds;
134 private final Rect mStableInsets = new Rect();
135 private final Rect mContentInsets = new Rect();
136 private final Rect mFrame = new Rect();
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200137 private TaskSnapshot mSnapshot;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800138 private final RectF mTmpSnapshotSize = new RectF();
139 private final RectF mTmpDstFrame = new RectF();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200140 private final CharSequence mTitle;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800141 private boolean mHasDrawn;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200142 private long mShownTime;
143 private final Handler mHandler;
144 private boolean mSizeMismatch;
145 private final Paint mBackgroundPaint = new Paint();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200146 private final int mStatusBarColor;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200147 @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700148 private final int mOrientationOnCreation;
chaviw619da692019-06-10 15:39:40 -0700149 private final SurfaceControl.Transaction mTransaction;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800150 private final Matrix mSnapshotMatrix = new Matrix();
151 private final float[] mTmpFloat9 = new float[9];
Jorim Jaggi02886a82016-12-06 09:10:06 -0800152
Garfield Tane8d84ab2019-10-11 09:49:40 -0700153 static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200154 TaskSnapshot snapshot) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800155
156 final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
157 final Window window = new Window();
158 final IWindowSession session = WindowManagerGlobal.getWindowSession();
159 window.setSession(session);
Robert Carr5fea55b2018-12-10 13:05:52 -0800160 final SurfaceControl surfaceControl = new SurfaceControl();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800161 final Rect tmpRect = new Rect();
Adrian Roos5c6b6222017-11-07 17:36:10 +0100162 final DisplayCutout.ParcelableWrapper tmpCutout = new DisplayCutout.ParcelableWrapper();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800163 final Rect tmpFrame = new Rect();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200164 final Rect taskBounds;
165 final Rect tmpContentInsets = new Rect();
166 final Rect tmpStableInsets = new Rect();
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200167 final InsetsState mTmpInsetsState = new InsetsState();
Tiger Huang0426a332020-03-29 01:17:08 +0800168 final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
Andrii Kulian44607962017-03-16 11:06:24 -0700169 final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
Adrian Roos4c864592019-04-10 14:47:57 +0200170 final TaskDescription taskDescription = new TaskDescription();
171 taskDescription.setBackgroundColor(WHITE);
Riddle Hsu84bc3d72019-12-19 19:24:07 +0800172 final WindowState topFullscreenOpaqueWindow;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200173 final int sysUiVis;
174 final int windowFlags;
175 final int windowPrivateFlags;
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700176 final int currentOrientation;
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700177 synchronized (service.mGlobalLock) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700178 final WindowState mainWindow = activity.findMainWindow();
179 final Task task = activity.getTask();
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +0200180 if (task == null) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700181 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
182 + activity);
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +0200183 return null;
184 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700185 final ActivityRecord topFullscreenActivity =
186 activity.getTask().getTopFullscreenActivity();
187 if (topFullscreenActivity == null) {
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +0200188 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
189 + task);
190 return null;
191 }
Riddle Hsu84bc3d72019-12-19 19:24:07 +0800192 topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
193 if (mainWindow == null || topFullscreenOpaqueWindow == null) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700194 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
195 + activity);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200196 return null;
197 }
Riddle Hsudb94bfd2020-05-13 01:50:17 +0800198 if (topFullscreenActivity.getWindowConfiguration().getRotation()
199 != snapshot.getRotation()) {
200 // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
201 // that the activity will be updated to the same rotation as the snapshot. Since
202 // the transition is not started yet, fixed rotation transform needs to be applied
203 // earlier to make the snapshot show in a rotated container.
204 activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
205 topFullscreenActivity, false /* checkOpening */);
206 }
207
Riddle Hsu84bc3d72019-12-19 19:24:07 +0800208 sysUiVis = topFullscreenOpaqueWindow.getSystemUiVisibility();
Jorim Jaggie670be72020-01-30 22:18:00 +0100209 WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
210 windowFlags = attrs.flags;
211 windowPrivateFlags = attrs.privateFlags;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200212
Jorim Jaggi90b3c472018-04-06 16:02:07 +0200213 layoutParams.packageName = mainWindow.getAttrs().packageName;
214 layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations;
Winson Chungbe9be7f2017-06-28 10:55:22 -0700215 layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800216 layoutParams.type = TYPE_APPLICATION_STARTING;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200217 layoutParams.format = snapshot.getSnapshot().getFormat();
218 layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
Jorim Jaggi02886a82016-12-06 09:10:06 -0800219 | FLAG_NOT_FOCUSABLE
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200220 | FLAG_NOT_TOUCHABLE;
Wale Ogunwale01ad4342017-06-30 07:07:01 -0700221 layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700222 layoutParams.token = activity.token;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800223 layoutParams.width = LayoutParams.MATCH_PARENT;
224 layoutParams.height = LayoutParams.MATCH_PARENT;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200225 layoutParams.systemUiVisibility = sysUiVis;
Jorim Jaggie670be72020-01-30 22:18:00 +0100226 layoutParams.insetsFlags.behavior
227 = topFullscreenOpaqueWindow.mAttrs.insetsFlags.behavior;
228 layoutParams.insetsFlags.appearance
229 = topFullscreenOpaqueWindow.mAttrs.insetsFlags.appearance;
shawnlin4d2a2f42020-04-14 14:34:16 +0800230 layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
Jorim Jaggie670be72020-01-30 22:18:00 +0100231 layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
232 layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
233 layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
234
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +0200235 layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
Bryce Lee6d410262017-02-28 15:30:17 -0800236
Adrian Roos4c864592019-04-10 14:47:57 +0200237 final TaskDescription td = task.getTaskDescription();
238 if (td != null) {
Mehdi Alizadehc5e29902019-11-14 17:18:44 -0800239 taskDescription.copyFromPreserveHiddenFields(td);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100240 }
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +0200241 taskBounds = new Rect();
242 task.getBounds(taskBounds);
Riddle Hsu84bc3d72019-12-19 19:24:07 +0800243 currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800244 }
245 try {
246 final int res = session.addToDisplay(window, window.mSeq, layoutParams,
Tiger Huang0426a332020-03-29 01:17:08 +0800247 View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect,
248 tmpRect, tmpCutout, null, mTmpInsetsState, mTempControls);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800249 if (res < 0) {
250 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
251 return null;
252 }
253 } catch (RemoteException e) {
254 // Local call.
255 }
256 final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
Adrian Roos4c864592019-04-10 14:47:57 +0200257 surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
258 windowFlags, windowPrivateFlags, taskBounds,
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +0100259 currentOrientation, topFullscreenOpaqueWindow.getRequestedInsetsState());
Jorim Jaggi02886a82016-12-06 09:10:06 -0800260 window.setOuter(snapshotSurface);
261 try {
chaviwbe43ac82018-04-04 15:14:49 -0700262 session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
Jorim Jaggif081f062019-10-24 16:24:54 +0200263 tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect,
Valerie Hau30360552020-01-14 16:12:01 -0800264 tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
Tiger Huang0426a332020-03-29 01:17:08 +0800265 mTempControls, sTmpSurfaceSize, sTmpSurfaceControl);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800266 } catch (RemoteException e) {
267 // Local call.
268 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200269 snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
270 snapshotSurface.drawSnapshot();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800271 return snapshotSurface;
272 }
273
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100274 @VisibleForTesting
Robert Carr5fea55b2018-12-10 13:05:52 -0800275 TaskSnapshotSurface(WindowManagerService service, Window window, SurfaceControl surfaceControl,
Adrian Roos4c864592019-04-10 14:47:57 +0200276 TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
277 int sysUiVis, int windowFlags, int windowPrivateFlags, Rect taskBounds,
Tiger Huang4a7835f2019-11-06 00:07:56 +0800278 int currentOrientation, InsetsState insetsState) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800279 mService = service;
Vishnu Nair33197392019-08-30 10:29:37 -0700280 mSurface = service.mSurfaceFactory.get();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200281 mHandler = new Handler(mService.mH.getLooper());
Jorim Jaggi02886a82016-12-06 09:10:06 -0800282 mSession = WindowManagerGlobal.getWindowSession();
283 mWindow = window;
Robert Carr5fea55b2018-12-10 13:05:52 -0800284 mSurfaceControl = surfaceControl;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200285 mSnapshot = snapshot;
286 mTitle = title;
Adrian Roos4c864592019-04-10 14:47:57 +0200287 int backgroundColor = taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200288 mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
289 mTaskBounds = taskBounds;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200290 mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
Tiger Huang4a7835f2019-11-06 00:07:56 +0800291 windowPrivateFlags, sysUiVis, taskDescription, 1f, insetsState);
Adrian Roos4c864592019-04-10 14:47:57 +0200292 mStatusBarColor = taskDescription.getStatusBarColor();
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700293 mOrientationOnCreation = currentOrientation;
chaviw619da692019-06-10 15:39:40 -0700294 mTransaction = mService.mTransactionFactory.get();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800295 }
296
297 @Override
298 public void remove() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700299 synchronized (mService.mGlobalLock) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200300 final long now = SystemClock.uptimeMillis();
301 if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
302 mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200303 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
304 "Defer removing snapshot surface in %dms", (now - mShownTime));
305
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200306 return;
307 }
308 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800309 try {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200310 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing snapshot surface");
Jorim Jaggi02886a82016-12-06 09:10:06 -0800311 mSession.remove(mWindow);
312 } catch (RemoteException e) {
313 // Local call.
314 }
315 }
316
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200317 @VisibleForTesting
318 void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
319 mFrame.set(frame);
320 mContentInsets.set(contentInsets);
321 mStableInsets.set(stableInsets);
322 mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
323 || mFrame.height() != mSnapshot.getSnapshot().getHeight());
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200324 mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200325 }
326
327 private void drawSnapshot() {
Robert Carr5fea55b2018-12-10 13:05:52 -0800328 mSurface.copyFrom(mSurfaceControl);
329
Adrian Roosb125e0b2019-10-02 14:55:14 +0200330 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Drawing snapshot surface sizeMismatch=%b",
331 mSizeMismatch);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200332 if (mSizeMismatch) {
333 // The dimensions of the buffer and the window don't match, so attaching the buffer
334 // will fail. Better create a child window with the exact dimensions and fill the parent
335 // window with the background color!
Peiyong Linccc06b62019-06-25 17:31:09 -0700336 drawSizeMismatchSnapshot();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200337 } else {
Peiyong Linccc06b62019-06-25 17:31:09 -0700338 drawSizeMatchSnapshot();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200339 }
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700340 synchronized (mService.mGlobalLock) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200341 mShownTime = SystemClock.uptimeMillis();
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100342 mHasDrawn = true;
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100343 }
Jorim Jaggidc9385a2017-05-13 02:00:31 +0200344 reportDrawn();
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200345
346 // In case window manager leaks us, make sure we don't retain the snapshot.
347 mSnapshot = null;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200348 }
349
Peiyong Linccc06b62019-06-25 17:31:09 -0700350 private void drawSizeMatchSnapshot() {
351 mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getSnapshot(),
352 mSnapshot.getColorSpace());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200353 mSurface.release();
354 }
355
Peiyong Linccc06b62019-06-25 17:31:09 -0700356 private void drawSizeMismatchSnapshot() {
Shibin George9696bd32018-02-26 20:29:44 +0530357 if (!mSurface.isValid()) {
358 throw new IllegalStateException("mSurface does not hold a valid surface.");
359 }
Peiyong Linccc06b62019-06-25 17:31:09 -0700360 final GraphicBuffer buffer = mSnapshot.getSnapshot();
Robert Carr5fea55b2018-12-10 13:05:52 -0800361 final SurfaceSession session = new SurfaceSession();
Winson Chung357deda2019-06-23 13:35:41 -0700362 // We consider nearly matched dimensions as there can be rounding errors and the user won't
363 // notice very minute differences from scaling one dimension more than the other
364 final boolean aspectRatioMismatch = Math.abs(
365 ((float) buffer.getWidth() / buffer.getHeight())
366 - ((float) mFrame.width() / mFrame.height())) > 0.01f;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200367
368 // Keep a reference to it such that it doesn't get destroyed when finalized.
Vishnu Nair33197392019-08-30 10:29:37 -0700369 mChildSurfaceControl = mService.mSurfaceControlFactory.apply(session)
Robert Carre625fcf2017-09-01 12:36:28 -0700370 .setName(mTitle + " - task-snapshot-surface")
Vishnu Naire86bd982018-11-28 13:23:17 -0800371 .setBufferSize(buffer.getWidth(), buffer.getHeight())
Robert Carre625fcf2017-09-01 12:36:28 -0700372 .setFormat(buffer.getFormat())
Robert Carr5fea55b2018-12-10 13:05:52 -0800373 .setParent(mSurfaceControl)
Robert Carre625fcf2017-09-01 12:36:28 -0700374 .build();
Vishnu Nair33197392019-08-30 10:29:37 -0700375 Surface surface = mService.mSurfaceFactory.get();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200376 surface.copyFrom(mChildSurfaceControl);
377
Winson Chung357deda2019-06-23 13:35:41 -0700378 final Rect frame;
chaviw619da692019-06-10 15:39:40 -0700379 // We can just show the surface here as it will still be hidden as the parent is
380 // still hidden.
381 mTransaction.show(mChildSurfaceControl);
382 if (aspectRatioMismatch) {
383 // Clip off ugly navigation bar.
384 final Rect crop = calculateSnapshotCrop();
385 frame = calculateSnapshotFrame(crop);
386 mTransaction.setWindowCrop(mChildSurfaceControl, crop);
387 mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top);
shawnlin4d2a2f42020-04-14 14:34:16 +0800388 mTmpSnapshotSize.set(crop);
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800389 mTmpDstFrame.set(frame);
chaviw619da692019-06-10 15:39:40 -0700390 } else {
391 frame = null;
shawnlin4d2a2f42020-04-14 14:34:16 +0800392 mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800393 mTmpDstFrame.set(mFrame);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200394 }
chaviw619da692019-06-10 15:39:40 -0700395
396 // Scale the mismatch dimensions to fill the task bounds
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800397 mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
398 mTransaction.setMatrix(mChildSurfaceControl, mSnapshotMatrix, mTmpFloat9);
399
chaviw619da692019-06-10 15:39:40 -0700400 mTransaction.apply();
Peiyong Linccc06b62019-06-25 17:31:09 -0700401 surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200402 surface.release();
403
Winson Chung357deda2019-06-23 13:35:41 -0700404 if (aspectRatioMismatch) {
405 final Canvas c = mSurface.lockCanvas(null);
406 drawBackgroundAndBars(c, frame);
407 mSurface.unlockCanvasAndPost(c);
408 mSurface.release();
409 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800410 }
411
Matthew Ngcb7ac672017-07-21 17:27:42 -0700412 /**
413 * Calculates the snapshot crop in snapshot coordinate space.
414 *
415 * @return crop rect in snapshot coordinate space.
416 */
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100417 @VisibleForTesting
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200418 Rect calculateSnapshotCrop() {
419 final Rect rect = new Rect();
420 rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
421 final Rect insets = mSnapshot.getContentInsets();
422
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800423 final float scaleX = (float) mSnapshot.getSnapshot().getWidth() / mSnapshot.getTaskSize().x;
424 final float scaleY =
425 (float) mSnapshot.getSnapshot().getHeight() / mSnapshot.getTaskSize().y;
426
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200427 // Let's remove all system decorations except the status bar, but only if the task is at the
428 // very top of the screen.
Adrian Roos98a146d2017-11-29 16:39:44 +0100429 final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800430 rect.inset((int) (insets.left * scaleX),
431 isTop ? 0 : (int) (insets.top * scaleY),
432 (int) (insets.right * scaleX),
433 (int) (insets.bottom * scaleY));
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200434 return rect;
435 }
436
Matthew Ngcb7ac672017-07-21 17:27:42 -0700437 /**
438 * Calculates the snapshot frame in window coordinate space from crop.
439 *
440 * @param crop rect that is in snapshot coordinate space.
441 */
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200442 @VisibleForTesting
443 Rect calculateSnapshotFrame(Rect crop) {
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800444 final float scaleX = (float) mSnapshot.getSnapshot().getWidth() / mSnapshot.getTaskSize().x;
445 final float scaleY =
446 (float) mSnapshot.getSnapshot().getHeight() / mSnapshot.getTaskSize().y;
Matthew Ngcb7ac672017-07-21 17:27:42 -0700447
448 // Rescale the frame from snapshot to window coordinate space
shawnlin4d2a2f42020-04-14 14:34:16 +0800449 final Rect frame = new Rect(0, 0,
450 (int) (crop.width() / scaleX + 0.5f),
451 (int) (crop.height() / scaleY + 0.5f)
Peter Kalauskasfe0a4132020-01-31 16:50:42 -0800452 );
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200453
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200454 // However, we also need to make space for the navigation bar on the left side.
455 final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
456 mContentInsets.left);
457 frame.offset(colorViewLeftInset, 0);
458 return frame;
459 }
460
461 @VisibleForTesting
462 void drawBackgroundAndBars(Canvas c, Rect frame) {
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200463 final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200464 final boolean fillHorizontally = c.getWidth() > frame.right;
465 final boolean fillVertically = c.getHeight() > frame.bottom;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100466 if (fillHorizontally) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200467 c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
468 c.getWidth(), fillVertically
469 ? frame.bottom
470 : c.getHeight(),
471 mBackgroundPaint);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100472 }
473 if (fillVertically) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200474 c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
475 }
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200476 mSystemBarBackgroundPainter.drawDecors(c, frame);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100477 }
478
Jorim Jaggi02886a82016-12-06 09:10:06 -0800479 private void reportDrawn() {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800480 try {
Vishnu Nairf7645aa2019-06-18 11:14:01 -0700481 mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800482 } catch (RemoteException e) {
483 // Local call.
484 }
485 }
486
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100487 private static Handler sHandler = new Handler(Looper.getMainLooper()) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800488
489 @Override
490 public void handleMessage(Message msg) {
491 switch (msg.what) {
492 case MSG_REPORT_DRAW:
493 final boolean hasDrawn;
494 final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700495 synchronized (surface.mService.mGlobalLock) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800496 hasDrawn = surface.mHasDrawn;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800497 }
498 if (hasDrawn) {
499 surface.reportDrawn();
500 }
501 break;
502 }
503 }
504 };
505
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200506 @VisibleForTesting
507 static class Window extends BaseIWindow {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800508
509 private TaskSnapshotSurface mOuter;
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700510
Jorim Jaggi02886a82016-12-06 09:10:06 -0800511 public void setOuter(TaskSnapshotSurface outer) {
512 mOuter = outer;
513 }
514
515 @Override
Jorim Jaggif081f062019-10-24 16:24:54 +0200516 public void resized(Rect frame, Rect contentInsets, Rect visibleInsets,
517 Rect stableInsets, boolean reportDraw,
Andrii Kulian44607962017-03-16 11:06:24 -0700518 MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
Brad Stenninge0573692019-03-11 13:52:46 -0700519 boolean alwaysConsumeSystemBars, int displayId,
Adrian Roos5c6b6222017-11-07 17:36:10 +0100520 DisplayCutout.ParcelableWrapper displayCutout) {
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700521 if (mergedConfiguration != null && mOuter != null
522 && mOuter.mOrientationOnCreation
523 != mergedConfiguration.getMergedConfiguration().orientation) {
524
525 // The orientation of the screen is changing. We better remove the snapshot ASAP as
526 // we are going to wait on the new window in any case to unfreeze the screen, and
527 // the starting window is not needed anymore.
528 sHandler.post(mOuter::remove);
529 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800530 if (reportDraw) {
531 sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
532 }
533 }
534 }
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200535
536 /**
537 * Helper class to draw the background of the system bars in regions the task snapshot isn't
538 * filling the window.
539 */
540 static class SystemBarBackgroundPainter {
541
542 private final Rect mContentInsets = new Rect();
543 private final Rect mStableInsets = new Rect();
544 private final Paint mStatusBarPaint = new Paint();
545 private final Paint mNavigationBarPaint = new Paint();
546 private final int mStatusBarColor;
547 private final int mNavigationBarColor;
548 private final int mWindowFlags;
549 private final int mWindowPrivateFlags;
550 private final int mSysUiVis;
Winson Chungffde2ea2019-06-17 17:19:13 -0700551 private final float mScale;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800552 private final InsetsState mInsetsState;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200553
Winson Chungffde2ea2019-06-17 17:19:13 -0700554 SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
Tiger Huang4a7835f2019-11-06 00:07:56 +0800555 TaskDescription taskDescription, float scale, InsetsState insetsState) {
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200556 mWindowFlags = windowFlags;
557 mWindowPrivateFlags = windowPrivateFlags;
558 mSysUiVis = sysUiVis;
Winson Chungffde2ea2019-06-17 17:19:13 -0700559 mScale = scale;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200560 final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
Jorim Jaggia6aabac2019-03-11 14:23:16 -0700561 final int semiTransparent = context.getColor(
562 R.color.system_bar_background_semi_transparent);
563 mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
Adrian Roos4c864592019-04-10 14:47:57 +0200564 semiTransparent, taskDescription.getStatusBarColor(), sysUiVis,
565 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
566 taskDescription.getEnsureStatusBarContrastWhenTransparent());
Jorim Jaggia6aabac2019-03-11 14:23:16 -0700567 mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
Adrian Roos4c864592019-04-10 14:47:57 +0200568 FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
569 taskDescription.getNavigationBarColor(), sysUiVis,
570 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
571 taskDescription.getEnsureNavigationBarContrastWhenTransparent()
572 && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200573 mStatusBarPaint.setColor(mStatusBarColor);
Adrian Roos4c864592019-04-10 14:47:57 +0200574 mNavigationBarPaint.setColor(mNavigationBarColor);
Tiger Huang4a7835f2019-11-06 00:07:56 +0800575 mInsetsState = insetsState;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200576 }
577
578 void setInsets(Rect contentInsets, Rect stableInsets) {
579 mContentInsets.set(contentInsets);
580 mStableInsets.set(stableInsets);
581 }
582
583 int getStatusBarColorViewHeight() {
Jorim Jaggia6aabac2019-03-11 14:23:16 -0700584 final boolean forceBarBackground =
585 (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800586 if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
587 ? STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
588 mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
589 : STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
590 mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
Winson Chungffde2ea2019-06-17 17:19:13 -0700591 return (int) (getColorViewTopInset(mStableInsets.top, mContentInsets.top) * mScale);
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200592 } else {
593 return 0;
594 }
595 }
596
597 private boolean isNavigationBarColorViewVisible() {
Jorim Jaggia6aabac2019-03-11 14:23:16 -0700598 final boolean forceBarBackground =
599 (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800600 return ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
601 ? NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
602 mSysUiVis, mNavigationBarColor, mWindowFlags, forceBarBackground)
603 : NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
604 mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200605 }
606
607 void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
608 drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
609 drawNavigationBarBackground(c);
610 }
611
612 @VisibleForTesting
613 void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
614 int statusBarHeight) {
Winson Chung51f42d22018-02-01 14:59:38 -0800615 if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200616 && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
Winson Chungffde2ea2019-06-17 17:19:13 -0700617 final int rightInset = (int) (DecorView.getColorViewRightInset(mStableInsets.right,
618 mContentInsets.right) * mScale);
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200619 final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
620 c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
621 }
622 }
623
624 @VisibleForTesting
625 void drawNavigationBarBackground(Canvas c) {
626 final Rect navigationBarRect = new Rect();
627 getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
Winson Chungffde2ea2019-06-17 17:19:13 -0700628 navigationBarRect, mScale);
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200629 final boolean visible = isNavigationBarColorViewVisible();
Winson Chung51f42d22018-02-01 14:59:38 -0800630 if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200631 c.drawRect(navigationBarRect, mNavigationBarPaint);
632 }
633 }
634 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800635}