blob: e36d41347b7807c51b55887b6b6c47077d0f1ff3 [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;
Phil Weaver396d5492016-03-22 17:53:50 -070046import android.text.TextUtils;
Svetoslav8e3feb12014-02-24 13:46:47 -080047import android.util.ArraySet;
48import android.util.Log;
49import android.util.Slog;
50import android.util.SparseArray;
51import android.util.TypedValue;
Rhed Jao02655dc2018-10-30 20:44:52 +080052import android.view.Display;
Svetoslav8e3feb12014-02-24 13:46:47 -080053import android.view.MagnificationSpec;
54import android.view.Surface;
55import android.view.Surface.OutOfResourcesException;
56import android.view.SurfaceControl;
Svetoslavf7174e82014-06-12 11:29:35 -070057import android.view.ViewConfiguration;
Svetoslav8e3feb12014-02-24 13:46:47 -080058import android.view.WindowInfo;
59import android.view.WindowManager;
Svetoslav8e3feb12014-02-24 13:46:47 -080060import android.view.animation.DecelerateInterpolator;
61import android.view.animation.Interpolator;
62
63import com.android.internal.R;
64import com.android.internal.os.SomeArgs;
Adrian Roose99bc052017-11-20 17:55:31 +010065import com.android.server.policy.WindowManagerPolicy;
66import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
67import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback;
Svetoslav8e3feb12014-02-24 13:46:47 -080068
69import java.util.ArrayList;
Allen Hairf20ac2c2016-02-11 17:42:59 -080070import java.util.HashSet;
Svetoslav8e3feb12014-02-24 13:46:47 -080071import java.util.List;
72import java.util.Set;
73
74/**
kopriva82c591b2018-10-08 15:57:00 -070075 * This class contains the accessibility related logic of the window manager.
Svetoslav8e3feb12014-02-24 13:46:47 -080076 */
77final class AccessibilityController {
78
Robert Carre625fcf2017-09-01 12:36:28 -070079 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -080080
81 private static final float[] sTempFloats = new float[9];
82
83 public AccessibilityController(WindowManagerService service) {
Robert Carre625fcf2017-09-01 12:36:28 -070084 mService = service;
Svetoslav8e3feb12014-02-24 13:46:47 -080085 }
86
Rhed Jao02655dc2018-10-30 20:44:52 +080087 private SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
Svetoslav8e3feb12014-02-24 13:46:47 -080088
89 private WindowsForAccessibilityObserver mWindowsForAccessibilityObserver;
90
Rhed Jao02655dc2018-10-30 20:44:52 +080091 public boolean setMagnificationCallbacksLocked(int displayId,
92 MagnificationCallbacks callbacks) {
93 boolean result = false;
Svetoslav8e3feb12014-02-24 13:46:47 -080094 if (callbacks != null) {
Rhed Jao02655dc2018-10-30 20:44:52 +080095 if (mDisplayMagnifiers.get(displayId) != null) {
Svetoslav8e3feb12014-02-24 13:46:47 -080096 throw new IllegalStateException("Magnification callbacks already set!");
97 }
Rhed Jao02655dc2018-10-30 20:44:52 +080098 final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
99 if (dc != null) {
100 final Display display = dc.getDisplay();
101 if (display != null && display.getType() != Display.TYPE_OVERLAY) {
102 mDisplayMagnifiers.put(displayId, new DisplayMagnifier(
103 mService, dc, display, callbacks));
104 result = true;
105 }
106 }
Svetoslav8e3feb12014-02-24 13:46:47 -0800107 } else {
Rhed Jao02655dc2018-10-30 20:44:52 +0800108 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
109 if (displayMagnifier == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800110 throw new IllegalStateException("Magnification callbacks already cleared!");
111 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800112 displayMagnifier.destroyLocked();
113 mDisplayMagnifiers.remove(displayId);
114 result = true;
Svetoslav8e3feb12014-02-24 13:46:47 -0800115 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800116 return result;
Svetoslav8e3feb12014-02-24 13:46:47 -0800117 }
118
119 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
120 if (callback != null) {
121 if (mWindowsForAccessibilityObserver != null) {
122 throw new IllegalStateException(
123 "Windows for accessibility callback already set!");
124 }
125 mWindowsForAccessibilityObserver = new WindowsForAccessibilityObserver(
Robert Carre625fcf2017-09-01 12:36:28 -0700126 mService, callback);
Svetoslav8e3feb12014-02-24 13:46:47 -0800127 } else {
128 if (mWindowsForAccessibilityObserver == null) {
129 throw new IllegalStateException(
130 "Windows for accessibility callback already cleared!");
131 }
132 mWindowsForAccessibilityObserver = null;
133 }
134 }
135
Phil Weaverc72faad2018-07-24 10:53:01 -0700136 public void performComputeChangedWindowsNotLocked(boolean forceSend) {
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700137 WindowsForAccessibilityObserver observer = null;
Robert Carre625fcf2017-09-01 12:36:28 -0700138 synchronized (mService) {
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700139 observer = mWindowsForAccessibilityObserver;
140 }
141 if (observer != null) {
Phil Weaverc72faad2018-07-24 10:53:01 -0700142 observer.performComputeChangedWindowsNotLocked(forceSend);
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700143 }
144 }
145
Rhed Jao02655dc2018-10-30 20:44:52 +0800146 public void setMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
147 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
148 if (displayMagnifier != null) {
149 displayMagnifier.setMagnificationSpecLocked(spec);
Svetoslav8e3feb12014-02-24 13:46:47 -0800150 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800151 // TODO: support multi-display for windows observer
152 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700153 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800154 }
155 }
156
Rhed Jao02655dc2018-10-30 20:44:52 +0800157 public void getMagnificationRegionLocked(int displayId, Region outMagnificationRegion) {
158 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
159 if (displayMagnifier != null) {
160 displayMagnifier.getMagnificationRegionLocked(outMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400161 }
162 }
163
Rhed Jao02655dc2018-10-30 20:44:52 +0800164 public void onRectangleOnScreenRequestedLocked(int displayId, Rect rectangle) {
165 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
166 if (displayMagnifier != null) {
167 displayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
Svetoslav8e3feb12014-02-24 13:46:47 -0800168 }
169 // Not relevant for the window observer.
170 }
171
Rhed Jao02655dc2018-10-30 20:44:52 +0800172 public void onWindowLayersChangedLocked(int displayId) {
173 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
174 if (displayMagnifier != null) {
175 displayMagnifier.onWindowLayersChangedLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800176 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800177 // TODO: support multi-display for windows observer
178 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700179 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800180 }
181 }
182
Andrii Kulian8ee72852017-03-10 10:36:45 -0800183 public void onRotationChangedLocked(DisplayContent displayContent) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800184 final int displayId = displayContent.getDisplayId();
185 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
186 if (displayMagnifier != null) {
187 displayMagnifier.onRotationChangedLocked(displayContent);
Svetoslav8e3feb12014-02-24 13:46:47 -0800188 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800189 // TODO: support multi-display for windows observer
190 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700191 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800192 }
193 }
194
195 public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800196 final int displayId = windowState.getDisplayId();
197 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
198 if (displayMagnifier != null) {
199 displayMagnifier.onAppWindowTransitionLocked(windowState, transition);
Svetoslav8e3feb12014-02-24 13:46:47 -0800200 }
201 // Not relevant for the window observer.
202 }
203
204 public void onWindowTransitionLocked(WindowState windowState, int transition) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800205 final int displayId = windowState.getDisplayId();
206 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
207 if (displayMagnifier != null) {
208 displayMagnifier.onWindowTransitionLocked(windowState, transition);
Svetoslav8e3feb12014-02-24 13:46:47 -0800209 }
Rhed Jao02655dc2018-10-30 20:44:52 +0800210 // TODO: support multi-display for windows observer
211 if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
Svetoslavf7174e82014-06-12 11:29:35 -0700212 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800213 }
214 }
215
Svetoslav3a0d8782014-12-04 12:50:11 -0800216 public void onWindowFocusChangedNotLocked() {
Svetoslav8e3feb12014-02-24 13:46:47 -0800217 // Not relevant for the display magnifier.
218
Svetoslav3a0d8782014-12-04 12:50:11 -0800219 WindowsForAccessibilityObserver observer = null;
Robert Carre625fcf2017-09-01 12:36:28 -0700220 synchronized (mService) {
Svetoslav3a0d8782014-12-04 12:50:11 -0800221 observer = mWindowsForAccessibilityObserver;
222 }
223 if (observer != null) {
Phil Weaverc72faad2018-07-24 10:53:01 -0700224 observer.performComputeChangedWindowsNotLocked(false);
Svetoslav8e3feb12014-02-24 13:46:47 -0800225 }
226 }
227
Svetoslavf7174e82014-06-12 11:29:35 -0700228 public void onSomeWindowResizedOrMovedLocked() {
Svetoslav4604abc2014-06-10 18:59:30 -0700229 // Not relevant for the display magnifier.
230
231 if (mWindowsForAccessibilityObserver != null) {
Svetoslavf7174e82014-06-12 11:29:35 -0700232 mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
Svetoslav4604abc2014-06-10 18:59:30 -0700233 }
234 }
235
Svetoslav8e3feb12014-02-24 13:46:47 -0800236 /** NOTE: This has to be called within a surface transaction. */
Rhed Jao02655dc2018-10-30 20:44:52 +0800237 public void drawMagnifiedRegionBorderIfNeededLocked(int displayId) {
238 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
239 if (displayMagnifier != null) {
240 displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800241 }
242 // Not relevant for the window observer.
243 }
244
245 public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
Rhed Jao02655dc2018-10-30 20:44:52 +0800246 final int displayId = windowState.getDisplayId();
247 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
248 if (displayMagnifier != null) {
249 return displayMagnifier.getMagnificationSpecForWindowLocked(windowState);
Svetoslav8e3feb12014-02-24 13:46:47 -0800250 }
251 return null;
252 }
253
254 public boolean hasCallbacksLocked() {
Rhed Jao02655dc2018-10-30 20:44:52 +0800255 // TODO: support multi-display for windows observer
256 return (mDisplayMagnifiers.size() > 0
Svetoslav8e3feb12014-02-24 13:46:47 -0800257 || mWindowsForAccessibilityObserver != null);
258 }
259
Rhed Jao02655dc2018-10-30 20:44:52 +0800260 public void setForceShowMagnifiableBoundsLocked(int displayId, boolean show) {
261 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
262 if (displayMagnifier != null) {
263 displayMagnifier.setForceShowMagnifiableBoundsLocked(show);
264 displayMagnifier.showMagnificationBoundsIfNeeded();
Casey Burkhardt74922c62017-02-13 12:43:16 -0800265 }
266 }
267
Svetoslav8e3feb12014-02-24 13:46:47 -0800268 private static void populateTransformationMatrixLocked(WindowState windowState,
269 Matrix outMatrix) {
Jorim Jaggieb0d3bc2017-12-15 14:56:19 +0100270 windowState.getTransformationMatrix(sTempFloats, outMatrix);
Svetoslav8e3feb12014-02-24 13:46:47 -0800271 }
272
273 /**
274 * This class encapsulates the functionality related to display magnification.
275 */
276 private static final class DisplayMagnifier {
277
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800278 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ? "DisplayMagnifier" : TAG_WM;
Svetoslav8e3feb12014-02-24 13:46:47 -0800279
280 private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
281 private static final boolean DEBUG_ROTATION = false;
282 private static final boolean DEBUG_LAYERS = false;
283 private static final boolean DEBUG_RECTANGLE_REQUESTED = false;
284 private static final boolean DEBUG_VIEWPORT_WINDOW = false;
285
286 private final Rect mTempRect1 = new Rect();
287 private final Rect mTempRect2 = new Rect();
288
289 private final Region mTempRegion1 = new Region();
290 private final Region mTempRegion2 = new Region();
291 private final Region mTempRegion3 = new Region();
292 private final Region mTempRegion4 = new Region();
293
294 private final Context mContext;
Robert Carre625fcf2017-09-01 12:36:28 -0700295 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -0800296 private final MagnifiedViewport mMagnifedViewport;
297 private final Handler mHandler;
Rhed Jao02655dc2018-10-30 20:44:52 +0800298 private final DisplayContent mDisplayContent;
299 private final Display mDisplay;
Svetoslav8e3feb12014-02-24 13:46:47 -0800300
301 private final MagnificationCallbacks mCallbacks;
302
303 private final long mLongAnimationDuration;
304
Casey Burkhardt74922c62017-02-13 12:43:16 -0800305 private boolean mForceShowMagnifiableBounds = false;
306
Svetoslav8e3feb12014-02-24 13:46:47 -0800307 public DisplayMagnifier(WindowManagerService windowManagerService,
Rhed Jao02655dc2018-10-30 20:44:52 +0800308 DisplayContent displayContent,
309 Display display,
Svetoslav8e3feb12014-02-24 13:46:47 -0800310 MagnificationCallbacks callbacks) {
311 mContext = windowManagerService.mContext;
Robert Carre625fcf2017-09-01 12:36:28 -0700312 mService = windowManagerService;
Svetoslav8e3feb12014-02-24 13:46:47 -0800313 mCallbacks = callbacks;
Rhed Jao02655dc2018-10-30 20:44:52 +0800314 mDisplayContent = displayContent;
315 mDisplay = display;
Robert Carre625fcf2017-09-01 12:36:28 -0700316 mHandler = new MyHandler(mService.mH.getLooper());
Svetoslav8e3feb12014-02-24 13:46:47 -0800317 mMagnifedViewport = new MagnifiedViewport();
318 mLongAnimationDuration = mContext.getResources().getInteger(
319 com.android.internal.R.integer.config_longAnimTime);
320 }
321
322 public void setMagnificationSpecLocked(MagnificationSpec spec) {
323 mMagnifedViewport.updateMagnificationSpecLocked(spec);
324 mMagnifedViewport.recomputeBoundsLocked();
Robert Carrb1579c82017-09-05 14:54:47 -0700325
Rhed Jao02655dc2018-10-30 20:44:52 +0800326 mService.applyMagnificationSpecLocked(mDisplay.getDisplayId(), spec);
Robert Carre625fcf2017-09-01 12:36:28 -0700327 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800328 }
329
Casey Burkhardt74922c62017-02-13 12:43:16 -0800330 public void setForceShowMagnifiableBoundsLocked(boolean show) {
331 mForceShowMagnifiableBounds = show;
332 mMagnifedViewport.setMagnifiedRegionBorderShownLocked(show, true);
333 }
334
335 public boolean isForceShowingMagnifiableBoundsLocked() {
336 return mForceShowMagnifiableBounds;
337 }
338
Svetoslavf7174e82014-06-12 11:29:35 -0700339 public void onRectangleOnScreenRequestedLocked(Rect rectangle) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800340 if (DEBUG_RECTANGLE_REQUESTED) {
341 Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle);
342 }
343 if (!mMagnifedViewport.isMagnifyingLocked()) {
344 return;
345 }
346 Rect magnifiedRegionBounds = mTempRect2;
347 mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(magnifiedRegionBounds);
348 if (magnifiedRegionBounds.contains(rectangle)) {
349 return;
350 }
351 SomeArgs args = SomeArgs.obtain();
352 args.argi1 = rectangle.left;
353 args.argi2 = rectangle.top;
354 args.argi3 = rectangle.right;
355 args.argi4 = rectangle.bottom;
356 mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED,
357 args).sendToTarget();
358 }
359
360 public void onWindowLayersChangedLocked() {
361 if (DEBUG_LAYERS) {
362 Slog.i(LOG_TAG, "Layers changed.");
363 }
364 mMagnifedViewport.recomputeBoundsLocked();
Robert Carre625fcf2017-09-01 12:36:28 -0700365 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800366 }
367
Andrii Kulian8ee72852017-03-10 10:36:45 -0800368 public void onRotationChangedLocked(DisplayContent displayContent) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800369 if (DEBUG_ROTATION) {
Andrii Kulian8ee72852017-03-10 10:36:45 -0800370 final int rotation = displayContent.getRotation();
371 Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
Svetoslav8e3feb12014-02-24 13:46:47 -0800372 + " displayId: " + displayContent.getDisplayId());
373 }
374 mMagnifedViewport.onRotationChangedLocked();
375 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
376 }
377
378 public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
379 if (DEBUG_WINDOW_TRANSITIONS) {
380 Slog.i(LOG_TAG, "Window transition: "
381 + AppTransition.appTransitionToString(transition)
382 + " displayId: " + windowState.getDisplayId());
383 }
384 final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
385 if (magnifying) {
386 switch (transition) {
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100387 case WindowManager.TRANSIT_ACTIVITY_OPEN:
388 case WindowManager.TRANSIT_TASK_OPEN:
389 case WindowManager.TRANSIT_TASK_TO_FRONT:
390 case WindowManager.TRANSIT_WALLPAPER_OPEN:
391 case WindowManager.TRANSIT_WALLPAPER_CLOSE:
392 case WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN: {
Svetoslav8e3feb12014-02-24 13:46:47 -0800393 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
394 }
395 }
396 }
397 }
398
399 public void onWindowTransitionLocked(WindowState windowState, int transition) {
400 if (DEBUG_WINDOW_TRANSITIONS) {
401 Slog.i(LOG_TAG, "Window transition: "
402 + AppTransition.appTransitionToString(transition)
403 + " displayId: " + windowState.getDisplayId());
404 }
405 final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
406 final int type = windowState.mAttrs.type;
407 switch (transition) {
408 case WindowManagerPolicy.TRANSIT_ENTER:
409 case WindowManagerPolicy.TRANSIT_SHOW: {
410 if (!magnifying) {
411 break;
412 }
413 switch (type) {
414 case WindowManager.LayoutParams.TYPE_APPLICATION:
Chong Zhangfea963e2016-08-15 17:14:16 -0700415 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
Svetoslav8e3feb12014-02-24 13:46:47 -0800416 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
417 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
418 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
Wale Ogunwale0a4dc222015-04-14 12:58:42 -0700419 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
Svetoslav8e3feb12014-02-24 13:46:47 -0800420 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
421 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
422 case WindowManager.LayoutParams.TYPE_PHONE:
423 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
424 case WindowManager.LayoutParams.TYPE_TOAST:
425 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800426 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
Svetoslav8e3feb12014-02-24 13:46:47 -0800427 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
428 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
429 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
430 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
431 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
Jason Monk8f7f3182015-11-18 16:35:14 -0500432 case WindowManager.LayoutParams.TYPE_QS_DIALOG:
Adrian Roos9a645132014-10-08 02:59:56 +0200433 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: {
Svetoslav8e3feb12014-02-24 13:46:47 -0800434 Rect magnifiedRegionBounds = mTempRect2;
435 mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(
436 magnifiedRegionBounds);
437 Rect touchableRegionBounds = mTempRect1;
438 windowState.getTouchableRegion(mTempRegion1);
439 mTempRegion1.getBounds(touchableRegionBounds);
440 if (!magnifiedRegionBounds.intersect(touchableRegionBounds)) {
441 mCallbacks.onRectangleOnScreenRequested(
442 touchableRegionBounds.left,
443 touchableRegionBounds.top,
444 touchableRegionBounds.right,
445 touchableRegionBounds.bottom);
446 }
447 } break;
448 } break;
449 }
450 }
451 }
452
453 public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
454 MagnificationSpec spec = mMagnifedViewport.getMagnificationSpecLocked();
455 if (spec != null && !spec.isNop()) {
Robert Carrb1579c82017-09-05 14:54:47 -0700456 if (!windowState.shouldMagnify()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800457 return null;
458 }
459 }
460 return spec;
461 }
462
Phil Weaver70439242016-03-10 15:15:49 -0800463 public void getMagnificationRegionLocked(Region outMagnificationRegion) {
Phil Weaver53b690b2017-08-14 17:42:39 -0700464 // Make sure we're working with the most current bounds
465 mMagnifedViewport.recomputeBoundsLocked();
Phil Weaver70439242016-03-10 15:15:49 -0800466 mMagnifedViewport.getMagnificationRegionLocked(outMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400467 }
468
Svetoslav8e3feb12014-02-24 13:46:47 -0800469 public void destroyLocked() {
470 mMagnifedViewport.destroyWindow();
471 }
472
Phil Weaver251db072017-03-28 08:35:38 -0700473 // Can be called outside of a surface transaction
474 public void showMagnificationBoundsIfNeeded() {
475 mHandler.obtainMessage(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)
476 .sendToTarget();
477 }
478
Svetoslav8e3feb12014-02-24 13:46:47 -0800479 /** NOTE: This has to be called within a surface transaction. */
480 public void drawMagnifiedRegionBorderIfNeededLocked() {
481 mMagnifedViewport.drawWindowIfNeededLocked();
482 }
483
484 private final class MagnifiedViewport {
485
Svetoslav8e3feb12014-02-24 13:46:47 -0800486 private final SparseArray<WindowState> mTempWindowStates =
487 new SparseArray<WindowState>();
488
489 private final RectF mTempRectF = new RectF();
490
491 private final Point mTempPoint = new Point();
492
493 private final Matrix mTempMatrix = new Matrix();
494
Phil Weaver70439242016-03-10 15:15:49 -0800495 private final Region mMagnificationRegion = new Region();
496 private final Region mOldMagnificationRegion = new Region();
Svetoslav8e3feb12014-02-24 13:46:47 -0800497
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800498 private final Path mCircularPath;
499
Svetoslav8e3feb12014-02-24 13:46:47 -0800500 private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain();
501
502 private final WindowManager mWindowManager;
503
Svetoslav7505e332014-08-22 12:14:28 -0700504 private final float mBorderWidth;
Svetoslav8e3feb12014-02-24 13:46:47 -0800505 private final int mHalfBorderWidth;
Svetoslav7505e332014-08-22 12:14:28 -0700506 private final int mDrawBorderInset;
Svetoslav8e3feb12014-02-24 13:46:47 -0800507
508 private final ViewportWindow mWindow;
509
510 private boolean mFullRedrawNeeded;
Robert Carrb1579c82017-09-05 14:54:47 -0700511 private int mTempLayer = 0;
Svetoslav8e3feb12014-02-24 13:46:47 -0800512
513 public MagnifiedViewport() {
514 mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800515 mBorderWidth = mContext.getResources().getDimension(
516 com.android.internal.R.dimen.accessibility_magnification_indicator_width);
Svetoslav7505e332014-08-22 12:14:28 -0700517 mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
518 mDrawBorderInset = (int) mBorderWidth / 2;
Svetoslav8e3feb12014-02-24 13:46:47 -0800519 mWindow = new ViewportWindow(mContext);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800520
Adam Powell01f280d2015-05-18 16:07:42 -0700521 if (mContext.getResources().getConfiguration().isScreenRound()) {
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800522 mCircularPath = new Path();
Rhed Jao02655dc2018-10-30 20:44:52 +0800523 mDisplay.getRealSize(mTempPoint);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800524 final int centerXY = mTempPoint.x / 2;
525 mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
526 } else {
527 mCircularPath = null;
528 }
529
Svetoslav8e3feb12014-02-24 13:46:47 -0800530 recomputeBoundsLocked();
531 }
532
Phil Weaver70439242016-03-10 15:15:49 -0800533 public void getMagnificationRegionLocked(@NonNull Region outMagnificationRegion) {
534 outMagnificationRegion.set(mMagnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400535 }
536
Svetoslav8e3feb12014-02-24 13:46:47 -0800537 public void updateMagnificationSpecLocked(MagnificationSpec spec) {
538 if (spec != null) {
539 mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY);
540 } else {
541 mMagnificationSpec.clear();
542 }
543 // If this message is pending we are in a rotation animation and do not want
544 // to show the border. We will do so when the pending message is handled.
Svetoslav7505e332014-08-22 12:14:28 -0700545 if (!mHandler.hasMessages(
546 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800547 setMagnifiedRegionBorderShownLocked(
548 isMagnifyingLocked() || isForceShowingMagnifiableBoundsLocked(), true);
Svetoslav8e3feb12014-02-24 13:46:47 -0800549 }
550 }
551
552 public void recomputeBoundsLocked() {
Rhed Jao02655dc2018-10-30 20:44:52 +0800553 mDisplay.getRealSize(mTempPoint);
Svetoslav8e3feb12014-02-24 13:46:47 -0800554 final int screenWidth = mTempPoint.x;
555 final int screenHeight = mTempPoint.y;
556
Phil Weaver70439242016-03-10 15:15:49 -0800557 mMagnificationRegion.set(0, 0, 0, 0);
558 final Region availableBounds = mTempRegion1;
559 availableBounds.set(0, 0, screenWidth, screenHeight);
Svetoslav8e3feb12014-02-24 13:46:47 -0800560
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800561 if (mCircularPath != null) {
Phil Weaver70439242016-03-10 15:15:49 -0800562 availableBounds.setPath(mCircularPath, availableBounds);
Casey Burkhardtd29a1e42015-02-12 14:07:55 -0800563 }
564
Svetoslav8e3feb12014-02-24 13:46:47 -0800565 Region nonMagnifiedBounds = mTempRegion4;
Svet Ganovb21df802014-09-01 19:06:33 -0700566 nonMagnifiedBounds.set(0, 0, 0, 0);
Svetoslav8e3feb12014-02-24 13:46:47 -0800567
568 SparseArray<WindowState> visibleWindows = mTempWindowStates;
569 visibleWindows.clear();
570 populateWindowsOnScreenLocked(visibleWindows);
571
572 final int visibleWindowCount = visibleWindows.size();
573 for (int i = visibleWindowCount - 1; i >= 0; i--) {
574 WindowState windowState = visibleWindows.valueAt(i);
Phil Weaverd321075e2017-06-13 09:13:35 -0700575 if ((windowState.mAttrs.type == TYPE_MAGNIFICATION_OVERLAY)
576 || ((windowState.mAttrs.privateFlags
Robert Carr132c9f52017-07-31 17:02:30 -0700577 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0)) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800578 continue;
579 }
580
Phil Weaver65c06702016-03-15 15:33:46 -0700581 // Consider the touchable portion of the window
Svetoslav8e3feb12014-02-24 13:46:47 -0800582 Matrix matrix = mTempMatrix;
583 populateTransformationMatrixLocked(windowState, matrix);
Phil Weaver65c06702016-03-15 15:33:46 -0700584 Region touchableRegion = mTempRegion3;
585 windowState.getTouchableRegion(touchableRegion);
586 Rect touchableFrame = mTempRect1;
587 touchableRegion.getBounds(touchableFrame);
Svetoslav8e3feb12014-02-24 13:46:47 -0800588 RectF windowFrame = mTempRectF;
Phil Weaver65c06702016-03-15 15:33:46 -0700589 windowFrame.set(touchableFrame);
chaviw492139a2018-07-16 16:07:35 -0700590 windowFrame.offset(-windowState.getFrameLw().left,
591 -windowState.getFrameLw().top);
Phil Weaver65c06702016-03-15 15:33:46 -0700592 matrix.mapRect(windowFrame);
593 Region windowBounds = mTempRegion2;
594 windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
595 (int) windowFrame.right, (int) windowFrame.bottom);
596 // Only update new regions
597 Region portionOfWindowAlreadyAccountedFor = mTempRegion3;
Phil Weaver70439242016-03-10 15:15:49 -0800598 portionOfWindowAlreadyAccountedFor.set(mMagnificationRegion);
Phil Weaver65c06702016-03-15 15:33:46 -0700599 portionOfWindowAlreadyAccountedFor.op(nonMagnifiedBounds, Region.Op.UNION);
600 windowBounds.op(portionOfWindowAlreadyAccountedFor, Region.Op.DIFFERENCE);
Svetoslav8e3feb12014-02-24 13:46:47 -0800601
Robert Carrb1579c82017-09-05 14:54:47 -0700602 if (windowState.shouldMagnify()) {
Phil Weaver70439242016-03-10 15:15:49 -0800603 mMagnificationRegion.op(windowBounds, Region.Op.UNION);
604 mMagnificationRegion.op(availableBounds, Region.Op.INTERSECT);
Svetoslav8e3feb12014-02-24 13:46:47 -0800605 } else {
Svetoslav8e3feb12014-02-24 13:46:47 -0800606 nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
Phil Weaver70439242016-03-10 15:15:49 -0800607 availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
Svetoslav8e3feb12014-02-24 13:46:47 -0800608 }
609
Jackal Guoc2e12c42019-02-27 17:06:33 +0800610 // Count letterbox into nonMagnifiedBounds
611 if (windowState.isLetterboxedForDisplayCutoutLw()) {
612 Region letterboxBounds = getLetterboxBounds(windowState);
613 nonMagnifiedBounds.op(letterboxBounds, Region.Op.UNION);
614 availableBounds.op(letterboxBounds, Region.Op.DIFFERENCE);
615 }
616
Phil Weaver65c06702016-03-15 15:33:46 -0700617 // Update accounted bounds
Svetoslav8e3feb12014-02-24 13:46:47 -0800618 Region accountedBounds = mTempRegion2;
Phil Weaver70439242016-03-10 15:15:49 -0800619 accountedBounds.set(mMagnificationRegion);
Svetoslav8e3feb12014-02-24 13:46:47 -0800620 accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
621 accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
622
623 if (accountedBounds.isRect()) {
624 Rect accountedFrame = mTempRect1;
625 accountedBounds.getBounds(accountedFrame);
626 if (accountedFrame.width() == screenWidth
627 && accountedFrame.height() == screenHeight) {
628 break;
629 }
630 }
631 }
632
633 visibleWindows.clear();
634
Phil Weaver70439242016-03-10 15:15:49 -0800635 mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
Svetoslav7505e332014-08-22 12:14:28 -0700636 screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
Svetoslav8e3feb12014-02-24 13:46:47 -0800637 Region.Op.INTERSECT);
638
Phil Weaver70439242016-03-10 15:15:49 -0800639 final boolean magnifiedChanged =
640 !mOldMagnificationRegion.equals(mMagnificationRegion);
641 if (magnifiedChanged) {
642 mWindow.setBounds(mMagnificationRegion);
643 final Rect dirtyRect = mTempRect1;
644 if (mFullRedrawNeeded) {
645 mFullRedrawNeeded = false;
646 dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
647 screenWidth - mDrawBorderInset,
648 screenHeight - mDrawBorderInset);
649 mWindow.invalidate(dirtyRect);
650 } else {
651 final Region dirtyRegion = mTempRegion3;
652 dirtyRegion.set(mMagnificationRegion);
653 dirtyRegion.op(mOldMagnificationRegion, Region.Op.UNION);
654 dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
655 dirtyRegion.getBounds(dirtyRect);
656 mWindow.invalidate(dirtyRect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800657 }
658
Phil Weaver70439242016-03-10 15:15:49 -0800659 mOldMagnificationRegion.set(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500660 final SomeArgs args = SomeArgs.obtain();
Phil Weaver70439242016-03-10 15:15:49 -0800661 args.arg1 = Region.obtain(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500662 mHandler.obtainMessage(
Phil Weaver70439242016-03-10 15:15:49 -0800663 MyHandler.MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED, args)
664 .sendToTarget();
Svetoslav8e3feb12014-02-24 13:46:47 -0800665 }
666 }
667
Jackal Guoc2e12c42019-02-27 17:06:33 +0800668 private Region getLetterboxBounds(WindowState windowState) {
669 final AppWindowToken appToken = windowState.mAppToken;
670 if (appToken == null) {
671 return new Region();
672 }
673
674 mDisplay.getRealSize(mTempPoint);
675 final Rect letterboxInsets = appToken.getLetterboxInsets();
676 final int screenWidth = mTempPoint.x;
677 final int screenHeight = mTempPoint.y;
678 final Rect nonLetterboxRect = mTempRect1;
679 final Region letterboxBounds = mTempRegion3;
680 nonLetterboxRect.set(0, 0, screenWidth, screenHeight);
681 nonLetterboxRect.inset(letterboxInsets);
682 letterboxBounds.set(0, 0, screenWidth, screenHeight);
683 letterboxBounds.op(nonLetterboxRect, Region.Op.DIFFERENCE);
684 return letterboxBounds;
685 }
686
Svetoslav8e3feb12014-02-24 13:46:47 -0800687 public void onRotationChangedLocked() {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800688 // If we are showing the magnification border, hide it immediately so
Svetoslav8e3feb12014-02-24 13:46:47 -0800689 // the user does not see strange artifacts during rotation. The screenshot
Casey Burkhardt74922c62017-02-13 12:43:16 -0800690 // used for rotation already has the border. After the rotation is complete
Svetoslav8e3feb12014-02-24 13:46:47 -0800691 // we will show the border.
Casey Burkhardt74922c62017-02-13 12:43:16 -0800692 if (isMagnifyingLocked() || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800693 setMagnifiedRegionBorderShownLocked(false, false);
694 final long delay = (long) (mLongAnimationDuration
Robert Carre625fcf2017-09-01 12:36:28 -0700695 * mService.getWindowAnimationScaleLocked());
Svetoslav8e3feb12014-02-24 13:46:47 -0800696 Message message = mHandler.obtainMessage(
697 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED);
698 mHandler.sendMessageDelayed(message, delay);
699 }
700 recomputeBoundsLocked();
701 mWindow.updateSize();
702 }
703
704 public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
705 if (shown) {
706 mFullRedrawNeeded = true;
Phil Weaver70439242016-03-10 15:15:49 -0800707 mOldMagnificationRegion.set(0, 0, 0, 0);
Svetoslav8e3feb12014-02-24 13:46:47 -0800708 }
709 mWindow.setShown(shown, animate);
710 }
711
712 public void getMagnifiedFrameInContentCoordsLocked(Rect rect) {
713 MagnificationSpec spec = mMagnificationSpec;
Phil Weaver70439242016-03-10 15:15:49 -0800714 mMagnificationRegion.getBounds(rect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800715 rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
716 rect.scale(1.0f / spec.scale);
717 }
718
719 public boolean isMagnifyingLocked() {
720 return mMagnificationSpec.scale > 1.0f;
721 }
722
723 public MagnificationSpec getMagnificationSpecLocked() {
724 return mMagnificationSpec;
725 }
726
727 /** NOTE: This has to be called within a surface transaction. */
728 public void drawWindowIfNeededLocked() {
729 recomputeBoundsLocked();
730 mWindow.drawIfNeeded();
731 }
732
733 public void destroyWindow() {
734 mWindow.releaseSurface();
735 }
736
737 private void populateWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Robert Carrb1579c82017-09-05 14:54:47 -0700738 mTempLayer = 0;
Rhed Jao02655dc2018-10-30 20:44:52 +0800739 mDisplayContent.forAllWindows((w) -> {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800740 if (w.isOnScreen() && w.isVisibleLw()
Phil Weaverd6ce7372018-05-18 09:48:01 -0700741 && (w.mAttrs.alpha != 0)
Wale Ogunwaled1880962016-11-08 10:31:59 -0800742 && !w.mWinAnimator.mEnterAnimationPending) {
Robert Carrb1579c82017-09-05 14:54:47 -0700743 mTempLayer++;
744 outWindows.put(mTempLayer, w);
Svetoslav8e3feb12014-02-24 13:46:47 -0800745 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800746 }, false /* traverseTopToBottom */ );
Svetoslav8e3feb12014-02-24 13:46:47 -0800747 }
748
749 private final class ViewportWindow {
750 private static final String SURFACE_TITLE = "Magnification Overlay";
751
Svetoslav8e3feb12014-02-24 13:46:47 -0800752 private final Region mBounds = new Region();
753 private final Rect mDirtyRect = new Rect();
754 private final Paint mPaint = new Paint();
755
Svetoslav8e3feb12014-02-24 13:46:47 -0800756 private final SurfaceControl mSurfaceControl;
757 private final Surface mSurface = new Surface();
758
Svet Ganovb21df802014-09-01 19:06:33 -0700759 private final AnimationController mAnimationController;
760
Svetoslav8e3feb12014-02-24 13:46:47 -0800761 private boolean mShown;
762 private int mAlpha;
763
764 private boolean mInvalidated;
765
766 public ViewportWindow(Context context) {
767 SurfaceControl surfaceControl = null;
768 try {
Rhed Jao02655dc2018-10-30 20:44:52 +0800769 mDisplay.getRealSize(mTempPoint);
770 surfaceControl = mDisplayContent
771 .makeOverlay()
Robert Carre625fcf2017-09-01 12:36:28 -0700772 .setName(SURFACE_TITLE)
Vishnu Naire86bd982018-11-28 13:23:17 -0800773 .setBufferSize(mTempPoint.x, mTempPoint.y) // not a typo
Robert Carre625fcf2017-09-01 12:36:28 -0700774 .setFormat(PixelFormat.TRANSLUCENT)
775 .build();
Svetoslav8e3feb12014-02-24 13:46:47 -0800776 } catch (OutOfResourcesException oore) {
777 /* ignore */
778 }
779 mSurfaceControl = surfaceControl;
Robert Carre625fcf2017-09-01 12:36:28 -0700780 mSurfaceControl.setLayer(mService.mPolicy.getWindowLayerFromTypeLw(
Phil Weaverd321075e2017-06-13 09:13:35 -0700781 TYPE_MAGNIFICATION_OVERLAY)
Svetoslav8e3feb12014-02-24 13:46:47 -0800782 * WindowManagerService.TYPE_LAYER_MULTIPLIER);
783 mSurfaceControl.setPosition(0, 0);
784 mSurface.copyFrom(mSurfaceControl);
785
Svet Ganovb21df802014-09-01 19:06:33 -0700786 mAnimationController = new AnimationController(context,
Robert Carre625fcf2017-09-01 12:36:28 -0700787 mService.mH.getLooper());
Svet Ganovb21df802014-09-01 19:06:33 -0700788
Svetoslav8e3feb12014-02-24 13:46:47 -0800789 TypedValue typedValue = new TypedValue();
790 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
791 typedValue, true);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700792 final int borderColor = context.getColor(typedValue.resourceId);
Svetoslav8e3feb12014-02-24 13:46:47 -0800793
794 mPaint.setStyle(Paint.Style.STROKE);
795 mPaint.setStrokeWidth(mBorderWidth);
796 mPaint.setColor(borderColor);
797
Svetoslav8e3feb12014-02-24 13:46:47 -0800798 mInvalidated = true;
799 }
800
801 public void setShown(boolean shown, boolean animate) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700802 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800803 if (mShown == shown) {
804 return;
805 }
806 mShown = shown;
Svet Ganovb21df802014-09-01 19:06:33 -0700807 mAnimationController.onFrameShownStateChanged(shown, animate);
Svetoslav8e3feb12014-02-24 13:46:47 -0800808 if (DEBUG_VIEWPORT_WINDOW) {
809 Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
810 }
811 }
812 }
813
814 @SuppressWarnings("unused")
815 // Called reflectively from an animator.
816 public int getAlpha() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700817 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800818 return mAlpha;
819 }
820 }
821
822 public void setAlpha(int alpha) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700823 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800824 if (mAlpha == alpha) {
825 return;
826 }
827 mAlpha = alpha;
828 invalidate(null);
829 if (DEBUG_VIEWPORT_WINDOW) {
830 Slog.i(LOG_TAG, "ViewportWindow set alpha: " + alpha);
831 }
832 }
833 }
834
835 public void setBounds(Region bounds) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700836 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800837 if (mBounds.equals(bounds)) {
838 return;
839 }
840 mBounds.set(bounds);
841 invalidate(mDirtyRect);
842 if (DEBUG_VIEWPORT_WINDOW) {
843 Slog.i(LOG_TAG, "ViewportWindow set bounds: " + bounds);
844 }
845 }
846 }
847
848 public void updateSize() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700849 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800850 mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
Vishnu Naire86bd982018-11-28 13:23:17 -0800851 mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
Svetoslav8e3feb12014-02-24 13:46:47 -0800852 invalidate(mDirtyRect);
853 }
854 }
855
856 public void invalidate(Rect dirtyRect) {
857 if (dirtyRect != null) {
858 mDirtyRect.set(dirtyRect);
859 } else {
860 mDirtyRect.setEmpty();
861 }
862 mInvalidated = true;
Robert Carre625fcf2017-09-01 12:36:28 -0700863 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800864 }
865
866 /** NOTE: This has to be called within a surface transaction. */
867 public void drawIfNeeded() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700868 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800869 if (!mInvalidated) {
870 return;
871 }
872 mInvalidated = false;
Svetoslav8e3feb12014-02-24 13:46:47 -0800873 if (mAlpha > 0) {
Adrian Roos69364f52018-04-19 18:49:39 +0200874 Canvas canvas = null;
875 try {
876 // Empty dirty rectangle means unspecified.
877 if (mDirtyRect.isEmpty()) {
878 mBounds.getBounds(mDirtyRect);
879 }
880 mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
881 canvas = mSurface.lockCanvas(mDirtyRect);
882 if (DEBUG_VIEWPORT_WINDOW) {
883 Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
884 }
885 } catch (IllegalArgumentException iae) {
886 /* ignore */
887 } catch (Surface.OutOfResourcesException oore) {
888 /* ignore */
889 }
890 if (canvas == null) {
891 return;
892 }
893 if (DEBUG_VIEWPORT_WINDOW) {
894 Slog.i(LOG_TAG, "Bounds: " + mBounds);
895 }
896 canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
897 mPaint.setAlpha(mAlpha);
898 Path path = mBounds.getBoundaryPath();
899 canvas.drawPath(path, mPaint);
900
901 mSurface.unlockCanvasAndPost(canvas);
Svetoslav8e3feb12014-02-24 13:46:47 -0800902 mSurfaceControl.show();
903 } else {
904 mSurfaceControl.hide();
905 }
906 }
907 }
908
909 public void releaseSurface() {
910 mSurfaceControl.release();
911 mSurface.release();
912 }
Svet Ganovb21df802014-09-01 19:06:33 -0700913
914 private final class AnimationController extends Handler {
915 private static final String PROPERTY_NAME_ALPHA = "alpha";
916
917 private static final int MIN_ALPHA = 0;
918 private static final int MAX_ALPHA = 255;
919
920 private static final int MSG_FRAME_SHOWN_STATE_CHANGED = 1;
921
922 private final ValueAnimator mShowHideFrameAnimator;
923
924 public AnimationController(Context context, Looper looper) {
925 super(looper);
926 mShowHideFrameAnimator = ObjectAnimator.ofInt(ViewportWindow.this,
927 PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA);
928
929 Interpolator interpolator = new DecelerateInterpolator(2.5f);
930 final long longAnimationDuration = context.getResources().getInteger(
931 com.android.internal.R.integer.config_longAnimTime);
932
933 mShowHideFrameAnimator.setInterpolator(interpolator);
934 mShowHideFrameAnimator.setDuration(longAnimationDuration);
935 }
936
937 public void onFrameShownStateChanged(boolean shown, boolean animate) {
938 obtainMessage(MSG_FRAME_SHOWN_STATE_CHANGED,
939 shown ? 1 : 0, animate ? 1 : 0).sendToTarget();
940 }
941
942 @Override
943 public void handleMessage(Message message) {
944 switch (message.what) {
945 case MSG_FRAME_SHOWN_STATE_CHANGED: {
946 final boolean shown = message.arg1 == 1;
947 final boolean animate = message.arg2 == 1;
948
949 if (animate) {
950 if (mShowHideFrameAnimator.isRunning()) {
951 mShowHideFrameAnimator.reverse();
952 } else {
953 if (shown) {
954 mShowHideFrameAnimator.start();
955 } else {
956 mShowHideFrameAnimator.reverse();
957 }
958 }
959 } else {
960 mShowHideFrameAnimator.cancel();
961 if (shown) {
962 setAlpha(MAX_ALPHA);
963 } else {
964 setAlpha(MIN_ALPHA);
965 }
966 }
967 } break;
968 }
969 }
970 }
Svetoslav8e3feb12014-02-24 13:46:47 -0800971 }
972 }
973
974 private class MyHandler extends Handler {
Phil Weaver70439242016-03-10 15:15:49 -0800975 public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -0800976 public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
977 public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
978 public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
979 public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
980
981 public MyHandler(Looper looper) {
982 super(looper);
983 }
984
985 @Override
986 public void handleMessage(Message message) {
987 switch (message.what) {
Phil Weaver70439242016-03-10 15:15:49 -0800988 case MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED: {
Alan Viverette214fb682015-11-17 09:47:11 -0500989 final SomeArgs args = (SomeArgs) message.obj;
990 final Region magnifiedBounds = (Region) args.arg1;
Phil Weaver70439242016-03-10 15:15:49 -0800991 mCallbacks.onMagnificationRegionChanged(magnifiedBounds);
Alan Viverette214fb682015-11-17 09:47:11 -0500992 magnifiedBounds.recycle();
Svetoslav8e3feb12014-02-24 13:46:47 -0800993 } break;
994
995 case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
996 SomeArgs args = (SomeArgs) message.obj;
997 final int left = args.argi1;
998 final int top = args.argi2;
999 final int right = args.argi3;
1000 final int bottom = args.argi4;
1001 mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom);
1002 args.recycle();
1003 } break;
1004
1005 case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: {
1006 mCallbacks.onUserContextChanged();
1007 } break;
1008
1009 case MESSAGE_NOTIFY_ROTATION_CHANGED: {
1010 final int rotation = message.arg1;
1011 mCallbacks.onRotationChanged(rotation);
1012 } break;
1013
1014 case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : {
Wale Ogunwaledb485de2018-10-29 09:47:07 -07001015 synchronized (mService.mGlobalLock) {
Casey Burkhardt74922c62017-02-13 12:43:16 -08001016 if (mMagnifedViewport.isMagnifyingLocked()
1017 || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001018 mMagnifedViewport.setMagnifiedRegionBorderShownLocked(true, true);
Robert Carre625fcf2017-09-01 12:36:28 -07001019 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -08001020 }
1021 }
1022 } break;
1023 }
1024 }
1025 }
1026 }
1027
1028 /**
1029 * This class encapsulates the functionality related to computing the windows
1030 * reported for accessibility purposes. These windows are all windows a sighted
1031 * user can see on the screen.
1032 */
1033 private static final class WindowsForAccessibilityObserver {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -08001034 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ?
1035 "WindowsForAccessibilityObserver" : TAG_WM;
Svetoslav8e3feb12014-02-24 13:46:47 -08001036
1037 private static final boolean DEBUG = false;
1038
1039 private final SparseArray<WindowState> mTempWindowStates =
1040 new SparseArray<WindowState>();
1041
1042 private final List<WindowInfo> mOldWindows = new ArrayList<WindowInfo>();
1043
1044 private final Set<IBinder> mTempBinderSet = new ArraySet<IBinder>();
1045
1046 private final RectF mTempRectF = new RectF();
1047
1048 private final Matrix mTempMatrix = new Matrix();
1049
1050 private final Point mTempPoint = new Point();
1051
1052 private final Rect mTempRect = new Rect();
1053
1054 private final Region mTempRegion = new Region();
1055
1056 private final Region mTempRegion1 = new Region();
1057
1058 private final Context mContext;
1059
Robert Carre625fcf2017-09-01 12:36:28 -07001060 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001061
1062 private final Handler mHandler;
1063
1064 private final WindowsForAccessibilityCallback mCallback;
1065
Svetoslavf7174e82014-06-12 11:29:35 -07001066 private final long mRecurringAccessibilityEventsIntervalMillis;
1067
Robert Carrb1579c82017-09-05 14:54:47 -07001068 private int mTempLayer = 0;
1069
Svetoslav8e3feb12014-02-24 13:46:47 -08001070 public WindowsForAccessibilityObserver(WindowManagerService windowManagerService,
1071 WindowsForAccessibilityCallback callback) {
1072 mContext = windowManagerService.mContext;
Robert Carre625fcf2017-09-01 12:36:28 -07001073 mService = windowManagerService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001074 mCallback = callback;
Robert Carre625fcf2017-09-01 12:36:28 -07001075 mHandler = new MyHandler(mService.mH.getLooper());
Svetoslavf7174e82014-06-12 11:29:35 -07001076 mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration
1077 .getSendRecurringAccessibilityEventsInterval();
Phil Weaverc72faad2018-07-24 10:53:01 -07001078 computeChangedWindows(true);
Svetoslav8e3feb12014-02-24 13:46:47 -08001079 }
1080
Phil Weaverc72faad2018-07-24 10:53:01 -07001081 public void performComputeChangedWindowsNotLocked(boolean forceSend) {
Svetoslav3a0d8782014-12-04 12:50:11 -08001082 mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS);
Phil Weaverc72faad2018-07-24 10:53:01 -07001083 computeChangedWindows(forceSend);
Svetoslav3a0d8782014-12-04 12:50:11 -08001084 }
1085
Svetoslavf7174e82014-06-12 11:29:35 -07001086 public void scheduleComputeChangedWindowsLocked() {
Svetoslav3a0d8782014-12-04 12:50:11 -08001087 if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) {
Svetoslavf7174e82014-06-12 11:29:35 -07001088 mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS,
1089 mRecurringAccessibilityEventsIntervalMillis);
1090 }
1091 }
1092
Phil Weaverc72faad2018-07-24 10:53:01 -07001093 /**
1094 * Check if windows have changed, and send them to the accessibilty subsystem if they have.
1095 *
1096 * @param forceSend Send the windows the accessibility even if they haven't changed.
1097 */
1098 public void computeChangedWindows(boolean forceSend) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001099 if (DEBUG) {
1100 Slog.i(LOG_TAG, "computeChangedWindows()");
1101 }
1102
Svetoslav3a0d8782014-12-04 12:50:11 -08001103 boolean windowsChanged = false;
1104 List<WindowInfo> windows = new ArrayList<WindowInfo>();
1105
Wale Ogunwaledb485de2018-10-29 09:47:07 -07001106 synchronized (mService.mGlobalLock) {
Svetoslavf7174e82014-06-12 11:29:35 -07001107 // Do not send the windows if there is no current focus as
1108 // the window manager is still looking for where to put it.
1109 // We will do the work when we get a focus change callback.
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001110 // TODO(b/112273690): Support multiple displays
1111 if (mService.getDefaultDisplayContentLocked().mCurrentFocus == null) {
Svetoslavf7174e82014-06-12 11:29:35 -07001112 return;
1113 }
1114
Svetoslav8e3feb12014-02-24 13:46:47 -08001115 WindowManager windowManager = (WindowManager)
1116 mContext.getSystemService(Context.WINDOW_SERVICE);
1117 windowManager.getDefaultDisplay().getRealSize(mTempPoint);
1118 final int screenWidth = mTempPoint.x;
1119 final int screenHeight = mTempPoint.y;
1120
1121 Region unaccountedSpace = mTempRegion;
1122 unaccountedSpace.set(0, 0, screenWidth, screenHeight);
1123
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001124 final SparseArray<WindowState> visibleWindows = mTempWindowStates;
Svetoslav8e3feb12014-02-24 13:46:47 -08001125 populateVisibleWindowsOnScreenLocked(visibleWindows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001126 Set<IBinder> addedWindows = mTempBinderSet;
1127 addedWindows.clear();
1128
Svetoslavf7174e82014-06-12 11:29:35 -07001129 boolean focusedWindowAdded = false;
1130
Svetoslav8e3feb12014-02-24 13:46:47 -08001131 final int visibleWindowCount = visibleWindows.size();
Allen Hairf20ac2c2016-02-11 17:42:59 -08001132 HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001133
1134 // Iterate until we figure out what is touchable for the entire screen.
1135 for (int i = visibleWindowCount - 1; i >= 0 && !unaccountedSpace.isEmpty(); i--) {
Alan Viverette9538eea2014-11-13 14:49:20 -08001136 final WindowState windowState = visibleWindows.valueAt(i);
Allen Hairf20ac2c2016-02-11 17:42:59 -08001137
Alan Viverette9538eea2014-11-13 14:49:20 -08001138 final Rect boundsInScreen = mTempRect;
1139 computeWindowBoundsInScreen(windowState, boundsInScreen);
1140
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001141 if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
1142 skipRemainingWindowsForTasks)) {
Eugene Susla18e7fc112018-03-16 14:35:31 -07001143 addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001144 updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
1145 skipRemainingWindowsForTasks);
Svetoslavf7174e82014-06-12 11:29:35 -07001146 }
1147 }
1148
Svetoslav8e3feb12014-02-24 13:46:47 -08001149 // Remove child/parent references to windows that were not added.
1150 final int windowCount = windows.size();
1151 for (int i = 0; i < windowCount; i++) {
1152 WindowInfo window = windows.get(i);
1153 if (!addedWindows.contains(window.parentToken)) {
1154 window.parentToken = null;
1155 }
1156 if (window.childTokens != null) {
1157 final int childTokenCount = window.childTokens.size();
1158 for (int j = childTokenCount - 1; j >= 0; j--) {
1159 if (!addedWindows.contains(window.childTokens.get(j))) {
1160 window.childTokens.remove(j);
1161 }
1162 }
1163 // Leave the child token list if empty.
1164 }
1165 }
1166
1167 visibleWindows.clear();
1168 addedWindows.clear();
1169
Phil Weaverc72faad2018-07-24 10:53:01 -07001170 if (!forceSend) {
1171 // We computed the windows and if they changed notify the client.
1172 if (mOldWindows.size() != windows.size()) {
1173 // Different size means something changed.
1174 windowsChanged = true;
1175 } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) {
1176 // Since we always traverse windows from high to low layer
1177 // the old and new windows at the same index should be the
1178 // same, otherwise something changed.
1179 for (int i = 0; i < windowCount; i++) {
1180 WindowInfo oldWindow = mOldWindows.get(i);
1181 WindowInfo newWindow = windows.get(i);
1182 // We do not care for layer changes given the window
1183 // order does not change. This brings no new information
1184 // to the clients.
1185 if (windowChangedNoLayer(oldWindow, newWindow)) {
1186 windowsChanged = true;
1187 break;
1188 }
Svetoslav8e3feb12014-02-24 13:46:47 -08001189 }
1190 }
1191 }
1192
Phil Weaverc72faad2018-07-24 10:53:01 -07001193 if (forceSend || windowsChanged) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001194 cacheWindows(windows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001195 }
1196 }
Svetoslav3a0d8782014-12-04 12:50:11 -08001197
1198 // Now we do not hold the lock, so send the windows over.
Phil Weaverc72faad2018-07-24 10:53:01 -07001199 if (forceSend || windowsChanged) {
Svetoslav3a0d8782014-12-04 12:50:11 -08001200 if (DEBUG) {
Phil Weaverc72faad2018-07-24 10:53:01 -07001201 Log.i(LOG_TAG, "Windows changed or force sending:" + windows);
Svetoslav3a0d8782014-12-04 12:50:11 -08001202 }
1203 mCallback.onWindowsForAccessibilityChanged(windows);
1204 } else {
1205 if (DEBUG) {
1206 Log.i(LOG_TAG, "No windows changed.");
1207 }
1208 }
1209
1210 // Recycle the windows as we do not need them.
1211 clearAndRecycleWindows(windows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001212 }
1213
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001214 private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
1215 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1216 if (windowState.isFocused()) {
1217 return true;
1218 }
1219
1220 // If the window is part of a task that we're finished with - ignore.
1221 final Task task = windowState.getTask();
1222 if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
1223 return false;
1224 }
1225
1226 // Ignore non-touchable windows, except the split-screen divider, which is
1227 // occasionally non-touchable but still useful for identifying split-screen
1228 // mode.
1229 if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
1230 && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
1231 return false;
1232 }
1233
1234 // If the window is completely covered by other windows - ignore.
1235 if (unaccountedSpace.quickReject(boundsInScreen)) {
1236 return false;
1237 }
1238
1239 // Add windows of certain types not covered by modal windows.
1240 if (isReportedWindowType(windowState.mAttrs.type)) {
1241 return true;
1242 }
1243
1244 return false;
1245 }
1246
1247 private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
1248 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1249 if (windowState.mAttrs.type
1250 != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
1251
1252 // Account for the space this window takes if the window
1253 // is not an accessibility overlay which does not change
1254 // the reported windows.
1255 unaccountedSpace.op(boundsInScreen, unaccountedSpace,
1256 Region.Op.REVERSE_DIFFERENCE);
1257
1258 // If a window is modal it prevents other windows from being touched
1259 if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1260 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
1261 // Account for all space in the task, whether the windows in it are
1262 // touchable or not. The modal window blocks all touches from the task's
1263 // area.
1264 unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
1265 Region.Op.REVERSE_DIFFERENCE);
1266
1267 final Task task = windowState.getTask();
1268 if (task != null) {
1269 // If the window is associated with a particular task, we can skip the
1270 // rest of the windows for that task.
1271 skipRemainingWindowsForTasks.add(task.mTaskId);
1272 } else {
1273 // If the window is not associated with a particular task, then it is
1274 // globally modal. In this case we can skip all remaining windows.
1275 unaccountedSpace.setEmpty();
1276 }
1277 }
1278 }
1279 }
1280
Svetoslavf7174e82014-06-12 11:29:35 -07001281 private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
1282 // Get the touchable frame.
1283 Region touchableRegion = mTempRegion1;
1284 windowState.getTouchableRegion(touchableRegion);
1285 Rect touchableFrame = mTempRect;
1286 touchableRegion.getBounds(touchableFrame);
1287
1288 // Move to origin as all transforms are captured by the matrix.
1289 RectF windowFrame = mTempRectF;
1290 windowFrame.set(touchableFrame);
chaviw492139a2018-07-16 16:07:35 -07001291 windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
Svetoslavf7174e82014-06-12 11:29:35 -07001292
1293 // Map the frame to get what appears on the screen.
1294 Matrix matrix = mTempMatrix;
1295 populateTransformationMatrixLocked(windowState, matrix);
1296 matrix.mapRect(windowFrame);
1297
1298 // Got the bounds.
1299 outBounds.set((int) windowFrame.left, (int) windowFrame.top,
1300 (int) windowFrame.right, (int) windowFrame.bottom);
1301 }
1302
Eugene Susla18e7fc112018-03-16 14:35:31 -07001303 private static void addPopulatedWindowInfo(
1304 WindowState windowState, Rect boundsInScreen,
1305 List<WindowInfo> out, Set<IBinder> tokenOut) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -07001306 final WindowInfo window = windowState.getWindowInfo();
Svetoslavf7174e82014-06-12 11:29:35 -07001307 window.boundsInScreen.set(boundsInScreen);
Eugene Susla18e7fc112018-03-16 14:35:31 -07001308 window.layer = tokenOut.size();
1309 out.add(window);
1310 tokenOut.add(window.token);
Svetoslavf7174e82014-06-12 11:29:35 -07001311 }
1312
Svetoslav8e3feb12014-02-24 13:46:47 -08001313 private void cacheWindows(List<WindowInfo> windows) {
1314 final int oldWindowCount = mOldWindows.size();
1315 for (int i = oldWindowCount - 1; i >= 0; i--) {
1316 mOldWindows.remove(i).recycle();
1317 }
1318 final int newWindowCount = windows.size();
1319 for (int i = 0; i < newWindowCount; i++) {
1320 WindowInfo newWindow = windows.get(i);
1321 mOldWindows.add(WindowInfo.obtain(newWindow));
1322 }
1323 }
1324
1325 private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) {
1326 if (oldWindow == newWindow) {
1327 return false;
1328 }
Svetoslavf7174e82014-06-12 11:29:35 -07001329 if (oldWindow == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001330 return true;
1331 }
Svetoslavf7174e82014-06-12 11:29:35 -07001332 if (newWindow == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001333 return true;
1334 }
1335 if (oldWindow.type != newWindow.type) {
1336 return true;
1337 }
1338 if (oldWindow.focused != newWindow.focused) {
1339 return true;
1340 }
1341 if (oldWindow.token == null) {
1342 if (newWindow.token != null) {
1343 return true;
1344 }
1345 } else if (!oldWindow.token.equals(newWindow.token)) {
1346 return true;
1347 }
1348 if (oldWindow.parentToken == null) {
1349 if (newWindow.parentToken != null) {
1350 return true;
1351 }
1352 } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) {
1353 return true;
1354 }
1355 if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) {
1356 return true;
1357 }
1358 if (oldWindow.childTokens != null && newWindow.childTokens != null
1359 && !oldWindow.childTokens.equals(newWindow.childTokens)) {
1360 return true;
1361 }
Phil Weaver396d5492016-03-22 17:53:50 -07001362 if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
1363 return true;
1364 }
1365 if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
1366 return true;
1367 }
Svetoslav8e3feb12014-02-24 13:46:47 -08001368 return false;
1369 }
1370
Svetoslav3a0d8782014-12-04 12:50:11 -08001371 private static void clearAndRecycleWindows(List<WindowInfo> windows) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001372 final int windowCount = windows.size();
1373 for (int i = windowCount - 1; i >= 0; i--) {
1374 windows.remove(i).recycle();
1375 }
1376 }
1377
1378 private static boolean isReportedWindowType(int windowType) {
Jorim Jaggi73294b62016-10-26 18:02:36 -07001379 return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER
Svetoslav8e3feb12014-02-24 13:46:47 -08001380 && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS
1381 && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY
1382 && windowType != WindowManager.LayoutParams.TYPE_DRAG
Selim Cinekf83e8242015-05-19 18:08:14 -07001383 && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER
Svetoslav8e3feb12014-02-24 13:46:47 -08001384 && windowType != WindowManager.LayoutParams.TYPE_POINTER
Phil Weaverd321075e2017-06-13 09:13:35 -07001385 && windowType != TYPE_MAGNIFICATION_OVERLAY
Svetoslav8e3feb12014-02-24 13:46:47 -08001386 && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
1387 && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
1388 && windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
1389 }
1390
1391 private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Robert Carre625fcf2017-09-01 12:36:28 -07001392 final DisplayContent dc = mService.getDefaultDisplayContentLocked();
Robert Carrb1579c82017-09-05 14:54:47 -07001393 mTempLayer = 0;
Wale Ogunwaled1880962016-11-08 10:31:59 -08001394 dc.forAllWindows((w) -> {
1395 if (w.isVisibleLw()) {
Robert Carrb1579c82017-09-05 14:54:47 -07001396 outWindows.put(mTempLayer++, w);
Svetoslav8e3feb12014-02-24 13:46:47 -08001397 }
Wale Ogunwaled1880962016-11-08 10:31:59 -08001398 }, false /* traverseTopToBottom */ );
Svetoslav8e3feb12014-02-24 13:46:47 -08001399 }
1400
1401 private class MyHandler extends Handler {
Svetoslavf7174e82014-06-12 11:29:35 -07001402 public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -08001403
1404 public MyHandler(Looper looper) {
1405 super(looper, null, false);
1406 }
1407
1408 @Override
1409 @SuppressWarnings("unchecked")
1410 public void handleMessage(Message message) {
1411 switch (message.what) {
Svetoslavf7174e82014-06-12 11:29:35 -07001412 case MESSAGE_COMPUTE_CHANGED_WINDOWS: {
Phil Weaverc72faad2018-07-24 10:53:01 -07001413 computeChangedWindows(false);
Svetoslavf7174e82014-06-12 11:29:35 -07001414 } break;
Svetoslav8e3feb12014-02-24 13:46:47 -08001415 }
1416 }
1417 }
1418 }
1419}