blob: 3a116bb10d98289483f8735a954c4ca48a68232c [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;
21import static android.view.SurfaceControl.HIDDEN;
22import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
23import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
24import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
25import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
Jorim Jaggi02886a82016-12-06 09:10:06 -080026import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
27import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020028import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
29import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
30import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
31import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
32import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
33import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
34import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
Jorim Jaggi02886a82016-12-06 09:10:06 -080035import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
36import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020037import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
38import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
39import static com.android.internal.policy.DecorView.getColorViewLeftInset;
40import static com.android.internal.policy.DecorView.getColorViewTopInset;
41import static com.android.internal.policy.DecorView.getNavigationBarRect;
Jorim Jaggie4b0f282017-05-17 15:10:29 +020042import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
Jorim Jaggi02886a82016-12-06 09:10:06 -080043import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
44import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
45
Jorim Jaggid635a4a2017-05-03 15:21:26 +020046import android.annotation.Nullable;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010047import android.app.ActivityManager.TaskDescription;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020048import android.app.ActivityManager.TaskSnapshot;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020049import android.app.ActivityThread;
50import android.content.Context;
Jorim Jaggi02886a82016-12-06 09:10:06 -080051import android.graphics.Canvas;
52import android.graphics.GraphicBuffer;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010053import android.graphics.Paint;
Jorim Jaggi02886a82016-12-06 09:10:06 -080054import android.graphics.Rect;
55import android.os.Handler;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010056import android.os.Looper;
Jorim Jaggi02886a82016-12-06 09:10:06 -080057import android.os.Message;
58import android.os.RemoteException;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020059import android.os.SystemClock;
Andrii Kulian44607962017-03-16 11:06:24 -070060import android.util.MergedConfiguration;
Jorim Jaggi02886a82016-12-06 09:10:06 -080061import android.util.Slog;
Jorim Jaggi02886a82016-12-06 09:10:06 -080062import android.view.IWindowSession;
63import android.view.Surface;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020064import android.view.SurfaceControl;
65import android.view.SurfaceSession;
Jorim Jaggi02886a82016-12-06 09:10:06 -080066import android.view.View;
67import android.view.ViewGroup.LayoutParams;
68import android.view.WindowManager;
69import android.view.WindowManagerGlobal;
70import android.view.WindowManagerPolicy.StartingSurface;
71
Jorim Jaggi30d64f32017-04-07 16:33:17 +020072import com.android.internal.R;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010073import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020074import com.android.internal.policy.DecorView;
Jorim Jaggi02886a82016-12-06 09:10:06 -080075import com.android.internal.view.BaseIWindow;
76
77/**
78 * This class represents a starting window that shows a snapshot.
79 * <p>
80 * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
81 */
82class TaskSnapshotSurface implements StartingSurface {
83
Jorim Jaggi30d64f32017-04-07 16:33:17 +020084 private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
85
86 /**
87 * When creating the starting window, we use the exact same layout flags such that we end up
88 * with a window with the exact same dimensions etc. However, these flags are not used in layout
89 * and might cause other side effects so we exclude them.
90 */
91 private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
92 | FLAG_NOT_TOUCHABLE
93 | FLAG_NOT_TOUCH_MODAL
94 | FLAG_ALT_FOCUSABLE_IM
95 | FLAG_NOT_FOCUSABLE
96 | FLAG_HARDWARE_ACCELERATED
97 | FLAG_IGNORE_CHEEK_PRESSES
98 | FLAG_LOCAL_FOCUS_MODE
99 | FLAG_SLIPPERY
100 | FLAG_WATCH_OUTSIDE_TOUCH
101 | FLAG_SPLIT_TOUCH
102 | FLAG_SCALED
103 | FLAG_SECURE;
104
Jorim Jaggi02886a82016-12-06 09:10:06 -0800105 private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
106 private static final int MSG_REPORT_DRAW = 0;
107 private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
108 private final Window mWindow;
109 private final Surface mSurface;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200110 private SurfaceControl mChildSurfaceControl;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800111 private final IWindowSession mSession;
112 private final WindowManagerService mService;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200113 private final Rect mTaskBounds;
114 private final Rect mStableInsets = new Rect();
115 private final Rect mContentInsets = new Rect();
116 private final Rect mFrame = new Rect();
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200117 private TaskSnapshot mSnapshot;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200118 private final CharSequence mTitle;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800119 private boolean mHasDrawn;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200120 private long mShownTime;
121 private final Handler mHandler;
122 private boolean mSizeMismatch;
123 private final Paint mBackgroundPaint = new Paint();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200124 private final int mStatusBarColor;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200125 @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800126
127 static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200128 TaskSnapshot snapshot) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800129
130 final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
131 final Window window = new Window();
132 final IWindowSession session = WindowManagerGlobal.getWindowSession();
133 window.setSession(session);
134 final Surface surface = new Surface();
135 final Rect tmpRect = new Rect();
136 final Rect tmpFrame = new Rect();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200137 final Rect taskBounds;
138 final Rect tmpContentInsets = new Rect();
139 final Rect tmpStableInsets = new Rect();
Andrii Kulian44607962017-03-16 11:06:24 -0700140 final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200141 int backgroundColor = WHITE;
142 int statusBarColor = 0;
143 int navigationBarColor = 0;
144 final int sysUiVis;
145 final int windowFlags;
146 final int windowPrivateFlags;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800147 synchronized (service.mWindowMap) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200148 final WindowState mainWindow = token.findMainWindow();
149 if (mainWindow == null) {
150 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
151 + token);
152 return null;
153 }
154 sysUiVis = mainWindow.getSystemUiVisibility();
155 windowFlags = mainWindow.getAttrs().flags;
156 windowPrivateFlags = mainWindow.getAttrs().privateFlags;
157
Jorim Jaggi02886a82016-12-06 09:10:06 -0800158 layoutParams.type = TYPE_APPLICATION_STARTING;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200159 layoutParams.format = snapshot.getSnapshot().getFormat();
160 layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
Jorim Jaggi02886a82016-12-06 09:10:06 -0800161 | FLAG_NOT_FOCUSABLE
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200162 | FLAG_NOT_TOUCHABLE;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800163 layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
164 layoutParams.token = token.token;
165 layoutParams.width = LayoutParams.MATCH_PARENT;
166 layoutParams.height = LayoutParams.MATCH_PARENT;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200167 layoutParams.systemUiVisibility = sysUiVis;
Bryce Lee6d410262017-02-28 15:30:17 -0800168 final Task task = token.getTask();
169 if (task != null) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200170 layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
Bryce Lee6d410262017-02-28 15:30:17 -0800171
172 final TaskDescription taskDescription = task.getTaskDescription();
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100173 if (taskDescription != null) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200174 backgroundColor = taskDescription.getBackgroundColor();
175 statusBarColor = taskDescription.getStatusBarColor();
176 navigationBarColor = taskDescription.getNavigationBarColor();
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100177 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200178 taskBounds = new Rect();
179 task.getBounds(taskBounds);
180 } else {
181 taskBounds = null;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100182 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800183 }
184 try {
185 final int res = session.addToDisplay(window, window.mSeq, layoutParams,
186 View.VISIBLE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
187 tmpRect, null);
188 if (res < 0) {
189 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
190 return null;
191 }
192 } catch (RemoteException e) {
193 // Local call.
194 }
195 final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200196 surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor,
197 navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800198 window.setOuter(snapshotSurface);
199 try {
200 session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200201 tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
202 tmpMergedConfiguration, surface);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800203 } catch (RemoteException e) {
204 // Local call.
205 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200206 snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
207 snapshotSurface.drawSnapshot();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800208 return snapshotSurface;
209 }
210
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100211 @VisibleForTesting
212 TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200213 TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor,
214 int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags,
215 Rect taskBounds) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800216 mService = service;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200217 mHandler = new Handler(mService.mH.getLooper());
Jorim Jaggi02886a82016-12-06 09:10:06 -0800218 mSession = WindowManagerGlobal.getWindowSession();
219 mWindow = window;
220 mSurface = surface;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200221 mSnapshot = snapshot;
222 mTitle = title;
223 mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
224 mTaskBounds = taskBounds;
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200225 mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
226 windowPrivateFlags, sysUiVis, statusBarColor, navigationBarColor);
227 mStatusBarColor = statusBarColor;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800228 }
229
230 @Override
231 public void remove() {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200232 synchronized (mService.mWindowMap) {
233 final long now = SystemClock.uptimeMillis();
234 if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
235 mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200236 if (DEBUG_STARTING_WINDOW) {
237 Slog.v(TAG, "Defer removing snapshot surface in " + (now - mShownTime) + "ms");
238 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200239 return;
240 }
241 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800242 try {
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200243 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing snapshot surface");
Jorim Jaggi02886a82016-12-06 09:10:06 -0800244 mSession.remove(mWindow);
245 } catch (RemoteException e) {
246 // Local call.
247 }
248 }
249
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200250 @VisibleForTesting
251 void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
252 mFrame.set(frame);
253 mContentInsets.set(contentInsets);
254 mStableInsets.set(stableInsets);
255 mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
256 || mFrame.height() != mSnapshot.getSnapshot().getHeight());
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200257 mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200258 }
259
260 private void drawSnapshot() {
261 final GraphicBuffer buffer = mSnapshot.getSnapshot();
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200262 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch="
263 + mSizeMismatch);
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200264 if (mSizeMismatch) {
265 // The dimensions of the buffer and the window don't match, so attaching the buffer
266 // will fail. Better create a child window with the exact dimensions and fill the parent
267 // window with the background color!
268 drawSizeMismatchSnapshot(buffer);
269 } else {
270 drawSizeMatchSnapshot(buffer);
271 }
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100272 synchronized (mService.mWindowMap) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200273 mShownTime = SystemClock.uptimeMillis();
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100274 mHasDrawn = true;
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100275 }
Jorim Jaggidc9385a2017-05-13 02:00:31 +0200276 reportDrawn();
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200277
278 // In case window manager leaks us, make sure we don't retain the snapshot.
279 mSnapshot = null;
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200280 }
281
282 private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
283 mSurface.attachAndQueueBuffer(buffer);
284 mSurface.release();
285 }
286
287 private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
288 final SurfaceSession session = new SurfaceSession(mSurface);
289
290 // Keep a reference to it such that it doesn't get destroyed when finalized.
291 mChildSurfaceControl = new SurfaceControl(session,
292 mTitle + " - task-snapshot-surface",
293 buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN);
294 Surface surface = new Surface();
295 surface.copyFrom(mChildSurfaceControl);
296
297 // Clip off ugly navigation bar.
298 final Rect crop = calculateSnapshotCrop();
299 final Rect frame = calculateSnapshotFrame(crop);
300 SurfaceControl.openTransaction();
301 try {
302 // We can just show the surface here as it will still be hidden as the parent is
303 // still hidden.
304 mChildSurfaceControl.show();
305 mChildSurfaceControl.setWindowCrop(crop);
306 mChildSurfaceControl.setPosition(frame.left, frame.top);
307 } finally {
308 SurfaceControl.closeTransaction();
309 }
310 surface.attachAndQueueBuffer(buffer);
311 surface.release();
312
313 final Canvas c = mSurface.lockCanvas(null);
314 drawBackgroundAndBars(c, frame);
315 mSurface.unlockCanvasAndPost(c);
Jorim Jaggi2f24b652017-01-18 02:17:37 +0100316 mSurface.release();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800317 }
318
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100319 @VisibleForTesting
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200320 Rect calculateSnapshotCrop() {
321 final Rect rect = new Rect();
322 rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
323 final Rect insets = mSnapshot.getContentInsets();
324
325 // Let's remove all system decorations except the status bar, but only if the task is at the
326 // very top of the screen.
327 rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom);
328 return rect;
329 }
330
331 @VisibleForTesting
332 Rect calculateSnapshotFrame(Rect crop) {
333 final Rect frame = new Rect(crop);
334
335 // By default, offset it to to top/left corner
336 frame.offsetTo(-crop.left, -crop.top);
337
338 // However, we also need to make space for the navigation bar on the left side.
339 final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
340 mContentInsets.left);
341 frame.offset(colorViewLeftInset, 0);
342 return frame;
343 }
344
345 @VisibleForTesting
346 void drawBackgroundAndBars(Canvas c, Rect frame) {
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200347 final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200348 final boolean fillHorizontally = c.getWidth() > frame.right;
349 final boolean fillVertically = c.getHeight() > frame.bottom;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100350 if (fillHorizontally) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200351 c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
352 c.getWidth(), fillVertically
353 ? frame.bottom
354 : c.getHeight(),
355 mBackgroundPaint);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100356 }
357 if (fillVertically) {
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200358 c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
359 }
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200360 mSystemBarBackgroundPainter.drawDecors(c, frame);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100361 }
362
Jorim Jaggi02886a82016-12-06 09:10:06 -0800363 private void reportDrawn() {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800364 try {
365 mSession.finishDrawing(mWindow);
366 } catch (RemoteException e) {
367 // Local call.
368 }
369 }
370
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100371 private static Handler sHandler = new Handler(Looper.getMainLooper()) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800372
373 @Override
374 public void handleMessage(Message msg) {
375 switch (msg.what) {
376 case MSG_REPORT_DRAW:
377 final boolean hasDrawn;
378 final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
379 synchronized (surface.mService.mWindowMap) {
380 hasDrawn = surface.mHasDrawn;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800381 }
382 if (hasDrawn) {
383 surface.reportDrawn();
384 }
385 break;
386 }
387 }
388 };
389
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200390 @VisibleForTesting
391 static class Window extends BaseIWindow {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800392
393 private TaskSnapshotSurface mOuter;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800394 public void setOuter(TaskSnapshotSurface outer) {
395 mOuter = outer;
396 }
397
398 @Override
399 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
Andrii Kulian44607962017-03-16 11:06:24 -0700400 Rect stableInsets, Rect outsets, boolean reportDraw,
401 MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
402 boolean alwaysConsumeNavBar, int displayId) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800403 if (reportDraw) {
404 sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
405 }
406 }
407 }
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200408
409 /**
410 * Helper class to draw the background of the system bars in regions the task snapshot isn't
411 * filling the window.
412 */
413 static class SystemBarBackgroundPainter {
414
415 private final Rect mContentInsets = new Rect();
416 private final Rect mStableInsets = new Rect();
417 private final Paint mStatusBarPaint = new Paint();
418 private final Paint mNavigationBarPaint = new Paint();
419 private final int mStatusBarColor;
420 private final int mNavigationBarColor;
421 private final int mWindowFlags;
422 private final int mWindowPrivateFlags;
423 private final int mSysUiVis;
424
425 SystemBarBackgroundPainter( int windowFlags, int windowPrivateFlags, int sysUiVis,
426 int statusBarColor, int navigationBarColor) {
427 mWindowFlags = windowFlags;
428 mWindowPrivateFlags = windowPrivateFlags;
429 mSysUiVis = sysUiVis;
430 final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
431 mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
432 context.getColor(R.color.system_bar_background_semi_transparent),
433 statusBarColor);
434 mNavigationBarColor = navigationBarColor;
435 mStatusBarPaint.setColor(mStatusBarColor);
436 mNavigationBarPaint.setColor(navigationBarColor);
437 }
438
439 void setInsets(Rect contentInsets, Rect stableInsets) {
440 mContentInsets.set(contentInsets);
441 mStableInsets.set(stableInsets);
442 }
443
444 int getStatusBarColorViewHeight() {
445 final boolean forceStatusBarBackground =
446 (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
447 if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
448 mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
449 return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
450 } else {
451 return 0;
452 }
453 }
454
455 private boolean isNavigationBarColorViewVisible() {
456 return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
457 mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
458 }
459
460 void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
461 drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
462 drawNavigationBarBackground(c);
463 }
464
465 @VisibleForTesting
466 void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
467 int statusBarHeight) {
468 if (statusBarHeight > 0
469 && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
470 final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
471 mContentInsets.right);
472 final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
473 c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
474 }
475 }
476
477 @VisibleForTesting
478 void drawNavigationBarBackground(Canvas c) {
479 final Rect navigationBarRect = new Rect();
480 getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
481 navigationBarRect);
482 final boolean visible = isNavigationBarColorViewVisible();
483 if (visible && !navigationBarRect.isEmpty()) {
484 c.drawRect(navigationBarRect, mNavigationBarPaint);
485 }
486 }
487 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800488}