blob: 04403e2712c1d0e0b9571e17e59b51b2366fcea3 [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
19import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
20import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
21import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
22import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
23import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
24import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
25import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
28
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010029import android.app.ActivityManager.TaskDescription;
Jorim Jaggi02886a82016-12-06 09:10:06 -080030import android.graphics.Bitmap;
31import android.graphics.Canvas;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010032import android.graphics.Color;
Jorim Jaggi02886a82016-12-06 09:10:06 -080033import android.graphics.GraphicBuffer;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010034import android.graphics.Paint;
Jorim Jaggi02886a82016-12-06 09:10:06 -080035import android.graphics.Rect;
36import android.os.Handler;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010037import android.os.Looper;
Jorim Jaggi02886a82016-12-06 09:10:06 -080038import android.os.Message;
39import android.os.RemoteException;
Andrii Kulian44607962017-03-16 11:06:24 -070040import android.util.MergedConfiguration;
Jorim Jaggi02886a82016-12-06 09:10:06 -080041import android.util.Slog;
Jorim Jaggi02886a82016-12-06 09:10:06 -080042import android.view.IWindowSession;
43import android.view.Surface;
44import android.view.View;
45import android.view.ViewGroup.LayoutParams;
46import android.view.WindowManager;
47import android.view.WindowManagerGlobal;
48import android.view.WindowManagerPolicy.StartingSurface;
49
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010050import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggi02886a82016-12-06 09:10:06 -080051import com.android.internal.view.BaseIWindow;
52
53/**
54 * This class represents a starting window that shows a snapshot.
55 * <p>
56 * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
57 */
58class TaskSnapshotSurface implements StartingSurface {
59
60 private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
61 private static final int MSG_REPORT_DRAW = 0;
62 private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
63 private final Window mWindow;
64 private final Surface mSurface;
65 private final IWindowSession mSession;
66 private final WindowManagerService mService;
67 private boolean mHasDrawn;
68 private boolean mReportNextDraw;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010069 private Paint mFillBackgroundPaint = new Paint();
Jorim Jaggi02886a82016-12-06 09:10:06 -080070
71 static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
72 GraphicBuffer snapshot) {
73
74 final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
75 final Window window = new Window();
76 final IWindowSession session = WindowManagerGlobal.getWindowSession();
77 window.setSession(session);
78 final Surface surface = new Surface();
79 final Rect tmpRect = new Rect();
80 final Rect tmpFrame = new Rect();
Andrii Kulian44607962017-03-16 11:06:24 -070081 final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010082 int fillBackgroundColor = Color.WHITE;
Jorim Jaggi02886a82016-12-06 09:10:06 -080083 synchronized (service.mWindowMap) {
84 layoutParams.type = TYPE_APPLICATION_STARTING;
85 layoutParams.format = snapshot.getFormat();
86 layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
87 | FLAG_LAYOUT_IN_SCREEN
88 | FLAG_NOT_FOCUSABLE
89 | FLAG_NOT_TOUCHABLE
90 | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
91 layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
92 layoutParams.token = token.token;
93 layoutParams.width = LayoutParams.MATCH_PARENT;
94 layoutParams.height = LayoutParams.MATCH_PARENT;
95
96 // TODO: Inherit behavior whether to draw behind status bar/nav bar.
97 layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
98 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Bryce Lee6d410262017-02-28 15:30:17 -080099 final Task task = token.getTask();
100 if (task != null) {
101 layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
102
103 final TaskDescription taskDescription = task.getTaskDescription();
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100104 if (taskDescription != null) {
105 fillBackgroundColor = taskDescription.getBackgroundColor();
106 }
107 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800108 }
109 try {
110 final int res = session.addToDisplay(window, window.mSeq, layoutParams,
111 View.VISIBLE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
112 tmpRect, null);
113 if (res < 0) {
114 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
115 return null;
116 }
117 } catch (RemoteException e) {
118 // Local call.
119 }
120 final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100121 surface, fillBackgroundColor);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800122 window.setOuter(snapshotSurface);
123 try {
124 session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
Andrii Kulian44607962017-03-16 11:06:24 -0700125 tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800126 surface);
127 } catch (RemoteException e) {
128 // Local call.
129 }
130 snapshotSurface.drawSnapshot(snapshot);
131 return snapshotSurface;
132 }
133
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100134 @VisibleForTesting
135 TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
136 int fillBackgroundColor) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800137 mService = service;
138 mSession = WindowManagerGlobal.getWindowSession();
139 mWindow = window;
140 mSurface = surface;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100141 mFillBackgroundPaint.setColor(fillBackgroundColor);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800142 }
143
144 @Override
145 public void remove() {
146 try {
147 mSession.remove(mWindow);
148 } catch (RemoteException e) {
149 // Local call.
150 }
151 }
152
153 private void drawSnapshot(GraphicBuffer snapshot) {
Robert Carra35e5de2017-03-03 17:04:54 -0800154 mSurface.attachAndQueueBuffer(snapshot);
Jorim Jaggi39367cf2017-03-13 16:41:13 +0100155 final boolean reportNextDraw;
156 synchronized (mService.mWindowMap) {
157 mHasDrawn = true;
158 reportNextDraw = mReportNextDraw;
159 }
160 if (reportNextDraw) {
161 reportDrawn();
162 }
Jorim Jaggi2f24b652017-01-18 02:17:37 +0100163 mSurface.release();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800164 }
165
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100166 @VisibleForTesting
167 void fillEmptyBackground(Canvas c, Bitmap b) {
168 final boolean fillHorizontally = c.getWidth() > b.getWidth();
169 final boolean fillVertically = c.getHeight() > b.getHeight();
170 if (fillHorizontally) {
171 c.drawRect(b.getWidth(), 0, c.getWidth(), fillVertically
172 ? b.getHeight()
173 : c.getHeight(),
174 mFillBackgroundPaint);
175 }
176 if (fillVertically) {
177 c.drawRect(0, b.getHeight(), c.getWidth(), c.getHeight(), mFillBackgroundPaint);
178 }
179 }
180
Jorim Jaggi02886a82016-12-06 09:10:06 -0800181 private void reportDrawn() {
182 synchronized (mService.mWindowMap) {
183 mReportNextDraw = false;
184 }
185 try {
186 mSession.finishDrawing(mWindow);
187 } catch (RemoteException e) {
188 // Local call.
189 }
190 }
191
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100192 private static Handler sHandler = new Handler(Looper.getMainLooper()) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800193
194 @Override
195 public void handleMessage(Message msg) {
196 switch (msg.what) {
197 case MSG_REPORT_DRAW:
198 final boolean hasDrawn;
199 final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
200 synchronized (surface.mService.mWindowMap) {
201 hasDrawn = surface.mHasDrawn;
202 if (!hasDrawn) {
203 surface.mReportNextDraw = true;
204 }
205 }
206 if (hasDrawn) {
207 surface.reportDrawn();
208 }
209 break;
210 }
211 }
212 };
213
214 private static class Window extends BaseIWindow {
215
216 private TaskSnapshotSurface mOuter;
217
218 public void setOuter(TaskSnapshotSurface outer) {
219 mOuter = outer;
220 }
221
222 @Override
223 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
Andrii Kulian44607962017-03-16 11:06:24 -0700224 Rect stableInsets, Rect outsets, boolean reportDraw,
225 MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
226 boolean alwaysConsumeNavBar, int displayId) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800227 if (reportDraw) {
228 sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
229 }
230 }
231 }
232}