blob: a2891e97f5216ccb0d1f451a2465d449d5cd702a [file] [log] [blame]
Svetoslav8e3feb12014-02-24 13:46:47 -08001/*
2 * Copyright (C) 2014 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
Vishnu Naire86bd982018-11-28 13:23:17 -080019import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
Phil Weaverb2779532017-12-18 17:09:32 -080020import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Phil Weaverd321075e2017-06-13 09:13:35 -070021import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
Phil Weaverd321075e2017-06-13 09:13:35 -070022
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080023import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
25
Svetoslav8e3feb12014-02-24 13:46:47 -080026import android.animation.ObjectAnimator;
27import android.animation.ValueAnimator;
Alan Viverette59e53a12016-03-28 13:41:32 -040028import android.annotation.NonNull;
Svetoslav8e3feb12014-02-24 13:46:47 -080029import android.app.Service;
30import android.content.Context;
31import android.graphics.Canvas;
32import android.graphics.Color;
33import android.graphics.Matrix;
34import android.graphics.Paint;
35import android.graphics.Path;
36import android.graphics.PixelFormat;
37import android.graphics.Point;
38import android.graphics.PorterDuff.Mode;
39import android.graphics.Rect;
40import android.graphics.RectF;
41import android.graphics.Region;
42import android.os.Handler;
43import android.os.IBinder;
44import android.os.Looper;
45import android.os.Message;
46import android.util.ArraySet;
Svetoslav8e3feb12014-02-24 13:46:47 -080047import android.util.Slog;
48import android.util.SparseArray;
49import android.util.TypedValue;
Rhed Jao02655dc2018-10-30 20:44:52 +080050import android.view.Display;
Svetoslav8e3feb12014-02-24 13:46:47 -080051import android.view.MagnificationSpec;
52import android.view.Surface;
53import android.view.Surface.OutOfResourcesException;
54import android.view.SurfaceControl;
Svetoslavf7174e82014-06-12 11:29:35 -070055import android.view.ViewConfiguration;
Svetoslav8e3feb12014-02-24 13:46:47 -080056import android.view.WindowInfo;
57import android.view.WindowManager;
Svetoslav8e3feb12014-02-24 13:46:47 -080058import android.view.animation.DecelerateInterpolator;
59import android.view.animation.Interpolator;
60
61import com.android.internal.R;
62import com.android.internal.os.SomeArgs;
Adrian Roose99bc052017-11-20 17:55:31 +010063import com.android.server.policy.WindowManagerPolicy;
64import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
65import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback;
Svetoslav8e3feb12014-02-24 13:46:47 -080066
67import java.util.ArrayList;
Allen Hairf20ac2c2016-02-11 17:42:59 -080068import java.util.HashSet;
Svetoslav8e3feb12014-02-24 13:46:47 -080069import java.util.List;
70import java.util.Set;
71
72/**
kopriva82c591b2018-10-08 15:57:00 -070073 * This class contains the accessibility related logic of the window manager.
Svetoslav8e3feb12014-02-24 13:46:47 -080074 */
75final class AccessibilityController {
76
Robert Carre625fcf2017-09-01 12:36:28 -070077 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -080078
79 private static final float[] sTempFloats = new float[9];
80
81 public AccessibilityController(WindowManagerService service) {
Robert Carre625fcf2017-09-01 12:36:28 -070082 mService = service;
Svetoslav8e3feb12014-02-24 13:46:47 -080083 }
84
Rhed Jao02655dc2018-10-30 20:44:52 +080085 private SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
Svetoslav8e3feb12014-02-24 13:46:47 -080086
87 private WindowsForAccessibilityObserver mWindowsForAccessibilityObserver;
88
Rhed Jao02655dc2018-10-30 20:44:52 +080089 public boolean setMagnificationCallbacksLocked(int displayId,
90 MagnificationCallbacks callbacks) {
91 boolean result = false;
Svetoslav8e3feb12014-02-24 13:46:47 -080092 if (callbacks != null) {
Rhed Jao02655dc2018-10-30 20:44:52 +080093 if (mDisplayMagnifiers.get(displayId) != null) {
Svetoslav8e3feb12014-02-24 13:46:47 -080094 throw new IllegalStateException("Magnification callbacks already set!");
95 }
Rhed Jao02655dc2018-10-30 20:44:52 +080096 final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
97 if (dc != null) {
98 final Display display = dc.getDisplay();
99 if (display != null && display.getType() != Display.TYPE_OVERLAY) {
100 mDisplayMagnifiers.put(displayId, new DisplayMagnifier(
101 mService, dc, display, callbacks));
102 result = true;
103 }
104 }
Svetoslav8e3feb12014-02-24 13:46:47 -0800105 } else {
Rhed Jao02655dc2018-10-30 20:44:52 +0800106 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
107 if (displayMagnifier == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800108 throw new IllegalStateException("Magnification callbacks already cleared!");
109 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800110 displayMagnifier.destroyLocked();
111 mDisplayMagnifiers.remove(displayId);
112 result = true;
Svetoslav8e3feb12014-02-24 13:46:47 -0800113 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800114 return result;
Svetoslav8e3feb12014-02-24 13:46:47 -0800115 }
116
117 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
118 if (callback != null) {
119 if (mWindowsForAccessibilityObserver != null) {
120 throw new IllegalStateException(
121 "Windows for accessibility callback already set!");
122 }
123 mWindowsForAccessibilityObserver = new WindowsForAccessibilityObserver(
Robert Carre625fcf2017-09-01 12:36:28 -0700124 mService, callback);
Svetoslav8e3feb12014-02-24 13:46:47 -0800125 } else {
126 if (mWindowsForAccessibilityObserver == null) {
127 throw new IllegalStateException(
128 "Windows for accessibility callback already cleared!");
129 }
130 mWindowsForAccessibilityObserver = null;
131 }
132 }
133
Phil Weaverc72faad2018-07-24 10:53:01 -0700134 public void performComputeChangedWindowsNotLocked(boolean forceSend) {
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700135 WindowsForAccessibilityObserver observer = null;
Robert Carre625fcf2017-09-01 12:36:28 -0700136 synchronized (mService) {
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700137 observer = mWindowsForAccessibilityObserver;
138 }
139 if (observer != null) {
Phil Weaverc72faad2018-07-24 10:53:01 -0700140 observer.performComputeChangedWindowsNotLocked(forceSend);
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700141 }
142 }
143
Rhed Jao02655dc2018-10-30 20:44:52 +0800144 public void setMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
145 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
146 if (displayMagnifier != null) {
147 displayMagnifier.setMagnificationSpecLocked(spec);
Svetoslav8e3feb12014-02-24 13:46:47 -0800148 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800149 // TODO: support multi-display for windows observer
150 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700151 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800152 }
153 }
154
Rhed Jao02655dc2018-10-30 20:44:52 +0800155 public void getMagnificationRegionLocked(int displayId, Region outMagnificationRegion) {
156 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
157 if (displayMagnifier != null) {
158 displayMagnifier.getMagnificationRegionLocked(outMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400159 }
160 }
161
Rhed Jao02655dc2018-10-30 20:44:52 +0800162 public void onRectangleOnScreenRequestedLocked(int displayId, Rect rectangle) {
163 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
164 if (displayMagnifier != null) {
165 displayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
Svetoslav8e3feb12014-02-24 13:46:47 -0800166 }
167 // Not relevant for the window observer.
168 }
169
Rhed Jao02655dc2018-10-30 20:44:52 +0800170 public void onWindowLayersChangedLocked(int displayId) {
171 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
172 if (displayMagnifier != null) {
173 displayMagnifier.onWindowLayersChangedLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800174 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800175 // TODO: support multi-display for windows observer
176 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700177 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800178 }
179 }
180
Andrii Kulian8ee72852017-03-10 10:36:45 -0800181 public void onRotationChangedLocked(DisplayContent displayContent) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800182 final int displayId = displayContent.getDisplayId();
183 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
184 if (displayMagnifier != null) {
185 displayMagnifier.onRotationChangedLocked(displayContent);
Svetoslav8e3feb12014-02-24 13:46:47 -0800186 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800187 // TODO: support multi-display for windows observer
188 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700189 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800190 }
191 }
192
193 public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800194 final int displayId = windowState.getDisplayId();
195 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
196 if (displayMagnifier != null) {
197 displayMagnifier.onAppWindowTransitionLocked(windowState, transition);
Svetoslav8e3feb12014-02-24 13:46:47 -0800198 }
199 // Not relevant for the window observer.
200 }
201
202 public void onWindowTransitionLocked(WindowState windowState, int transition) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800203 final int displayId = windowState.getDisplayId();
204 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
205 if (displayMagnifier != null) {
206 displayMagnifier.onWindowTransitionLocked(windowState, transition);
Svetoslav8e3feb12014-02-24 13:46:47 -0800207 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800208 // TODO: support multi-display for windows observer
209 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700210 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800211 }
212 }
213
Svetoslav3a0d8782014-12-04 12:50:11 -0800214 public void onWindowFocusChangedNotLocked() {
Svetoslav8e3feb12014-02-24 13:46:47 -0800215 // Not relevant for the display magnifier.
216
Svetoslav3a0d8782014-12-04 12:50:11 -0800217 WindowsForAccessibilityObserver observer = null;
Robert Carre625fcf2017-09-01 12:36:28 -0700218 synchronized (mService) {
Svetoslav3a0d8782014-12-04 12:50:11 -0800219 observer = mWindowsForAccessibilityObserver;
220 }
221 if (observer != null) {
Phil Weaverc72faad2018-07-24 10:53:01 -0700222 observer.performComputeChangedWindowsNotLocked(false);
Svetoslav8e3feb12014-02-24 13:46:47 -0800223 }
224 }
225
Svetoslavf7174e82014-06-12 11:29:35 -0700226 public void onSomeWindowResizedOrMovedLocked() {
Svetoslav4604abc2014-06-10 18:59:30 -0700227 // Not relevant for the display magnifier.
228
229 if (mWindowsForAccessibilityObserver != null) {
Svetoslavf7174e82014-06-12 11:29:35 -0700230 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav4604abc2014-06-10 18:59:30 -0700231 }
232 }
233
Svetoslav8e3feb12014-02-24 13:46:47 -0800234 /** NOTE: This has to be called within a surface transaction. */
Rhed Jao02655dc2018-10-30 20:44:52 +0800235 public void drawMagnifiedRegionBorderIfNeededLocked(int displayId) {
236 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
237 if (displayMagnifier != null) {
238 displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800239 }
240 // Not relevant for the window observer.
241 }
242
243 public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800244 final int displayId = windowState.getDisplayId();
245 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
246 if (displayMagnifier != null) {
247 return displayMagnifier.getMagnificationSpecForWindowLocked(windowState);
Svetoslav8e3feb12014-02-24 13:46:47 -0800248 }
249 return null;
250 }
251
252 public boolean hasCallbacksLocked() {
Rhed Jao02655dc2018-10-30 20:44:52 +0800253 // TODO: support multi-display for windows observer
254 return (mDisplayMagnifiers.size() > 0
Svetoslav8e3feb12014-02-24 13:46:47 -0800255 || mWindowsForAccessibilityObserver != null);
256 }
257
Rhed Jao02655dc2018-10-30 20:44:52 +0800258 public void setForceShowMagnifiableBoundsLocked(int displayId, boolean show) {
259 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
260 if (displayMagnifier != null) {
261 displayMagnifier.setForceShowMagnifiableBoundsLocked(show);
262 displayMagnifier.showMagnificationBoundsIfNeeded();
Casey Burkhardt74922c62017-02-13 12:43:16 -0800263 }
264 }
265
Svetoslav8e3feb12014-02-24 13:46:47 -0800266 private static void populateTransformationMatrixLocked(WindowState windowState,
267 Matrix outMatrix) {
Jorim Jaggieb0d3bc2017-12-15 14:56:19 +0100268 windowState.getTransformationMatrix(sTempFloats, outMatrix);
Svetoslav8e3feb12014-02-24 13:46:47 -0800269 }
270
271 /**
272 * This class encapsulates the functionality related to display magnification.
273 */
274 private static final class DisplayMagnifier {
275
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800276 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ? "DisplayMagnifier" : TAG_WM;
Svetoslav8e3feb12014-02-24 13:46:47 -0800277
278 private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
279 private static final boolean DEBUG_ROTATION = false;
280 private static final boolean DEBUG_LAYERS = false;
281 private static final boolean DEBUG_RECTANGLE_REQUESTED = false;
282 private static final boolean DEBUG_VIEWPORT_WINDOW = false;
283
284 private final Rect mTempRect1 = new Rect();
285 private final Rect mTempRect2 = new Rect();
286
287 private final Region mTempRegion1 = new Region();
288 private final Region mTempRegion2 = new Region();
289 private final Region mTempRegion3 = new Region();
290 private final Region mTempRegion4 = new Region();
291
292 private final Context mContext;
Robert Carre625fcf2017-09-01 12:36:28 -0700293 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -0800294 private final MagnifiedViewport mMagnifedViewport;
295 private final Handler mHandler;
Rhed Jao02655dc2018-10-30 20:44:52 +0800296 private final DisplayContent mDisplayContent;
297 private final Display mDisplay;
Svetoslav8e3feb12014-02-24 13:46:47 -0800298
299 private final MagnificationCallbacks mCallbacks;
300
301 private final long mLongAnimationDuration;
302
Casey Burkhardt74922c62017-02-13 12:43:16 -0800303 private boolean mForceShowMagnifiableBounds = false;
304
Svetoslav8e3feb12014-02-24 13:46:47 -0800305 public DisplayMagnifier(WindowManagerService windowManagerService,
Rhed Jao02655dc2018-10-30 20:44:52 +0800306 DisplayContent displayContent,
307 Display display,
Svetoslav8e3feb12014-02-24 13:46:47 -0800308 MagnificationCallbacks callbacks) {
309 mContext = windowManagerService.mContext;
Robert Carre625fcf2017-09-01 12:36:28 -0700310 mService = windowManagerService;
Svetoslav8e3feb12014-02-24 13:46:47 -0800311 mCallbacks = callbacks;
Rhed Jao02655dc2018-10-30 20:44:52 +0800312 mDisplayContent = displayContent;
313 mDisplay = display;
Robert Carre625fcf2017-09-01 12:36:28 -0700314 mHandler = new MyHandler(mService.mH.getLooper());
Svetoslav8e3feb12014-02-24 13:46:47 -0800315 mMagnifedViewport = new MagnifiedViewport();
316 mLongAnimationDuration = mContext.getResources().getInteger(
317 com.android.internal.R.integer.config_longAnimTime);
318 }
319
320 public void setMagnificationSpecLocked(MagnificationSpec spec) {
321 mMagnifedViewport.updateMagnificationSpecLocked(spec);
322 mMagnifedViewport.recomputeBoundsLocked();
Robert Carrb1579c82017-09-05 14:54:47 -0700323
Rhed Jao02655dc2018-10-30 20:44:52 +0800324 mService.applyMagnificationSpecLocked(mDisplay.getDisplayId(), spec);
Robert Carre625fcf2017-09-01 12:36:28 -0700325 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800326 }
327
Casey Burkhardt74922c62017-02-13 12:43:16 -0800328 public void setForceShowMagnifiableBoundsLocked(boolean show) {
329 mForceShowMagnifiableBounds = show;
330 mMagnifedViewport.setMagnifiedRegionBorderShownLocked(show, true);
331 }
332
333 public boolean isForceShowingMagnifiableBoundsLocked() {
334 return mForceShowMagnifiableBounds;
335 }
336
Svetoslavf7174e82014-06-12 11:29:35 -0700337 public void onRectangleOnScreenRequestedLocked(Rect rectangle) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800338 if (DEBUG_RECTANGLE_REQUESTED) {
339 Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle);
340 }
341 if (!mMagnifedViewport.isMagnifyingLocked()) {
342 return;
343 }
344 Rect magnifiedRegionBounds = mTempRect2;
345 mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(magnifiedRegionBounds);
346 if (magnifiedRegionBounds.contains(rectangle)) {
347 return;
348 }
349 SomeArgs args = SomeArgs.obtain();
350 args.argi1 = rectangle.left;
351 args.argi2 = rectangle.top;
352 args.argi3 = rectangle.right;
353 args.argi4 = rectangle.bottom;
354 mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED,
355 args).sendToTarget();
356 }
357
358 public void onWindowLayersChangedLocked() {
359 if (DEBUG_LAYERS) {
360 Slog.i(LOG_TAG, "Layers changed.");
361 }
362 mMagnifedViewport.recomputeBoundsLocked();
Robert Carre625fcf2017-09-01 12:36:28 -0700363 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800364 }
365
Andrii Kulian8ee72852017-03-10 10:36:45 -0800366 public void onRotationChangedLocked(DisplayContent displayContent) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800367 if (DEBUG_ROTATION) {
Andrii Kulian8ee72852017-03-10 10:36:45 -0800368 final int rotation = displayContent.getRotation();
369 Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
Svetoslav8e3feb12014-02-24 13:46:47 -0800370 + " displayId: " + displayContent.getDisplayId());
371 }
372 mMagnifedViewport.onRotationChangedLocked();
373 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
374 }
375
376 public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
377 if (DEBUG_WINDOW_TRANSITIONS) {
378 Slog.i(LOG_TAG, "Window transition: "
379 + AppTransition.appTransitionToString(transition)
380 + " displayId: " + windowState.getDisplayId());
381 }
382 final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
383 if (magnifying) {
384 switch (transition) {
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100385 case WindowManager.TRANSIT_ACTIVITY_OPEN:
386 case WindowManager.TRANSIT_TASK_OPEN:
387 case WindowManager.TRANSIT_TASK_TO_FRONT:
388 case WindowManager.TRANSIT_WALLPAPER_OPEN:
389 case WindowManager.TRANSIT_WALLPAPER_CLOSE:
390 case WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN: {
Svetoslav8e3feb12014-02-24 13:46:47 -0800391 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
392 }
393 }
394 }
395 }
396
397 public void onWindowTransitionLocked(WindowState windowState, int transition) {
398 if (DEBUG_WINDOW_TRANSITIONS) {
399 Slog.i(LOG_TAG, "Window transition: "
400 + AppTransition.appTransitionToString(transition)
401 + " displayId: " + windowState.getDisplayId());
402 }
403 final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
404 final int type = windowState.mAttrs.type;
405 switch (transition) {
406 case WindowManagerPolicy.TRANSIT_ENTER:
407 case WindowManagerPolicy.TRANSIT_SHOW: {
408 if (!magnifying) {
409 break;
410 }
411 switch (type) {
412 case WindowManager.LayoutParams.TYPE_APPLICATION:
Chong Zhangfea963e2016-08-15 17:14:16 -0700413 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
Svetoslav8e3feb12014-02-24 13:46:47 -0800414 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
415 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
416 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
Wale Ogunwale0a4dc222015-04-14 12:58:42 -0700417 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
Svetoslav8e3feb12014-02-24 13:46:47 -0800418 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
419 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
420 case WindowManager.LayoutParams.TYPE_PHONE:
421 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
422 case WindowManager.LayoutParams.TYPE_TOAST:
423 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800424 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
Svetoslav8e3feb12014-02-24 13:46:47 -0800425 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
426 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
427 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
428 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
429 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
Jason Monk8f7f3182015-11-18 16:35:14 -0500430 case WindowManager.LayoutParams.TYPE_QS_DIALOG:
Adrian Roos9a645132014-10-08 02:59:56 +0200431 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: {
Svetoslav8e3feb12014-02-24 13:46:47 -0800432 Rect magnifiedRegionBounds = mTempRect2;
433 mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(
434 magnifiedRegionBounds);
435 Rect touchableRegionBounds = mTempRect1;
436 windowState.getTouchableRegion(mTempRegion1);
437 mTempRegion1.getBounds(touchableRegionBounds);
438 if (!magnifiedRegionBounds.intersect(touchableRegionBounds)) {
439 mCallbacks.onRectangleOnScreenRequested(
440 touchableRegionBounds.left,
441 touchableRegionBounds.top,
442 touchableRegionBounds.right,
443 touchableRegionBounds.bottom);
444 }
445 } break;
446 } break;
447 }
448 }
449 }
450
451 public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
452 MagnificationSpec spec = mMagnifedViewport.getMagnificationSpecLocked();
453 if (spec != null && !spec.isNop()) {
Robert Carrb1579c82017-09-05 14:54:47 -0700454 if (!windowState.shouldMagnify()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800455 return null;
456 }
457 }
458 return spec;
459 }
460
Phil Weaver70439242016-03-10 15:15:49 -0800461 public void getMagnificationRegionLocked(Region outMagnificationRegion) {
Phil Weaver53b690b2017-08-14 17:42:39 -0700462 // Make sure we're working with the most current bounds
463 mMagnifedViewport.recomputeBoundsLocked();
Phil Weaver70439242016-03-10 15:15:49 -0800464 mMagnifedViewport.getMagnificationRegionLocked(outMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400465 }
466
Svetoslav8e3feb12014-02-24 13:46:47 -0800467 public void destroyLocked() {
468 mMagnifedViewport.destroyWindow();
469 }
470
Phil Weaver251db072017-03-28 08:35:38 -0700471 // Can be called outside of a surface transaction
472 public void showMagnificationBoundsIfNeeded() {
473 mHandler.obtainMessage(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)
474 .sendToTarget();
475 }
476
Svetoslav8e3feb12014-02-24 13:46:47 -0800477 /** NOTE: This has to be called within a surface transaction. */
478 public void drawMagnifiedRegionBorderIfNeededLocked() {
479 mMagnifedViewport.drawWindowIfNeededLocked();
480 }
481
482 private final class MagnifiedViewport {
483
Svetoslav8e3feb12014-02-24 13:46:47 -0800484 private final SparseArray<WindowState> mTempWindowStates =
485 new SparseArray<WindowState>();
486
487 private final RectF mTempRectF = new RectF();
488
489 private final Point mTempPoint = new Point();
490
491 private final Matrix mTempMatrix = new Matrix();
492
Phil Weaver70439242016-03-10 15:15:49 -0800493 private final Region mMagnificationRegion = new Region();
494 private final Region mOldMagnificationRegion = new Region();
Svetoslav8e3feb12014-02-24 13:46:47 -0800495
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800496 private final Path mCircularPath;
497
Svetoslav8e3feb12014-02-24 13:46:47 -0800498 private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain();
499
500 private final WindowManager mWindowManager;
501
Svetoslav7505e332014-08-22 12:14:28 -0700502 private final float mBorderWidth;
Svetoslav8e3feb12014-02-24 13:46:47 -0800503 private final int mHalfBorderWidth;
Svetoslav7505e332014-08-22 12:14:28 -0700504 private final int mDrawBorderInset;
Svetoslav8e3feb12014-02-24 13:46:47 -0800505
506 private final ViewportWindow mWindow;
507
508 private boolean mFullRedrawNeeded;
Robert Carrb1579c82017-09-05 14:54:47 -0700509 private int mTempLayer = 0;
Svetoslav8e3feb12014-02-24 13:46:47 -0800510
511 public MagnifiedViewport() {
512 mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800513 mBorderWidth = mContext.getResources().getDimension(
514 com.android.internal.R.dimen.accessibility_magnification_indicator_width);
Svetoslav7505e332014-08-22 12:14:28 -0700515 mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
516 mDrawBorderInset = (int) mBorderWidth / 2;
Svetoslav8e3feb12014-02-24 13:46:47 -0800517 mWindow = new ViewportWindow(mContext);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800518
Adam Powell01f280d2015-05-18 16:07:42 -0700519 if (mContext.getResources().getConfiguration().isScreenRound()) {
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800520 mCircularPath = new Path();
Rhed Jao02655dc2018-10-30 20:44:52 +0800521 mDisplay.getRealSize(mTempPoint);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800522 final int centerXY = mTempPoint.x / 2;
523 mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
524 } else {
525 mCircularPath = null;
526 }
527
Svetoslav8e3feb12014-02-24 13:46:47 -0800528 recomputeBoundsLocked();
529 }
530
Phil Weaver70439242016-03-10 15:15:49 -0800531 public void getMagnificationRegionLocked(@NonNull Region outMagnificationRegion) {
532 outMagnificationRegion.set(mMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400533 }
534
Svetoslav8e3feb12014-02-24 13:46:47 -0800535 public void updateMagnificationSpecLocked(MagnificationSpec spec) {
536 if (spec != null) {
537 mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY);
538 } else {
539 mMagnificationSpec.clear();
540 }
541 // If this message is pending we are in a rotation animation and do not want
542 // to show the border. We will do so when the pending message is handled.
Svetoslav7505e332014-08-22 12:14:28 -0700543 if (!mHandler.hasMessages(
544 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800545 setMagnifiedRegionBorderShownLocked(
546 isMagnifyingLocked() || isForceShowingMagnifiableBoundsLocked(), true);
Svetoslav8e3feb12014-02-24 13:46:47 -0800547 }
548 }
549
550 public void recomputeBoundsLocked() {
Rhed Jao02655dc2018-10-30 20:44:52 +0800551 mDisplay.getRealSize(mTempPoint);
Svetoslav8e3feb12014-02-24 13:46:47 -0800552 final int screenWidth = mTempPoint.x;
553 final int screenHeight = mTempPoint.y;
554
Phil Weaver70439242016-03-10 15:15:49 -0800555 mMagnificationRegion.set(0, 0, 0, 0);
556 final Region availableBounds = mTempRegion1;
557 availableBounds.set(0, 0, screenWidth, screenHeight);
Svetoslav8e3feb12014-02-24 13:46:47 -0800558
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800559 if (mCircularPath != null) {
Phil Weaver70439242016-03-10 15:15:49 -0800560 availableBounds.setPath(mCircularPath, availableBounds);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800561 }
562
Svetoslav8e3feb12014-02-24 13:46:47 -0800563 Region nonMagnifiedBounds = mTempRegion4;
Svet Ganovb21df802014-09-01 19:06:33 -0700564 nonMagnifiedBounds.set(0, 0, 0, 0);
Svetoslav8e3feb12014-02-24 13:46:47 -0800565
566 SparseArray<WindowState> visibleWindows = mTempWindowStates;
567 visibleWindows.clear();
568 populateWindowsOnScreenLocked(visibleWindows);
569
570 final int visibleWindowCount = visibleWindows.size();
571 for (int i = visibleWindowCount - 1; i >= 0; i--) {
572 WindowState windowState = visibleWindows.valueAt(i);
Phil Weaverd321075e2017-06-13 09:13:35 -0700573 if ((windowState.mAttrs.type == TYPE_MAGNIFICATION_OVERLAY)
574 || ((windowState.mAttrs.privateFlags
Robert Carr132c9f52017-07-31 17:02:30 -0700575 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0)) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800576 continue;
577 }
578
Phil Weaver65c06702016-03-15 15:33:46 -0700579 // Consider the touchable portion of the window
Svetoslav8e3feb12014-02-24 13:46:47 -0800580 Matrix matrix = mTempMatrix;
581 populateTransformationMatrixLocked(windowState, matrix);
Phil Weaver65c06702016-03-15 15:33:46 -0700582 Region touchableRegion = mTempRegion3;
583 windowState.getTouchableRegion(touchableRegion);
584 Rect touchableFrame = mTempRect1;
585 touchableRegion.getBounds(touchableFrame);
Svetoslav8e3feb12014-02-24 13:46:47 -0800586 RectF windowFrame = mTempRectF;
Phil Weaver65c06702016-03-15 15:33:46 -0700587 windowFrame.set(touchableFrame);
chaviw492139a2018-07-16 16:07:35 -0700588 windowFrame.offset(-windowState.getFrameLw().left,
589 -windowState.getFrameLw().top);
Phil Weaver65c06702016-03-15 15:33:46 -0700590 matrix.mapRect(windowFrame);
591 Region windowBounds = mTempRegion2;
592 windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
593 (int) windowFrame.right, (int) windowFrame.bottom);
594 // Only update new regions
595 Region portionOfWindowAlreadyAccountedFor = mTempRegion3;
Phil Weaver70439242016-03-10 15:15:49 -0800596 portionOfWindowAlreadyAccountedFor.set(mMagnificationRegion);
Phil Weaver65c06702016-03-15 15:33:46 -0700597 portionOfWindowAlreadyAccountedFor.op(nonMagnifiedBounds, Region.Op.UNION);
598 windowBounds.op(portionOfWindowAlreadyAccountedFor, Region.Op.DIFFERENCE);
Svetoslav8e3feb12014-02-24 13:46:47 -0800599
Robert Carrb1579c82017-09-05 14:54:47 -0700600 if (windowState.shouldMagnify()) {
Phil Weaver70439242016-03-10 15:15:49 -0800601 mMagnificationRegion.op(windowBounds, Region.Op.UNION);
602 mMagnificationRegion.op(availableBounds, Region.Op.INTERSECT);
Svetoslav8e3feb12014-02-24 13:46:47 -0800603 } else {
Svetoslav8e3feb12014-02-24 13:46:47 -0800604 nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
Phil Weaver70439242016-03-10 15:15:49 -0800605 availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
Svetoslav8e3feb12014-02-24 13:46:47 -0800606 }
607
Jackal Guoc2e12c42019-02-27 17:06:33 +0800608 // Count letterbox into nonMagnifiedBounds
609 if (windowState.isLetterboxedForDisplayCutoutLw()) {
610 Region letterboxBounds = getLetterboxBounds(windowState);
611 nonMagnifiedBounds.op(letterboxBounds, Region.Op.UNION);
612 availableBounds.op(letterboxBounds, Region.Op.DIFFERENCE);
613 }
614
Phil Weaver65c06702016-03-15 15:33:46 -0700615 // Update accounted bounds
Svetoslav8e3feb12014-02-24 13:46:47 -0800616 Region accountedBounds = mTempRegion2;
Phil Weaver70439242016-03-10 15:15:49 -0800617 accountedBounds.set(mMagnificationRegion);
Svetoslav8e3feb12014-02-24 13:46:47 -0800618 accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
619 accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
620
621 if (accountedBounds.isRect()) {
622 Rect accountedFrame = mTempRect1;
623 accountedBounds.getBounds(accountedFrame);
624 if (accountedFrame.width() == screenWidth
625 && accountedFrame.height() == screenHeight) {
626 break;
627 }
628 }
629 }
630
631 visibleWindows.clear();
632
Phil Weaver70439242016-03-10 15:15:49 -0800633 mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
Svetoslav7505e332014-08-22 12:14:28 -0700634 screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
Svetoslav8e3feb12014-02-24 13:46:47 -0800635 Region.Op.INTERSECT);
636
Phil Weaver70439242016-03-10 15:15:49 -0800637 final boolean magnifiedChanged =
638 !mOldMagnificationRegion.equals(mMagnificationRegion);
639 if (magnifiedChanged) {
640 mWindow.setBounds(mMagnificationRegion);
641 final Rect dirtyRect = mTempRect1;
642 if (mFullRedrawNeeded) {
643 mFullRedrawNeeded = false;
644 dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
645 screenWidth - mDrawBorderInset,
646 screenHeight - mDrawBorderInset);
647 mWindow.invalidate(dirtyRect);
648 } else {
649 final Region dirtyRegion = mTempRegion3;
650 dirtyRegion.set(mMagnificationRegion);
651 dirtyRegion.op(mOldMagnificationRegion, Region.Op.UNION);
652 dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
653 dirtyRegion.getBounds(dirtyRect);
654 mWindow.invalidate(dirtyRect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800655 }
656
Phil Weaver70439242016-03-10 15:15:49 -0800657 mOldMagnificationRegion.set(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500658 final SomeArgs args = SomeArgs.obtain();
Phil Weaver70439242016-03-10 15:15:49 -0800659 args.arg1 = Region.obtain(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500660 mHandler.obtainMessage(
Phil Weaver70439242016-03-10 15:15:49 -0800661 MyHandler.MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED, args)
662 .sendToTarget();
Svetoslav8e3feb12014-02-24 13:46:47 -0800663 }
664 }
665
Jackal Guoc2e12c42019-02-27 17:06:33 +0800666 private Region getLetterboxBounds(WindowState windowState) {
667 final AppWindowToken appToken = windowState.mAppToken;
668 if (appToken == null) {
669 return new Region();
670 }
671
672 mDisplay.getRealSize(mTempPoint);
673 final Rect letterboxInsets = appToken.getLetterboxInsets();
674 final int screenWidth = mTempPoint.x;
675 final int screenHeight = mTempPoint.y;
676 final Rect nonLetterboxRect = mTempRect1;
677 final Region letterboxBounds = mTempRegion3;
678 nonLetterboxRect.set(0, 0, screenWidth, screenHeight);
679 nonLetterboxRect.inset(letterboxInsets);
680 letterboxBounds.set(0, 0, screenWidth, screenHeight);
681 letterboxBounds.op(nonLetterboxRect, Region.Op.DIFFERENCE);
682 return letterboxBounds;
683 }
684
Svetoslav8e3feb12014-02-24 13:46:47 -0800685 public void onRotationChangedLocked() {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800686 // If we are showing the magnification border, hide it immediately so
Svetoslav8e3feb12014-02-24 13:46:47 -0800687 // the user does not see strange artifacts during rotation. The screenshot
Casey Burkhardt74922c62017-02-13 12:43:16 -0800688 // used for rotation already has the border. After the rotation is complete
Svetoslav8e3feb12014-02-24 13:46:47 -0800689 // we will show the border.
Casey Burkhardt74922c62017-02-13 12:43:16 -0800690 if (isMagnifyingLocked() || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800691 setMagnifiedRegionBorderShownLocked(false, false);
692 final long delay = (long) (mLongAnimationDuration
Robert Carre625fcf2017-09-01 12:36:28 -0700693 * mService.getWindowAnimationScaleLocked());
Svetoslav8e3feb12014-02-24 13:46:47 -0800694 Message message = mHandler.obtainMessage(
695 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED);
696 mHandler.sendMessageDelayed(message, delay);
697 }
698 recomputeBoundsLocked();
699 mWindow.updateSize();
700 }
701
702 public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
703 if (shown) {
704 mFullRedrawNeeded = true;
Phil Weaver70439242016-03-10 15:15:49 -0800705 mOldMagnificationRegion.set(0, 0, 0, 0);
Svetoslav8e3feb12014-02-24 13:46:47 -0800706 }
707 mWindow.setShown(shown, animate);
708 }
709
710 public void getMagnifiedFrameInContentCoordsLocked(Rect rect) {
711 MagnificationSpec spec = mMagnificationSpec;
Phil Weaver70439242016-03-10 15:15:49 -0800712 mMagnificationRegion.getBounds(rect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800713 rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
714 rect.scale(1.0f / spec.scale);
715 }
716
717 public boolean isMagnifyingLocked() {
718 return mMagnificationSpec.scale > 1.0f;
719 }
720
721 public MagnificationSpec getMagnificationSpecLocked() {
722 return mMagnificationSpec;
723 }
724
725 /** NOTE: This has to be called within a surface transaction. */
726 public void drawWindowIfNeededLocked() {
727 recomputeBoundsLocked();
728 mWindow.drawIfNeeded();
729 }
730
731 public void destroyWindow() {
732 mWindow.releaseSurface();
733 }
734
735 private void populateWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Robert Carrb1579c82017-09-05 14:54:47 -0700736 mTempLayer = 0;
Rhed Jao02655dc2018-10-30 20:44:52 +0800737 mDisplayContent.forAllWindows((w) -> {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800738 if (w.isOnScreen() && w.isVisibleLw()
Phil Weaverd6ce7372018-05-18 09:48:01 -0700739 && (w.mAttrs.alpha != 0)
Wale Ogunwaled1880962016-11-08 10:31:59 -0800740 && !w.mWinAnimator.mEnterAnimationPending) {
Robert Carrb1579c82017-09-05 14:54:47 -0700741 mTempLayer++;
742 outWindows.put(mTempLayer, w);
Svetoslav8e3feb12014-02-24 13:46:47 -0800743 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800744 }, false /* traverseTopToBottom */ );
Svetoslav8e3feb12014-02-24 13:46:47 -0800745 }
746
747 private final class ViewportWindow {
748 private static final String SURFACE_TITLE = "Magnification Overlay";
749
Svetoslav8e3feb12014-02-24 13:46:47 -0800750 private final Region mBounds = new Region();
751 private final Rect mDirtyRect = new Rect();
752 private final Paint mPaint = new Paint();
753
Svetoslav8e3feb12014-02-24 13:46:47 -0800754 private final SurfaceControl mSurfaceControl;
755 private final Surface mSurface = new Surface();
756
Svet Ganovb21df802014-09-01 19:06:33 -0700757 private final AnimationController mAnimationController;
758
Svetoslav8e3feb12014-02-24 13:46:47 -0800759 private boolean mShown;
760 private int mAlpha;
761
762 private boolean mInvalidated;
763
764 public ViewportWindow(Context context) {
765 SurfaceControl surfaceControl = null;
766 try {
Rhed Jao02655dc2018-10-30 20:44:52 +0800767 mDisplay.getRealSize(mTempPoint);
768 surfaceControl = mDisplayContent
769 .makeOverlay()
Robert Carre625fcf2017-09-01 12:36:28 -0700770 .setName(SURFACE_TITLE)
Vishnu Naire86bd982018-11-28 13:23:17 -0800771 .setBufferSize(mTempPoint.x, mTempPoint.y) // not a typo
Robert Carre625fcf2017-09-01 12:36:28 -0700772 .setFormat(PixelFormat.TRANSLUCENT)
773 .build();
Svetoslav8e3feb12014-02-24 13:46:47 -0800774 } catch (OutOfResourcesException oore) {
775 /* ignore */
776 }
777 mSurfaceControl = surfaceControl;
Robert Carre625fcf2017-09-01 12:36:28 -0700778 mSurfaceControl.setLayer(mService.mPolicy.getWindowLayerFromTypeLw(
Phil Weaverd321075e2017-06-13 09:13:35 -0700779 TYPE_MAGNIFICATION_OVERLAY)
Svetoslav8e3feb12014-02-24 13:46:47 -0800780 * WindowManagerService.TYPE_LAYER_MULTIPLIER);
781 mSurfaceControl.setPosition(0, 0);
782 mSurface.copyFrom(mSurfaceControl);
783
Svet Ganovb21df802014-09-01 19:06:33 -0700784 mAnimationController = new AnimationController(context,
Robert Carre625fcf2017-09-01 12:36:28 -0700785 mService.mH.getLooper());
Svet Ganovb21df802014-09-01 19:06:33 -0700786
Svetoslav8e3feb12014-02-24 13:46:47 -0800787 TypedValue typedValue = new TypedValue();
788 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
789 typedValue, true);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700790 final int borderColor = context.getColor(typedValue.resourceId);
Svetoslav8e3feb12014-02-24 13:46:47 -0800791
792 mPaint.setStyle(Paint.Style.STROKE);
793 mPaint.setStrokeWidth(mBorderWidth);
794 mPaint.setColor(borderColor);
795
Svetoslav8e3feb12014-02-24 13:46:47 -0800796 mInvalidated = true;
797 }
798
799 public void setShown(boolean shown, boolean animate) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700800 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800801 if (mShown == shown) {
802 return;
803 }
804 mShown = shown;
Svet Ganovb21df802014-09-01 19:06:33 -0700805 mAnimationController.onFrameShownStateChanged(shown, animate);
Svetoslav8e3feb12014-02-24 13:46:47 -0800806 if (DEBUG_VIEWPORT_WINDOW) {
807 Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
808 }
809 }
810 }
811
812 @SuppressWarnings("unused")
813 // Called reflectively from an animator.
814 public int getAlpha() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700815 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800816 return mAlpha;
817 }
818 }
819
820 public void setAlpha(int alpha) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700821 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800822 if (mAlpha == alpha) {
823 return;
824 }
825 mAlpha = alpha;
826 invalidate(null);
827 if (DEBUG_VIEWPORT_WINDOW) {
828 Slog.i(LOG_TAG, "ViewportWindow set alpha: " + alpha);
829 }
830 }
831 }
832
833 public void setBounds(Region bounds) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700834 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800835 if (mBounds.equals(bounds)) {
836 return;
837 }
838 mBounds.set(bounds);
839 invalidate(mDirtyRect);
840 if (DEBUG_VIEWPORT_WINDOW) {
841 Slog.i(LOG_TAG, "ViewportWindow set bounds: " + bounds);
842 }
843 }
844 }
845
846 public void updateSize() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700847 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800848 mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
Vishnu Naire86bd982018-11-28 13:23:17 -0800849 mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
Svetoslav8e3feb12014-02-24 13:46:47 -0800850 invalidate(mDirtyRect);
851 }
852 }
853
854 public void invalidate(Rect dirtyRect) {
855 if (dirtyRect != null) {
856 mDirtyRect.set(dirtyRect);
857 } else {
858 mDirtyRect.setEmpty();
859 }
860 mInvalidated = true;
Robert Carre625fcf2017-09-01 12:36:28 -0700861 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800862 }
863
864 /** NOTE: This has to be called within a surface transaction. */
865 public void drawIfNeeded() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700866 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800867 if (!mInvalidated) {
868 return;
869 }
870 mInvalidated = false;
Svetoslav8e3feb12014-02-24 13:46:47 -0800871 if (mAlpha > 0) {
Adrian Roos69364f52018-04-19 18:49:39 +0200872 Canvas canvas = null;
873 try {
874 // Empty dirty rectangle means unspecified.
875 if (mDirtyRect.isEmpty()) {
876 mBounds.getBounds(mDirtyRect);
877 }
878 mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
879 canvas = mSurface.lockCanvas(mDirtyRect);
880 if (DEBUG_VIEWPORT_WINDOW) {
881 Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
882 }
883 } catch (IllegalArgumentException iae) {
884 /* ignore */
885 } catch (Surface.OutOfResourcesException oore) {
886 /* ignore */
887 }
888 if (canvas == null) {
889 return;
890 }
891 if (DEBUG_VIEWPORT_WINDOW) {
892 Slog.i(LOG_TAG, "Bounds: " + mBounds);
893 }
894 canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
895 mPaint.setAlpha(mAlpha);
896 Path path = mBounds.getBoundaryPath();
897 canvas.drawPath(path, mPaint);
898
899 mSurface.unlockCanvasAndPost(canvas);
Svetoslav8e3feb12014-02-24 13:46:47 -0800900 mSurfaceControl.show();
901 } else {
902 mSurfaceControl.hide();
903 }
904 }
905 }
906
907 public void releaseSurface() {
Jackal Guo3f7cf2a2019-03-06 12:32:52 +0800908 mSurfaceControl.remove();
Svetoslav8e3feb12014-02-24 13:46:47 -0800909 mSurface.release();
910 }
Svet Ganovb21df802014-09-01 19:06:33 -0700911
912 private final class AnimationController extends Handler {
913 private static final String PROPERTY_NAME_ALPHA = "alpha";
914
915 private static final int MIN_ALPHA = 0;
916 private static final int MAX_ALPHA = 255;
917
918 private static final int MSG_FRAME_SHOWN_STATE_CHANGED = 1;
919
920 private final ValueAnimator mShowHideFrameAnimator;
921
922 public AnimationController(Context context, Looper looper) {
923 super(looper);
924 mShowHideFrameAnimator = ObjectAnimator.ofInt(ViewportWindow.this,
925 PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA);
926
927 Interpolator interpolator = new DecelerateInterpolator(2.5f);
928 final long longAnimationDuration = context.getResources().getInteger(
929 com.android.internal.R.integer.config_longAnimTime);
930
931 mShowHideFrameAnimator.setInterpolator(interpolator);
932 mShowHideFrameAnimator.setDuration(longAnimationDuration);
933 }
934
935 public void onFrameShownStateChanged(boolean shown, boolean animate) {
936 obtainMessage(MSG_FRAME_SHOWN_STATE_CHANGED,
937 shown ? 1 : 0, animate ? 1 : 0).sendToTarget();
938 }
939
940 @Override
941 public void handleMessage(Message message) {
942 switch (message.what) {
943 case MSG_FRAME_SHOWN_STATE_CHANGED: {
944 final boolean shown = message.arg1 == 1;
945 final boolean animate = message.arg2 == 1;
946
947 if (animate) {
948 if (mShowHideFrameAnimator.isRunning()) {
949 mShowHideFrameAnimator.reverse();
950 } else {
951 if (shown) {
952 mShowHideFrameAnimator.start();
953 } else {
954 mShowHideFrameAnimator.reverse();
955 }
956 }
957 } else {
958 mShowHideFrameAnimator.cancel();
959 if (shown) {
960 setAlpha(MAX_ALPHA);
961 } else {
962 setAlpha(MIN_ALPHA);
963 }
964 }
965 } break;
966 }
967 }
968 }
Svetoslav8e3feb12014-02-24 13:46:47 -0800969 }
970 }
971
972 private class MyHandler extends Handler {
Phil Weaver70439242016-03-10 15:15:49 -0800973 public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -0800974 public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
975 public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
976 public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
977 public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
978
979 public MyHandler(Looper looper) {
980 super(looper);
981 }
982
983 @Override
984 public void handleMessage(Message message) {
985 switch (message.what) {
Phil Weaver70439242016-03-10 15:15:49 -0800986 case MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED: {
Alan Viverette214fb682015-11-17 09:47:11 -0500987 final SomeArgs args = (SomeArgs) message.obj;
988 final Region magnifiedBounds = (Region) args.arg1;
Phil Weaver70439242016-03-10 15:15:49 -0800989 mCallbacks.onMagnificationRegionChanged(magnifiedBounds);
Alan Viverette214fb682015-11-17 09:47:11 -0500990 magnifiedBounds.recycle();
Svetoslav8e3feb12014-02-24 13:46:47 -0800991 } break;
992
993 case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
994 SomeArgs args = (SomeArgs) message.obj;
995 final int left = args.argi1;
996 final int top = args.argi2;
997 final int right = args.argi3;
998 final int bottom = args.argi4;
999 mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom);
1000 args.recycle();
1001 } break;
1002
1003 case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: {
1004 mCallbacks.onUserContextChanged();
1005 } break;
1006
1007 case MESSAGE_NOTIFY_ROTATION_CHANGED: {
1008 final int rotation = message.arg1;
1009 mCallbacks.onRotationChanged(rotation);
1010 } break;
1011
1012 case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : {
Wale Ogunwaledb485de2018-10-29 09:47:07 -07001013 synchronized (mService.mGlobalLock) {
Casey Burkhardt74922c62017-02-13 12:43:16 -08001014 if (mMagnifedViewport.isMagnifyingLocked()
1015 || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001016 mMagnifedViewport.setMagnifiedRegionBorderShownLocked(true, true);
Robert Carre625fcf2017-09-01 12:36:28 -07001017 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -08001018 }
1019 }
1020 } break;
1021 }
1022 }
1023 }
1024 }
1025
1026 /**
1027 * This class encapsulates the functionality related to computing the windows
1028 * reported for accessibility purposes. These windows are all windows a sighted
1029 * user can see on the screen.
1030 */
1031 private static final class WindowsForAccessibilityObserver {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -08001032 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ?
1033 "WindowsForAccessibilityObserver" : TAG_WM;
Svetoslav8e3feb12014-02-24 13:46:47 -08001034
1035 private static final boolean DEBUG = false;
1036
Jackal Guo28dce102019-05-28 14:25:17 +08001037 private final SparseArray<WindowState> mTempWindowStates = new SparseArray<>();
Svetoslav8e3feb12014-02-24 13:46:47 -08001038
Jackal Guo28dce102019-05-28 14:25:17 +08001039 private final Set<IBinder> mTempBinderSet = new ArraySet<>();
Svetoslav8e3feb12014-02-24 13:46:47 -08001040
1041 private final RectF mTempRectF = new RectF();
1042
1043 private final Matrix mTempMatrix = new Matrix();
1044
1045 private final Point mTempPoint = new Point();
1046
1047 private final Rect mTempRect = new Rect();
1048
1049 private final Region mTempRegion = new Region();
1050
1051 private final Region mTempRegion1 = new Region();
1052
1053 private final Context mContext;
1054
Robert Carre625fcf2017-09-01 12:36:28 -07001055 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001056
1057 private final Handler mHandler;
1058
1059 private final WindowsForAccessibilityCallback mCallback;
1060
Svetoslavf7174e82014-06-12 11:29:35 -07001061 private final long mRecurringAccessibilityEventsIntervalMillis;
1062
Svetoslav8e3feb12014-02-24 13:46:47 -08001063 public WindowsForAccessibilityObserver(WindowManagerService windowManagerService,
1064 WindowsForAccessibilityCallback callback) {
1065 mContext = windowManagerService.mContext;
Robert Carre625fcf2017-09-01 12:36:28 -07001066 mService = windowManagerService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001067 mCallback = callback;
Robert Carre625fcf2017-09-01 12:36:28 -07001068 mHandler = new MyHandler(mService.mH.getLooper());
Svetoslavf7174e82014-06-12 11:29:35 -07001069 mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration
1070 .getSendRecurringAccessibilityEventsInterval();
Phil Weaverc72faad2018-07-24 10:53:01 -07001071 computeChangedWindows(true);
Svetoslav8e3feb12014-02-24 13:46:47 -08001072 }
1073
Phil Weaverc72faad2018-07-24 10:53:01 -07001074 public void performComputeChangedWindowsNotLocked(boolean forceSend) {
Svetoslav3a0d8782014-12-04 12:50:11 -08001075 mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS);
Phil Weaverc72faad2018-07-24 10:53:01 -07001076 computeChangedWindows(forceSend);
Svetoslav3a0d8782014-12-04 12:50:11 -08001077 }
1078
Svetoslavf7174e82014-06-12 11:29:35 -07001079 public void scheduleComputeChangedWindowsLocked() {
Svetoslav3a0d8782014-12-04 12:50:11 -08001080 if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) {
Svetoslavf7174e82014-06-12 11:29:35 -07001081 mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS,
1082 mRecurringAccessibilityEventsIntervalMillis);
1083 }
1084 }
1085
Phil Weaverc72faad2018-07-24 10:53:01 -07001086 /**
Jackal Guoc43a0a62019-04-23 09:15:14 +08001087 * Check if windows have changed, and send them to the accessibility subsystem if they have.
Phil Weaverc72faad2018-07-24 10:53:01 -07001088 *
1089 * @param forceSend Send the windows the accessibility even if they haven't changed.
1090 */
1091 public void computeChangedWindows(boolean forceSend) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001092 if (DEBUG) {
1093 Slog.i(LOG_TAG, "computeChangedWindows()");
1094 }
1095
Jackal Guo28dce102019-05-28 14:25:17 +08001096 List<WindowInfo> windows = new ArrayList<>();
Svetoslav3a0d8782014-12-04 12:50:11 -08001097
Wale Ogunwaledb485de2018-10-29 09:47:07 -07001098 synchronized (mService.mGlobalLock) {
Svetoslavf7174e82014-06-12 11:29:35 -07001099 // Do not send the windows if there is no current focus as
1100 // the window manager is still looking for where to put it.
1101 // We will do the work when we get a focus change callback.
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001102 // TODO(b/112273690): Support multiple displays
Jackal Guoc43a0a62019-04-23 09:15:14 +08001103 if (!isCurrentFocusWindowOnDefaultDisplay()) {
Svetoslavf7174e82014-06-12 11:29:35 -07001104 return;
1105 }
1106
Svetoslav8e3feb12014-02-24 13:46:47 -08001107 WindowManager windowManager = (WindowManager)
1108 mContext.getSystemService(Context.WINDOW_SERVICE);
1109 windowManager.getDefaultDisplay().getRealSize(mTempPoint);
1110 final int screenWidth = mTempPoint.x;
1111 final int screenHeight = mTempPoint.y;
1112
1113 Region unaccountedSpace = mTempRegion;
1114 unaccountedSpace.set(0, 0, screenWidth, screenHeight);
1115
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001116 final SparseArray<WindowState> visibleWindows = mTempWindowStates;
Svetoslav8e3feb12014-02-24 13:46:47 -08001117 populateVisibleWindowsOnScreenLocked(visibleWindows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001118 Set<IBinder> addedWindows = mTempBinderSet;
1119 addedWindows.clear();
1120
Svetoslavf7174e82014-06-12 11:29:35 -07001121 boolean focusedWindowAdded = false;
1122
Svetoslav8e3feb12014-02-24 13:46:47 -08001123 final int visibleWindowCount = visibleWindows.size();
Allen Hairf20ac2c2016-02-11 17:42:59 -08001124 HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001125
1126 // Iterate until we figure out what is touchable for the entire screen.
Qasid Ahmad Sadiqd98cedd2019-04-12 21:56:24 +08001127 for (int i = visibleWindowCount - 1; i >= 0; i--) {
Alan Viverette9538eea2014-11-13 14:49:20 -08001128 final WindowState windowState = visibleWindows.valueAt(i);
Allen Hairf20ac2c2016-02-11 17:42:59 -08001129
Alan Viverette9538eea2014-11-13 14:49:20 -08001130 final Rect boundsInScreen = mTempRect;
1131 computeWindowBoundsInScreen(windowState, boundsInScreen);
1132
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001133 if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
1134 skipRemainingWindowsForTasks)) {
Eugene Susla18e7fc112018-03-16 14:35:31 -07001135 addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001136 updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
1137 skipRemainingWindowsForTasks);
Qasid Ahmad Sadiqd98cedd2019-04-12 21:56:24 +08001138 focusedWindowAdded |= windowState.isFocused();
1139 }
1140
1141 if (unaccountedSpace.isEmpty() && focusedWindowAdded) {
1142 break;
Svetoslavf7174e82014-06-12 11:29:35 -07001143 }
1144 }
1145
Svetoslav8e3feb12014-02-24 13:46:47 -08001146 // Remove child/parent references to windows that were not added.
1147 final int windowCount = windows.size();
1148 for (int i = 0; i < windowCount; i++) {
1149 WindowInfo window = windows.get(i);
1150 if (!addedWindows.contains(window.parentToken)) {
1151 window.parentToken = null;
1152 }
1153 if (window.childTokens != null) {
1154 final int childTokenCount = window.childTokens.size();
1155 for (int j = childTokenCount - 1; j >= 0; j--) {
1156 if (!addedWindows.contains(window.childTokens.get(j))) {
1157 window.childTokens.remove(j);
1158 }
1159 }
1160 // Leave the child token list if empty.
1161 }
1162 }
1163
1164 visibleWindows.clear();
1165 addedWindows.clear();
Svetoslav8e3feb12014-02-24 13:46:47 -08001166 }
Svetoslav3a0d8782014-12-04 12:50:11 -08001167
Jackal Guo28dce102019-05-28 14:25:17 +08001168 mCallback.onWindowsForAccessibilityChanged(forceSend, windows);
Svetoslav3a0d8782014-12-04 12:50:11 -08001169
1170 // Recycle the windows as we do not need them.
1171 clearAndRecycleWindows(windows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001172 }
1173
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001174 private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
1175 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1176 if (windowState.isFocused()) {
1177 return true;
1178 }
1179
1180 // If the window is part of a task that we're finished with - ignore.
1181 final Task task = windowState.getTask();
1182 if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
1183 return false;
1184 }
1185
1186 // Ignore non-touchable windows, except the split-screen divider, which is
1187 // occasionally non-touchable but still useful for identifying split-screen
1188 // mode.
1189 if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
1190 && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
1191 return false;
1192 }
1193
1194 // If the window is completely covered by other windows - ignore.
1195 if (unaccountedSpace.quickReject(boundsInScreen)) {
1196 return false;
1197 }
1198
1199 // Add windows of certain types not covered by modal windows.
1200 if (isReportedWindowType(windowState.mAttrs.type)) {
1201 return true;
1202 }
1203
1204 return false;
1205 }
1206
1207 private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
1208 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1209 if (windowState.mAttrs.type
1210 != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
1211
1212 // Account for the space this window takes if the window
1213 // is not an accessibility overlay which does not change
1214 // the reported windows.
1215 unaccountedSpace.op(boundsInScreen, unaccountedSpace,
1216 Region.Op.REVERSE_DIFFERENCE);
1217
1218 // If a window is modal it prevents other windows from being touched
1219 if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1220 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
1221 // Account for all space in the task, whether the windows in it are
1222 // touchable or not. The modal window blocks all touches from the task's
1223 // area.
1224 unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
1225 Region.Op.REVERSE_DIFFERENCE);
1226
1227 final Task task = windowState.getTask();
1228 if (task != null) {
1229 // If the window is associated with a particular task, we can skip the
1230 // rest of the windows for that task.
1231 skipRemainingWindowsForTasks.add(task.mTaskId);
1232 } else {
1233 // If the window is not associated with a particular task, then it is
1234 // globally modal. In this case we can skip all remaining windows.
1235 unaccountedSpace.setEmpty();
1236 }
1237 }
1238 }
1239 }
1240
Svetoslavf7174e82014-06-12 11:29:35 -07001241 private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
1242 // Get the touchable frame.
1243 Region touchableRegion = mTempRegion1;
1244 windowState.getTouchableRegion(touchableRegion);
1245 Rect touchableFrame = mTempRect;
1246 touchableRegion.getBounds(touchableFrame);
1247
1248 // Move to origin as all transforms are captured by the matrix.
1249 RectF windowFrame = mTempRectF;
1250 windowFrame.set(touchableFrame);
chaviw492139a2018-07-16 16:07:35 -07001251 windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
Svetoslavf7174e82014-06-12 11:29:35 -07001252
1253 // Map the frame to get what appears on the screen.
1254 Matrix matrix = mTempMatrix;
1255 populateTransformationMatrixLocked(windowState, matrix);
1256 matrix.mapRect(windowFrame);
1257
1258 // Got the bounds.
1259 outBounds.set((int) windowFrame.left, (int) windowFrame.top,
1260 (int) windowFrame.right, (int) windowFrame.bottom);
1261 }
1262
Eugene Susla18e7fc112018-03-16 14:35:31 -07001263 private static void addPopulatedWindowInfo(
1264 WindowState windowState, Rect boundsInScreen,
1265 List<WindowInfo> out, Set<IBinder> tokenOut) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -07001266 final WindowInfo window = windowState.getWindowInfo();
Svetoslavf7174e82014-06-12 11:29:35 -07001267 window.boundsInScreen.set(boundsInScreen);
Eugene Susla18e7fc112018-03-16 14:35:31 -07001268 window.layer = tokenOut.size();
1269 out.add(window);
1270 tokenOut.add(window.token);
Svetoslavf7174e82014-06-12 11:29:35 -07001271 }
1272
Svetoslav3a0d8782014-12-04 12:50:11 -08001273 private static void clearAndRecycleWindows(List<WindowInfo> windows) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001274 final int windowCount = windows.size();
1275 for (int i = windowCount - 1; i >= 0; i--) {
1276 windows.remove(i).recycle();
1277 }
1278 }
1279
1280 private static boolean isReportedWindowType(int windowType) {
Jorim Jaggi73294b62016-10-26 18:02:36 -07001281 return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER
Svetoslav8e3feb12014-02-24 13:46:47 -08001282 && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS
1283 && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY
1284 && windowType != WindowManager.LayoutParams.TYPE_DRAG
Selim Cinekf83e8242015-05-19 18:08:14 -07001285 && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER
Svetoslav8e3feb12014-02-24 13:46:47 -08001286 && windowType != WindowManager.LayoutParams.TYPE_POINTER
Phil Weaverd321075e2017-06-13 09:13:35 -07001287 && windowType != TYPE_MAGNIFICATION_OVERLAY
Svetoslav8e3feb12014-02-24 13:46:47 -08001288 && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
1289 && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
1290 && windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
1291 }
1292
1293 private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Jackal Guoc43a0a62019-04-23 09:15:14 +08001294 final List<WindowState> tempWindowStatesList = new ArrayList<>();
Robert Carre625fcf2017-09-01 12:36:28 -07001295 final DisplayContent dc = mService.getDefaultDisplayContentLocked();
Wale Ogunwaled1880962016-11-08 10:31:59 -08001296 dc.forAllWindows((w) -> {
1297 if (w.isVisibleLw()) {
Jackal Guoc43a0a62019-04-23 09:15:14 +08001298 tempWindowStatesList.add(w);
Svetoslav8e3feb12014-02-24 13:46:47 -08001299 }
Tiger Huangd8ec9382019-04-18 14:35:09 -07001300 }, false /* traverseTopToBottom */);
Jackal Guoc43a0a62019-04-23 09:15:14 +08001301 // Insert the re-parented windows in another display on top of their parents in
1302 // default display.
Tiger Huangd8ec9382019-04-18 14:35:09 -07001303 mService.mRoot.forAllWindows(w -> {
Jackal Guoc43a0a62019-04-23 09:15:14 +08001304 final WindowState parentWindow = findRootDisplayParentWindow(w);
1305 if (parentWindow == null) {
1306 return;
Tiger Huangd8ec9382019-04-18 14:35:09 -07001307 }
Jackal Guoc43a0a62019-04-23 09:15:14 +08001308
1309 // TODO: Use Region instead to get rid of this complicated logic.
1310 // Check the tap exclude region of the parent window. If the tap exclude region
1311 // is empty, it means there is another can-receive-pointer-event view on top of
1312 // the region. Hence, we don't count the window as visible.
1313 if (w.isVisibleLw() && parentWindow.getDisplayContent().isDefaultDisplay
1314 && parentWindow.hasTapExcludeRegion()
1315 && tempWindowStatesList.contains(parentWindow)) {
1316 tempWindowStatesList.add(
1317 tempWindowStatesList.lastIndexOf(parentWindow) + 1, w);
1318 }
1319 }, true /* traverseTopToBottom */);
1320 for (int i = 0; i < tempWindowStatesList.size(); i++) {
1321 outWindows.put(i, tempWindowStatesList.get(i));
1322 }
Tiger Huangd8ec9382019-04-18 14:35:09 -07001323 }
1324
1325 private WindowState findRootDisplayParentWindow(WindowState win) {
1326 WindowState displayParentWindow = win.getDisplayContent().getParentWindow();
1327 if (displayParentWindow == null) {
1328 return null;
1329 }
1330 WindowState candidate = displayParentWindow;
1331 while (candidate != null) {
1332 displayParentWindow = candidate;
1333 candidate = displayParentWindow.getDisplayContent().getParentWindow();
1334 }
1335 return displayParentWindow;
Svetoslav8e3feb12014-02-24 13:46:47 -08001336 }
1337
Jackal Guoc43a0a62019-04-23 09:15:14 +08001338 private boolean isCurrentFocusWindowOnDefaultDisplay() {
1339 final WindowState focusedWindow =
1340 mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
1341 if (focusedWindow == null) {
1342 return false;
1343 }
1344
1345 final WindowState rootDisplayParentWindow = findRootDisplayParentWindow(focusedWindow);
1346 if (!focusedWindow.isDefaultDisplay()
1347 && (rootDisplayParentWindow == null
1348 || !rootDisplayParentWindow.isDefaultDisplay())) {
1349 return false;
1350 }
1351
1352 return true;
1353 }
1354
Svetoslav8e3feb12014-02-24 13:46:47 -08001355 private class MyHandler extends Handler {
Svetoslavf7174e82014-06-12 11:29:35 -07001356 public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -08001357
1358 public MyHandler(Looper looper) {
1359 super(looper, null, false);
1360 }
1361
1362 @Override
1363 @SuppressWarnings("unchecked")
1364 public void handleMessage(Message message) {
1365 switch (message.what) {
Svetoslavf7174e82014-06-12 11:29:35 -07001366 case MESSAGE_COMPUTE_CHANGED_WINDOWS: {
Phil Weaverc72faad2018-07-24 10:53:01 -07001367 computeChangedWindows(false);
Svetoslavf7174e82014-06-12 11:29:35 -07001368 } break;
Svetoslav8e3feb12014-02-24 13:46:47 -08001369 }
1370 }
1371 }
1372 }
1373}