blob: 545b69b2fd54556ca2126f00e90984e59e11f50f [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
Phil Weaver65c06702016-03-15 15:33:46 -0700610 // Update accounted bounds
Svetoslav8e3feb12014-02-24 13:46:47 -0800611 Region accountedBounds = mTempRegion2;
Phil Weaver70439242016-03-10 15:15:49 -0800612 accountedBounds.set(mMagnificationRegion);
Svetoslav8e3feb12014-02-24 13:46:47 -0800613 accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
614 accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
615
616 if (accountedBounds.isRect()) {
617 Rect accountedFrame = mTempRect1;
618 accountedBounds.getBounds(accountedFrame);
619 if (accountedFrame.width() == screenWidth
620 && accountedFrame.height() == screenHeight) {
621 break;
622 }
623 }
624 }
625
626 visibleWindows.clear();
627
Phil Weaver70439242016-03-10 15:15:49 -0800628 mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
Svetoslav7505e332014-08-22 12:14:28 -0700629 screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
Svetoslav8e3feb12014-02-24 13:46:47 -0800630 Region.Op.INTERSECT);
631
Phil Weaver70439242016-03-10 15:15:49 -0800632 final boolean magnifiedChanged =
633 !mOldMagnificationRegion.equals(mMagnificationRegion);
634 if (magnifiedChanged) {
635 mWindow.setBounds(mMagnificationRegion);
636 final Rect dirtyRect = mTempRect1;
637 if (mFullRedrawNeeded) {
638 mFullRedrawNeeded = false;
639 dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
640 screenWidth - mDrawBorderInset,
641 screenHeight - mDrawBorderInset);
642 mWindow.invalidate(dirtyRect);
643 } else {
644 final Region dirtyRegion = mTempRegion3;
645 dirtyRegion.set(mMagnificationRegion);
646 dirtyRegion.op(mOldMagnificationRegion, Region.Op.UNION);
647 dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
648 dirtyRegion.getBounds(dirtyRect);
649 mWindow.invalidate(dirtyRect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800650 }
651
Phil Weaver70439242016-03-10 15:15:49 -0800652 mOldMagnificationRegion.set(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500653 final SomeArgs args = SomeArgs.obtain();
Phil Weaver70439242016-03-10 15:15:49 -0800654 args.arg1 = Region.obtain(mMagnificationRegion);
Alan Viverette214fb682015-11-17 09:47:11 -0500655 mHandler.obtainMessage(
Phil Weaver70439242016-03-10 15:15:49 -0800656 MyHandler.MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED, args)
657 .sendToTarget();
Svetoslav8e3feb12014-02-24 13:46:47 -0800658 }
659 }
660
661 public void onRotationChangedLocked() {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800662 // If we are showing the magnification border, hide it immediately so
Svetoslav8e3feb12014-02-24 13:46:47 -0800663 // the user does not see strange artifacts during rotation. The screenshot
Casey Burkhardt74922c62017-02-13 12:43:16 -0800664 // used for rotation already has the border. After the rotation is complete
Svetoslav8e3feb12014-02-24 13:46:47 -0800665 // we will show the border.
Casey Burkhardt74922c62017-02-13 12:43:16 -0800666 if (isMagnifyingLocked() || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800667 setMagnifiedRegionBorderShownLocked(false, false);
668 final long delay = (long) (mLongAnimationDuration
Robert Carre625fcf2017-09-01 12:36:28 -0700669 * mService.getWindowAnimationScaleLocked());
Svetoslav8e3feb12014-02-24 13:46:47 -0800670 Message message = mHandler.obtainMessage(
671 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED);
672 mHandler.sendMessageDelayed(message, delay);
673 }
674 recomputeBoundsLocked();
675 mWindow.updateSize();
676 }
677
678 public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
679 if (shown) {
680 mFullRedrawNeeded = true;
Phil Weaver70439242016-03-10 15:15:49 -0800681 mOldMagnificationRegion.set(0, 0, 0, 0);
Svetoslav8e3feb12014-02-24 13:46:47 -0800682 }
683 mWindow.setShown(shown, animate);
684 }
685
686 public void getMagnifiedFrameInContentCoordsLocked(Rect rect) {
687 MagnificationSpec spec = mMagnificationSpec;
Phil Weaver70439242016-03-10 15:15:49 -0800688 mMagnificationRegion.getBounds(rect);
Svetoslav8e3feb12014-02-24 13:46:47 -0800689 rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
690 rect.scale(1.0f / spec.scale);
691 }
692
693 public boolean isMagnifyingLocked() {
694 return mMagnificationSpec.scale > 1.0f;
695 }
696
697 public MagnificationSpec getMagnificationSpecLocked() {
698 return mMagnificationSpec;
699 }
700
701 /** NOTE: This has to be called within a surface transaction. */
702 public void drawWindowIfNeededLocked() {
703 recomputeBoundsLocked();
704 mWindow.drawIfNeeded();
705 }
706
707 public void destroyWindow() {
708 mWindow.releaseSurface();
709 }
710
711 private void populateWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Robert Carrb1579c82017-09-05 14:54:47 -0700712 mTempLayer = 0;
Rhed Jao02655dc2018-10-30 20:44:52 +0800713 mDisplayContent.forAllWindows((w) -> {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800714 if (w.isOnScreen() && w.isVisibleLw()
Phil Weaverd6ce7372018-05-18 09:48:01 -0700715 && (w.mAttrs.alpha != 0)
Wale Ogunwaled1880962016-11-08 10:31:59 -0800716 && !w.mWinAnimator.mEnterAnimationPending) {
Robert Carrb1579c82017-09-05 14:54:47 -0700717 mTempLayer++;
718 outWindows.put(mTempLayer, w);
Svetoslav8e3feb12014-02-24 13:46:47 -0800719 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800720 }, false /* traverseTopToBottom */ );
Svetoslav8e3feb12014-02-24 13:46:47 -0800721 }
722
723 private final class ViewportWindow {
724 private static final String SURFACE_TITLE = "Magnification Overlay";
725
Svetoslav8e3feb12014-02-24 13:46:47 -0800726 private final Region mBounds = new Region();
727 private final Rect mDirtyRect = new Rect();
728 private final Paint mPaint = new Paint();
729
Svetoslav8e3feb12014-02-24 13:46:47 -0800730 private final SurfaceControl mSurfaceControl;
731 private final Surface mSurface = new Surface();
732
Svet Ganovb21df802014-09-01 19:06:33 -0700733 private final AnimationController mAnimationController;
734
Svetoslav8e3feb12014-02-24 13:46:47 -0800735 private boolean mShown;
736 private int mAlpha;
737
738 private boolean mInvalidated;
739
740 public ViewportWindow(Context context) {
741 SurfaceControl surfaceControl = null;
742 try {
Rhed Jao02655dc2018-10-30 20:44:52 +0800743 mDisplay.getRealSize(mTempPoint);
744 surfaceControl = mDisplayContent
745 .makeOverlay()
Robert Carre625fcf2017-09-01 12:36:28 -0700746 .setName(SURFACE_TITLE)
Vishnu Naire86bd982018-11-28 13:23:17 -0800747 .setBufferSize(mTempPoint.x, mTempPoint.y) // not a typo
Robert Carre625fcf2017-09-01 12:36:28 -0700748 .setFormat(PixelFormat.TRANSLUCENT)
749 .build();
Svetoslav8e3feb12014-02-24 13:46:47 -0800750 } catch (OutOfResourcesException oore) {
751 /* ignore */
752 }
753 mSurfaceControl = surfaceControl;
Robert Carre625fcf2017-09-01 12:36:28 -0700754 mSurfaceControl.setLayer(mService.mPolicy.getWindowLayerFromTypeLw(
Phil Weaverd321075e2017-06-13 09:13:35 -0700755 TYPE_MAGNIFICATION_OVERLAY)
Svetoslav8e3feb12014-02-24 13:46:47 -0800756 * WindowManagerService.TYPE_LAYER_MULTIPLIER);
757 mSurfaceControl.setPosition(0, 0);
758 mSurface.copyFrom(mSurfaceControl);
759
Svet Ganovb21df802014-09-01 19:06:33 -0700760 mAnimationController = new AnimationController(context,
Robert Carre625fcf2017-09-01 12:36:28 -0700761 mService.mH.getLooper());
Svet Ganovb21df802014-09-01 19:06:33 -0700762
Svetoslav8e3feb12014-02-24 13:46:47 -0800763 TypedValue typedValue = new TypedValue();
764 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
765 typedValue, true);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700766 final int borderColor = context.getColor(typedValue.resourceId);
Svetoslav8e3feb12014-02-24 13:46:47 -0800767
768 mPaint.setStyle(Paint.Style.STROKE);
769 mPaint.setStrokeWidth(mBorderWidth);
770 mPaint.setColor(borderColor);
771
Svetoslav8e3feb12014-02-24 13:46:47 -0800772 mInvalidated = true;
773 }
774
775 public void setShown(boolean shown, boolean animate) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700776 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800777 if (mShown == shown) {
778 return;
779 }
780 mShown = shown;
Svet Ganovb21df802014-09-01 19:06:33 -0700781 mAnimationController.onFrameShownStateChanged(shown, animate);
Svetoslav8e3feb12014-02-24 13:46:47 -0800782 if (DEBUG_VIEWPORT_WINDOW) {
783 Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
784 }
785 }
786 }
787
788 @SuppressWarnings("unused")
789 // Called reflectively from an animator.
790 public int getAlpha() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700791 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800792 return mAlpha;
793 }
794 }
795
796 public void setAlpha(int alpha) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700797 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800798 if (mAlpha == alpha) {
799 return;
800 }
801 mAlpha = alpha;
802 invalidate(null);
803 if (DEBUG_VIEWPORT_WINDOW) {
804 Slog.i(LOG_TAG, "ViewportWindow set alpha: " + alpha);
805 }
806 }
807 }
808
809 public void setBounds(Region bounds) {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700810 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800811 if (mBounds.equals(bounds)) {
812 return;
813 }
814 mBounds.set(bounds);
815 invalidate(mDirtyRect);
816 if (DEBUG_VIEWPORT_WINDOW) {
817 Slog.i(LOG_TAG, "ViewportWindow set bounds: " + bounds);
818 }
819 }
820 }
821
822 public void updateSize() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700823 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800824 mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
Vishnu Naire86bd982018-11-28 13:23:17 -0800825 mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
Svetoslav8e3feb12014-02-24 13:46:47 -0800826 invalidate(mDirtyRect);
827 }
828 }
829
830 public void invalidate(Rect dirtyRect) {
831 if (dirtyRect != null) {
832 mDirtyRect.set(dirtyRect);
833 } else {
834 mDirtyRect.setEmpty();
835 }
836 mInvalidated = true;
Robert Carre625fcf2017-09-01 12:36:28 -0700837 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800838 }
839
840 /** NOTE: This has to be called within a surface transaction. */
841 public void drawIfNeeded() {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700842 synchronized (mService.mGlobalLock) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800843 if (!mInvalidated) {
844 return;
845 }
846 mInvalidated = false;
Svetoslav8e3feb12014-02-24 13:46:47 -0800847 if (mAlpha > 0) {
Adrian Roos69364f52018-04-19 18:49:39 +0200848 Canvas canvas = null;
849 try {
850 // Empty dirty rectangle means unspecified.
851 if (mDirtyRect.isEmpty()) {
852 mBounds.getBounds(mDirtyRect);
853 }
854 mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
855 canvas = mSurface.lockCanvas(mDirtyRect);
856 if (DEBUG_VIEWPORT_WINDOW) {
857 Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
858 }
859 } catch (IllegalArgumentException iae) {
860 /* ignore */
861 } catch (Surface.OutOfResourcesException oore) {
862 /* ignore */
863 }
864 if (canvas == null) {
865 return;
866 }
867 if (DEBUG_VIEWPORT_WINDOW) {
868 Slog.i(LOG_TAG, "Bounds: " + mBounds);
869 }
870 canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
871 mPaint.setAlpha(mAlpha);
872 Path path = mBounds.getBoundaryPath();
873 canvas.drawPath(path, mPaint);
874
875 mSurface.unlockCanvasAndPost(canvas);
Svetoslav8e3feb12014-02-24 13:46:47 -0800876 mSurfaceControl.show();
877 } else {
878 mSurfaceControl.hide();
879 }
880 }
881 }
882
883 public void releaseSurface() {
884 mSurfaceControl.release();
885 mSurface.release();
886 }
Svet Ganovb21df802014-09-01 19:06:33 -0700887
888 private final class AnimationController extends Handler {
889 private static final String PROPERTY_NAME_ALPHA = "alpha";
890
891 private static final int MIN_ALPHA = 0;
892 private static final int MAX_ALPHA = 255;
893
894 private static final int MSG_FRAME_SHOWN_STATE_CHANGED = 1;
895
896 private final ValueAnimator mShowHideFrameAnimator;
897
898 public AnimationController(Context context, Looper looper) {
899 super(looper);
900 mShowHideFrameAnimator = ObjectAnimator.ofInt(ViewportWindow.this,
901 PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA);
902
903 Interpolator interpolator = new DecelerateInterpolator(2.5f);
904 final long longAnimationDuration = context.getResources().getInteger(
905 com.android.internal.R.integer.config_longAnimTime);
906
907 mShowHideFrameAnimator.setInterpolator(interpolator);
908 mShowHideFrameAnimator.setDuration(longAnimationDuration);
909 }
910
911 public void onFrameShownStateChanged(boolean shown, boolean animate) {
912 obtainMessage(MSG_FRAME_SHOWN_STATE_CHANGED,
913 shown ? 1 : 0, animate ? 1 : 0).sendToTarget();
914 }
915
916 @Override
917 public void handleMessage(Message message) {
918 switch (message.what) {
919 case MSG_FRAME_SHOWN_STATE_CHANGED: {
920 final boolean shown = message.arg1 == 1;
921 final boolean animate = message.arg2 == 1;
922
923 if (animate) {
924 if (mShowHideFrameAnimator.isRunning()) {
925 mShowHideFrameAnimator.reverse();
926 } else {
927 if (shown) {
928 mShowHideFrameAnimator.start();
929 } else {
930 mShowHideFrameAnimator.reverse();
931 }
932 }
933 } else {
934 mShowHideFrameAnimator.cancel();
935 if (shown) {
936 setAlpha(MAX_ALPHA);
937 } else {
938 setAlpha(MIN_ALPHA);
939 }
940 }
941 } break;
942 }
943 }
944 }
Svetoslav8e3feb12014-02-24 13:46:47 -0800945 }
946 }
947
948 private class MyHandler extends Handler {
Phil Weaver70439242016-03-10 15:15:49 -0800949 public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -0800950 public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
951 public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
952 public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
953 public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
954
955 public MyHandler(Looper looper) {
956 super(looper);
957 }
958
959 @Override
960 public void handleMessage(Message message) {
961 switch (message.what) {
Phil Weaver70439242016-03-10 15:15:49 -0800962 case MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED: {
Alan Viverette214fb682015-11-17 09:47:11 -0500963 final SomeArgs args = (SomeArgs) message.obj;
964 final Region magnifiedBounds = (Region) args.arg1;
Phil Weaver70439242016-03-10 15:15:49 -0800965 mCallbacks.onMagnificationRegionChanged(magnifiedBounds);
Alan Viverette214fb682015-11-17 09:47:11 -0500966 magnifiedBounds.recycle();
Svetoslav8e3feb12014-02-24 13:46:47 -0800967 } break;
968
969 case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
970 SomeArgs args = (SomeArgs) message.obj;
971 final int left = args.argi1;
972 final int top = args.argi2;
973 final int right = args.argi3;
974 final int bottom = args.argi4;
975 mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom);
976 args.recycle();
977 } break;
978
979 case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: {
980 mCallbacks.onUserContextChanged();
981 } break;
982
983 case MESSAGE_NOTIFY_ROTATION_CHANGED: {
984 final int rotation = message.arg1;
985 mCallbacks.onRotationChanged(rotation);
986 } break;
987
988 case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : {
Wale Ogunwaledb485de2018-10-29 09:47:07 -0700989 synchronized (mService.mGlobalLock) {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800990 if (mMagnifedViewport.isMagnifyingLocked()
991 || isForceShowingMagnifiableBoundsLocked()) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800992 mMagnifedViewport.setMagnifiedRegionBorderShownLocked(true, true);
Robert Carre625fcf2017-09-01 12:36:28 -0700993 mService.scheduleAnimationLocked();
Svetoslav8e3feb12014-02-24 13:46:47 -0800994 }
995 }
996 } break;
997 }
998 }
999 }
1000 }
1001
1002 /**
1003 * This class encapsulates the functionality related to computing the windows
1004 * reported for accessibility purposes. These windows are all windows a sighted
1005 * user can see on the screen.
1006 */
1007 private static final class WindowsForAccessibilityObserver {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -08001008 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ?
1009 "WindowsForAccessibilityObserver" : TAG_WM;
Svetoslav8e3feb12014-02-24 13:46:47 -08001010
1011 private static final boolean DEBUG = false;
1012
1013 private final SparseArray<WindowState> mTempWindowStates =
1014 new SparseArray<WindowState>();
1015
1016 private final List<WindowInfo> mOldWindows = new ArrayList<WindowInfo>();
1017
1018 private final Set<IBinder> mTempBinderSet = new ArraySet<IBinder>();
1019
1020 private final RectF mTempRectF = new RectF();
1021
1022 private final Matrix mTempMatrix = new Matrix();
1023
1024 private final Point mTempPoint = new Point();
1025
1026 private final Rect mTempRect = new Rect();
1027
1028 private final Region mTempRegion = new Region();
1029
1030 private final Region mTempRegion1 = new Region();
1031
1032 private final Context mContext;
1033
Robert Carre625fcf2017-09-01 12:36:28 -07001034 private final WindowManagerService mService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001035
1036 private final Handler mHandler;
1037
1038 private final WindowsForAccessibilityCallback mCallback;
1039
Svetoslavf7174e82014-06-12 11:29:35 -07001040 private final long mRecurringAccessibilityEventsIntervalMillis;
1041
Robert Carrb1579c82017-09-05 14:54:47 -07001042 private int mTempLayer = 0;
1043
Svetoslav8e3feb12014-02-24 13:46:47 -08001044 public WindowsForAccessibilityObserver(WindowManagerService windowManagerService,
1045 WindowsForAccessibilityCallback callback) {
1046 mContext = windowManagerService.mContext;
Robert Carre625fcf2017-09-01 12:36:28 -07001047 mService = windowManagerService;
Svetoslav8e3feb12014-02-24 13:46:47 -08001048 mCallback = callback;
Robert Carre625fcf2017-09-01 12:36:28 -07001049 mHandler = new MyHandler(mService.mH.getLooper());
Svetoslavf7174e82014-06-12 11:29:35 -07001050 mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration
1051 .getSendRecurringAccessibilityEventsInterval();
Phil Weaverc72faad2018-07-24 10:53:01 -07001052 computeChangedWindows(true);
Svetoslav8e3feb12014-02-24 13:46:47 -08001053 }
1054
Phil Weaverc72faad2018-07-24 10:53:01 -07001055 public void performComputeChangedWindowsNotLocked(boolean forceSend) {
Svetoslav3a0d8782014-12-04 12:50:11 -08001056 mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS);
Phil Weaverc72faad2018-07-24 10:53:01 -07001057 computeChangedWindows(forceSend);
Svetoslav3a0d8782014-12-04 12:50:11 -08001058 }
1059
Svetoslavf7174e82014-06-12 11:29:35 -07001060 public void scheduleComputeChangedWindowsLocked() {
Svetoslav3a0d8782014-12-04 12:50:11 -08001061 if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) {
Svetoslavf7174e82014-06-12 11:29:35 -07001062 mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS,
1063 mRecurringAccessibilityEventsIntervalMillis);
1064 }
1065 }
1066
Phil Weaverc72faad2018-07-24 10:53:01 -07001067 /**
1068 * Check if windows have changed, and send them to the accessibilty subsystem if they have.
1069 *
1070 * @param forceSend Send the windows the accessibility even if they haven't changed.
1071 */
1072 public void computeChangedWindows(boolean forceSend) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001073 if (DEBUG) {
1074 Slog.i(LOG_TAG, "computeChangedWindows()");
1075 }
1076
Svetoslav3a0d8782014-12-04 12:50:11 -08001077 boolean windowsChanged = false;
1078 List<WindowInfo> windows = new ArrayList<WindowInfo>();
1079
Wale Ogunwaledb485de2018-10-29 09:47:07 -07001080 synchronized (mService.mGlobalLock) {
Svetoslavf7174e82014-06-12 11:29:35 -07001081 // Do not send the windows if there is no current focus as
1082 // the window manager is still looking for where to put it.
1083 // We will do the work when we get a focus change callback.
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001084 // TODO(b/112273690): Support multiple displays
1085 if (mService.getDefaultDisplayContentLocked().mCurrentFocus == null) {
Svetoslavf7174e82014-06-12 11:29:35 -07001086 return;
1087 }
1088
Svetoslav8e3feb12014-02-24 13:46:47 -08001089 WindowManager windowManager = (WindowManager)
1090 mContext.getSystemService(Context.WINDOW_SERVICE);
1091 windowManager.getDefaultDisplay().getRealSize(mTempPoint);
1092 final int screenWidth = mTempPoint.x;
1093 final int screenHeight = mTempPoint.y;
1094
1095 Region unaccountedSpace = mTempRegion;
1096 unaccountedSpace.set(0, 0, screenWidth, screenHeight);
1097
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001098 final SparseArray<WindowState> visibleWindows = mTempWindowStates;
Svetoslav8e3feb12014-02-24 13:46:47 -08001099 populateVisibleWindowsOnScreenLocked(visibleWindows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001100 Set<IBinder> addedWindows = mTempBinderSet;
1101 addedWindows.clear();
1102
Svetoslavf7174e82014-06-12 11:29:35 -07001103 boolean focusedWindowAdded = false;
1104
Svetoslav8e3feb12014-02-24 13:46:47 -08001105 final int visibleWindowCount = visibleWindows.size();
Allen Hairf20ac2c2016-02-11 17:42:59 -08001106 HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001107
1108 // Iterate until we figure out what is touchable for the entire screen.
1109 for (int i = visibleWindowCount - 1; i >= 0 && !unaccountedSpace.isEmpty(); i--) {
Alan Viverette9538eea2014-11-13 14:49:20 -08001110 final WindowState windowState = visibleWindows.valueAt(i);
Allen Hairf20ac2c2016-02-11 17:42:59 -08001111
Alan Viverette9538eea2014-11-13 14:49:20 -08001112 final Rect boundsInScreen = mTempRect;
1113 computeWindowBoundsInScreen(windowState, boundsInScreen);
1114
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001115 if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
1116 skipRemainingWindowsForTasks)) {
Eugene Susla18e7fc112018-03-16 14:35:31 -07001117 addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001118 updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
1119 skipRemainingWindowsForTasks);
Svetoslavf7174e82014-06-12 11:29:35 -07001120 }
1121 }
1122
Svetoslav8e3feb12014-02-24 13:46:47 -08001123 // Remove child/parent references to windows that were not added.
1124 final int windowCount = windows.size();
1125 for (int i = 0; i < windowCount; i++) {
1126 WindowInfo window = windows.get(i);
1127 if (!addedWindows.contains(window.parentToken)) {
1128 window.parentToken = null;
1129 }
1130 if (window.childTokens != null) {
1131 final int childTokenCount = window.childTokens.size();
1132 for (int j = childTokenCount - 1; j >= 0; j--) {
1133 if (!addedWindows.contains(window.childTokens.get(j))) {
1134 window.childTokens.remove(j);
1135 }
1136 }
1137 // Leave the child token list if empty.
1138 }
1139 }
1140
1141 visibleWindows.clear();
1142 addedWindows.clear();
1143
Phil Weaverc72faad2018-07-24 10:53:01 -07001144 if (!forceSend) {
1145 // We computed the windows and if they changed notify the client.
1146 if (mOldWindows.size() != windows.size()) {
1147 // Different size means something changed.
1148 windowsChanged = true;
1149 } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) {
1150 // Since we always traverse windows from high to low layer
1151 // the old and new windows at the same index should be the
1152 // same, otherwise something changed.
1153 for (int i = 0; i < windowCount; i++) {
1154 WindowInfo oldWindow = mOldWindows.get(i);
1155 WindowInfo newWindow = windows.get(i);
1156 // We do not care for layer changes given the window
1157 // order does not change. This brings no new information
1158 // to the clients.
1159 if (windowChangedNoLayer(oldWindow, newWindow)) {
1160 windowsChanged = true;
1161 break;
1162 }
Svetoslav8e3feb12014-02-24 13:46:47 -08001163 }
1164 }
1165 }
1166
Phil Weaverc72faad2018-07-24 10:53:01 -07001167 if (forceSend || windowsChanged) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001168 cacheWindows(windows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001169 }
1170 }
Svetoslav3a0d8782014-12-04 12:50:11 -08001171
1172 // Now we do not hold the lock, so send the windows over.
Phil Weaverc72faad2018-07-24 10:53:01 -07001173 if (forceSend || windowsChanged) {
Svetoslav3a0d8782014-12-04 12:50:11 -08001174 if (DEBUG) {
Phil Weaverc72faad2018-07-24 10:53:01 -07001175 Log.i(LOG_TAG, "Windows changed or force sending:" + windows);
Svetoslav3a0d8782014-12-04 12:50:11 -08001176 }
1177 mCallback.onWindowsForAccessibilityChanged(windows);
1178 } else {
1179 if (DEBUG) {
1180 Log.i(LOG_TAG, "No windows changed.");
1181 }
1182 }
1183
1184 // Recycle the windows as we do not need them.
1185 clearAndRecycleWindows(windows);
Svetoslav8e3feb12014-02-24 13:46:47 -08001186 }
1187
Qasid Ahmad Sadiq5e1c1ca2019-01-03 21:55:55 -08001188 private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
1189 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1190 if (windowState.isFocused()) {
1191 return true;
1192 }
1193
1194 // If the window is part of a task that we're finished with - ignore.
1195 final Task task = windowState.getTask();
1196 if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
1197 return false;
1198 }
1199
1200 // Ignore non-touchable windows, except the split-screen divider, which is
1201 // occasionally non-touchable but still useful for identifying split-screen
1202 // mode.
1203 if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
1204 && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
1205 return false;
1206 }
1207
1208 // If the window is completely covered by other windows - ignore.
1209 if (unaccountedSpace.quickReject(boundsInScreen)) {
1210 return false;
1211 }
1212
1213 // Add windows of certain types not covered by modal windows.
1214 if (isReportedWindowType(windowState.mAttrs.type)) {
1215 return true;
1216 }
1217
1218 return false;
1219 }
1220
1221 private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
1222 Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
1223 if (windowState.mAttrs.type
1224 != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
1225
1226 // Account for the space this window takes if the window
1227 // is not an accessibility overlay which does not change
1228 // the reported windows.
1229 unaccountedSpace.op(boundsInScreen, unaccountedSpace,
1230 Region.Op.REVERSE_DIFFERENCE);
1231
1232 // If a window is modal it prevents other windows from being touched
1233 if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1234 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
1235 // Account for all space in the task, whether the windows in it are
1236 // touchable or not. The modal window blocks all touches from the task's
1237 // area.
1238 unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
1239 Region.Op.REVERSE_DIFFERENCE);
1240
1241 final Task task = windowState.getTask();
1242 if (task != null) {
1243 // If the window is associated with a particular task, we can skip the
1244 // rest of the windows for that task.
1245 skipRemainingWindowsForTasks.add(task.mTaskId);
1246 } else {
1247 // If the window is not associated with a particular task, then it is
1248 // globally modal. In this case we can skip all remaining windows.
1249 unaccountedSpace.setEmpty();
1250 }
1251 }
1252 }
1253 }
1254
Svetoslavf7174e82014-06-12 11:29:35 -07001255 private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
1256 // Get the touchable frame.
1257 Region touchableRegion = mTempRegion1;
1258 windowState.getTouchableRegion(touchableRegion);
1259 Rect touchableFrame = mTempRect;
1260 touchableRegion.getBounds(touchableFrame);
1261
1262 // Move to origin as all transforms are captured by the matrix.
1263 RectF windowFrame = mTempRectF;
1264 windowFrame.set(touchableFrame);
chaviw492139a2018-07-16 16:07:35 -07001265 windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
Svetoslavf7174e82014-06-12 11:29:35 -07001266
1267 // Map the frame to get what appears on the screen.
1268 Matrix matrix = mTempMatrix;
1269 populateTransformationMatrixLocked(windowState, matrix);
1270 matrix.mapRect(windowFrame);
1271
1272 // Got the bounds.
1273 outBounds.set((int) windowFrame.left, (int) windowFrame.top,
1274 (int) windowFrame.right, (int) windowFrame.bottom);
1275 }
1276
Eugene Susla18e7fc112018-03-16 14:35:31 -07001277 private static void addPopulatedWindowInfo(
1278 WindowState windowState, Rect boundsInScreen,
1279 List<WindowInfo> out, Set<IBinder> tokenOut) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -07001280 final WindowInfo window = windowState.getWindowInfo();
Svetoslavf7174e82014-06-12 11:29:35 -07001281 window.boundsInScreen.set(boundsInScreen);
Eugene Susla18e7fc112018-03-16 14:35:31 -07001282 window.layer = tokenOut.size();
1283 out.add(window);
1284 tokenOut.add(window.token);
Svetoslavf7174e82014-06-12 11:29:35 -07001285 }
1286
Svetoslav8e3feb12014-02-24 13:46:47 -08001287 private void cacheWindows(List<WindowInfo> windows) {
1288 final int oldWindowCount = mOldWindows.size();
1289 for (int i = oldWindowCount - 1; i >= 0; i--) {
1290 mOldWindows.remove(i).recycle();
1291 }
1292 final int newWindowCount = windows.size();
1293 for (int i = 0; i < newWindowCount; i++) {
1294 WindowInfo newWindow = windows.get(i);
1295 mOldWindows.add(WindowInfo.obtain(newWindow));
1296 }
1297 }
1298
1299 private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) {
1300 if (oldWindow == newWindow) {
1301 return false;
1302 }
Svetoslavf7174e82014-06-12 11:29:35 -07001303 if (oldWindow == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001304 return true;
1305 }
Svetoslavf7174e82014-06-12 11:29:35 -07001306 if (newWindow == null) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001307 return true;
1308 }
1309 if (oldWindow.type != newWindow.type) {
1310 return true;
1311 }
1312 if (oldWindow.focused != newWindow.focused) {
1313 return true;
1314 }
1315 if (oldWindow.token == null) {
1316 if (newWindow.token != null) {
1317 return true;
1318 }
1319 } else if (!oldWindow.token.equals(newWindow.token)) {
1320 return true;
1321 }
1322 if (oldWindow.parentToken == null) {
1323 if (newWindow.parentToken != null) {
1324 return true;
1325 }
1326 } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) {
1327 return true;
1328 }
1329 if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) {
1330 return true;
1331 }
1332 if (oldWindow.childTokens != null && newWindow.childTokens != null
1333 && !oldWindow.childTokens.equals(newWindow.childTokens)) {
1334 return true;
1335 }
Phil Weaver396d5492016-03-22 17:53:50 -07001336 if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
1337 return true;
1338 }
1339 if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
1340 return true;
1341 }
Svetoslav8e3feb12014-02-24 13:46:47 -08001342 return false;
1343 }
1344
Svetoslav3a0d8782014-12-04 12:50:11 -08001345 private static void clearAndRecycleWindows(List<WindowInfo> windows) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001346 final int windowCount = windows.size();
1347 for (int i = windowCount - 1; i >= 0; i--) {
1348 windows.remove(i).recycle();
1349 }
1350 }
1351
1352 private static boolean isReportedWindowType(int windowType) {
Jorim Jaggi73294b62016-10-26 18:02:36 -07001353 return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER
Svetoslav8e3feb12014-02-24 13:46:47 -08001354 && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS
1355 && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY
1356 && windowType != WindowManager.LayoutParams.TYPE_DRAG
Selim Cinekf83e8242015-05-19 18:08:14 -07001357 && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER
Svetoslav8e3feb12014-02-24 13:46:47 -08001358 && windowType != WindowManager.LayoutParams.TYPE_POINTER
Phil Weaverd321075e2017-06-13 09:13:35 -07001359 && windowType != TYPE_MAGNIFICATION_OVERLAY
Svetoslav8e3feb12014-02-24 13:46:47 -08001360 && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
1361 && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
1362 && windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
1363 }
1364
1365 private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
Robert Carre625fcf2017-09-01 12:36:28 -07001366 final DisplayContent dc = mService.getDefaultDisplayContentLocked();
Robert Carrb1579c82017-09-05 14:54:47 -07001367 mTempLayer = 0;
Wale Ogunwaled1880962016-11-08 10:31:59 -08001368 dc.forAllWindows((w) -> {
1369 if (w.isVisibleLw()) {
Robert Carrb1579c82017-09-05 14:54:47 -07001370 outWindows.put(mTempLayer++, w);
Svetoslav8e3feb12014-02-24 13:46:47 -08001371 }
Wale Ogunwaled1880962016-11-08 10:31:59 -08001372 }, false /* traverseTopToBottom */ );
Svetoslav8e3feb12014-02-24 13:46:47 -08001373 }
1374
1375 private class MyHandler extends Handler {
Svetoslavf7174e82014-06-12 11:29:35 -07001376 public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1;
Svetoslav8e3feb12014-02-24 13:46:47 -08001377
1378 public MyHandler(Looper looper) {
1379 super(looper, null, false);
1380 }
1381
1382 @Override
1383 @SuppressWarnings("unchecked")
1384 public void handleMessage(Message message) {
1385 switch (message.what) {
Svetoslavf7174e82014-06-12 11:29:35 -07001386 case MESSAGE_COMPUTE_CHANGED_WINDOWS: {
Phil Weaverc72faad2018-07-24 10:53:01 -07001387 computeChangedWindows(false);
Svetoslavf7174e82014-06-12 11:29:35 -07001388 } break;
Svetoslav8e3feb12014-02-24 13:46:47 -08001389 }
1390 }
1391 }
1392 }
1393}