1 /* 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 17 package com.android.server.wm; 18 19 import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CALLBACK; 20 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK; 21 import static android.os.Build.IS_USER; 22 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; 23 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; 24 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; 25 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; 26 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 27 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 28 29 import static com.android.server.accessibility.AccessibilityTraceFileProto.ENTRY; 30 import static com.android.server.accessibility.AccessibilityTraceFileProto.MAGIC_NUMBER; 31 import static com.android.server.accessibility.AccessibilityTraceFileProto.MAGIC_NUMBER_H; 32 import static com.android.server.accessibility.AccessibilityTraceFileProto.MAGIC_NUMBER_L; 33 import static com.android.server.accessibility.AccessibilityTraceProto.ACCESSIBILITY_SERVICE; 34 import static com.android.server.accessibility.AccessibilityTraceProto.CALENDAR_TIME; 35 import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_PARAMS; 36 import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_PKG; 37 import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_STACKS; 38 import static com.android.server.accessibility.AccessibilityTraceProto.CPU_STATS; 39 import static com.android.server.accessibility.AccessibilityTraceProto.ELAPSED_REALTIME_NANOS; 40 import static com.android.server.accessibility.AccessibilityTraceProto.LOGGING_TYPE; 41 import static com.android.server.accessibility.AccessibilityTraceProto.PROCESS_NAME; 42 import static com.android.server.accessibility.AccessibilityTraceProto.THREAD_ID_NAME; 43 import static com.android.server.accessibility.AccessibilityTraceProto.WHERE; 44 import static com.android.server.accessibility.AccessibilityTraceProto.WINDOW_MANAGER_SERVICE; 45 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 46 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 47 import static com.android.server.wm.WindowTracing.WINSCOPE_EXT; 48 49 import android.accessibilityservice.AccessibilityTrace; 50 import android.animation.ObjectAnimator; 51 import android.animation.ValueAnimator; 52 import android.annotation.NonNull; 53 import android.annotation.Nullable; 54 import android.app.Application; 55 import android.content.Context; 56 import android.content.pm.PackageManagerInternal; 57 import android.graphics.BLASTBufferQueue; 58 import android.graphics.Canvas; 59 import android.graphics.Color; 60 import android.graphics.Matrix; 61 import android.graphics.Paint; 62 import android.graphics.Path; 63 import android.graphics.PixelFormat; 64 import android.graphics.Point; 65 import android.graphics.PorterDuff.Mode; 66 import android.graphics.Rect; 67 import android.graphics.RectF; 68 import android.graphics.Region; 69 import android.os.Binder; 70 import android.os.Build; 71 import android.os.Handler; 72 import android.os.HandlerThread; 73 import android.os.IBinder; 74 import android.os.Looper; 75 import android.os.Message; 76 import android.os.Process; 77 import android.os.SystemClock; 78 import android.util.ArraySet; 79 import android.util.Pair; 80 import android.util.Slog; 81 import android.util.SparseArray; 82 import android.util.SparseBooleanArray; 83 import android.util.TypedValue; 84 import android.util.proto.ProtoOutputStream; 85 import android.view.Display; 86 import android.view.InsetsSource; 87 import android.view.MagnificationSpec; 88 import android.view.Surface; 89 import android.view.Surface.OutOfResourcesException; 90 import android.view.SurfaceControl; 91 import android.view.ViewConfiguration; 92 import android.view.WindowInfo; 93 import android.view.WindowManager; 94 import android.view.WindowManagerPolicyConstants; 95 import android.view.animation.DecelerateInterpolator; 96 import android.view.animation.Interpolator; 97 98 import com.android.internal.R; 99 import com.android.internal.os.SomeArgs; 100 import com.android.internal.util.TraceBuffer; 101 import com.android.internal.util.function.pooled.PooledLambda; 102 import com.android.server.LocalServices; 103 import com.android.server.policy.WindowManagerPolicy; 104 import com.android.server.wm.AccessibilityWindowsPopulator.AccessibilityWindow; 105 import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal; 106 import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks; 107 import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback; 108 109 import java.io.File; 110 import java.io.IOException; 111 import java.io.PrintWriter; 112 import java.text.SimpleDateFormat; 113 import java.util.ArrayList; 114 import java.util.Arrays; 115 import java.util.Date; 116 import java.util.HashSet; 117 import java.util.List; 118 import java.util.Set; 119 120 /** 121 * This class contains the accessibility related logic of the window manager. 122 */ 123 final class AccessibilityController { 124 private static final String TAG = AccessibilityController.class.getSimpleName(); 125 126 private static final Object STATIC_LOCK = new Object(); 127 static AccessibilityControllerInternalImpl getAccessibilityControllerInternal(WindowManagerService service)128 getAccessibilityControllerInternal(WindowManagerService service) { 129 return AccessibilityControllerInternalImpl.getInstance(service); 130 } 131 132 private final AccessibilityControllerInternalImpl mAccessibilityTracing; 133 private final WindowManagerService mService; 134 private static final Rect EMPTY_RECT = new Rect(); 135 private static final float[] sTempFloats = new float[9]; 136 137 private final SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>(); 138 private final SparseArray<WindowsForAccessibilityObserver> mWindowsForAccessibilityObserver = 139 new SparseArray<>(); 140 private SparseArray<IBinder> mFocusedWindow = new SparseArray<>(); 141 private int mFocusedDisplay = -1; 142 private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray(); 143 // Set to true if initializing window population complete. 144 private boolean mAllObserversInitialized = true; 145 private final AccessibilityWindowsPopulator mAccessibilityWindowsPopulator; 146 AccessibilityController(WindowManagerService service)147 AccessibilityController(WindowManagerService service) { 148 mService = service; 149 mAccessibilityTracing = 150 AccessibilityController.getAccessibilityControllerInternal(service); 151 152 mAccessibilityWindowsPopulator = new AccessibilityWindowsPopulator(mService, this); 153 } 154 setMagnificationCallbacks(int displayId, MagnificationCallbacks callbacks)155 boolean setMagnificationCallbacks(int displayId, MagnificationCallbacks callbacks) { 156 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 157 mAccessibilityTracing.logTrace( 158 TAG + ".setMagnificationCallbacks", 159 FLAGS_MAGNIFICATION_CALLBACK, 160 "displayId=" + displayId + "; callbacks={" + callbacks + "}"); 161 } 162 boolean result = false; 163 if (callbacks != null) { 164 if (mDisplayMagnifiers.get(displayId) != null) { 165 throw new IllegalStateException("Magnification callbacks already set!"); 166 } 167 final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); 168 if (dc != null) { 169 final Display display = dc.getDisplay(); 170 if (display != null && display.getType() != Display.TYPE_OVERLAY) { 171 final DisplayMagnifier magnifier = new DisplayMagnifier( 172 mService, dc, display, callbacks); 173 magnifier.notifyImeWindowVisibilityChanged( 174 mIsImeVisibleArray.get(displayId, false)); 175 mDisplayMagnifiers.put(displayId, magnifier); 176 result = true; 177 } 178 } 179 } else { 180 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 181 if (displayMagnifier == null) { 182 throw new IllegalStateException("Magnification callbacks already cleared!"); 183 } 184 displayMagnifier.destroy(); 185 mDisplayMagnifiers.remove(displayId); 186 result = true; 187 } 188 return result; 189 } 190 191 /** 192 * Sets a callback for observing which windows are touchable for the purposes 193 * of accessibility on specified display. 194 * 195 * @param displayId The logical display id. 196 * @param callback The callback. 197 */ setWindowsForAccessibilityCallback(int displayId, WindowsForAccessibilityCallback callback)198 void setWindowsForAccessibilityCallback(int displayId, 199 WindowsForAccessibilityCallback callback) { 200 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 201 mAccessibilityTracing.logTrace( 202 TAG + ".setWindowsForAccessibilityCallback", 203 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 204 "displayId=" + displayId + "; callback={" + callback + "}"); 205 } 206 207 if (callback != null) { 208 WindowsForAccessibilityObserver observer = 209 mWindowsForAccessibilityObserver.get(displayId); 210 if (observer != null) { 211 final String errorMessage = "Windows for accessibility callback of display " 212 + displayId + " already set!"; 213 Slog.e(TAG, errorMessage); 214 if (Build.IS_DEBUGGABLE) { 215 throw new IllegalStateException(errorMessage); 216 } 217 mWindowsForAccessibilityObserver.remove(displayId); 218 } 219 mAccessibilityWindowsPopulator.setWindowsNotification(true); 220 observer = new WindowsForAccessibilityObserver(mService, displayId, callback, 221 mAccessibilityWindowsPopulator); 222 mWindowsForAccessibilityObserver.put(displayId, observer); 223 mAllObserversInitialized &= observer.mInitialized; 224 } else { 225 final WindowsForAccessibilityObserver windowsForA11yObserver = 226 mWindowsForAccessibilityObserver.get(displayId); 227 if (windowsForA11yObserver == null) { 228 final String errorMessage = "Windows for accessibility callback of display " 229 + displayId + " already cleared!"; 230 Slog.e(TAG, errorMessage); 231 if (Build.IS_DEBUGGABLE) { 232 throw new IllegalStateException(errorMessage); 233 } 234 } 235 mWindowsForAccessibilityObserver.remove(displayId); 236 237 if (mWindowsForAccessibilityObserver.size() <= 0) { 238 mAccessibilityWindowsPopulator.setWindowsNotification(false); 239 } 240 } 241 } 242 performComputeChangedWindowsNot(int displayId, boolean forceSend)243 void performComputeChangedWindowsNot(int displayId, boolean forceSend) { 244 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 245 mAccessibilityTracing.logTrace( 246 TAG + ".performComputeChangedWindowsNot", 247 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 248 "displayId=" + displayId + "; forceSend=" + forceSend); 249 } 250 WindowsForAccessibilityObserver observer = null; 251 synchronized (mService.mGlobalLock) { 252 final WindowsForAccessibilityObserver windowsForA11yObserver = 253 mWindowsForAccessibilityObserver.get(displayId); 254 if (windowsForA11yObserver != null) { 255 observer = windowsForA11yObserver; 256 } 257 } 258 if (observer != null) { 259 observer.performComputeChangedWindows(forceSend); 260 } 261 } 262 setMagnificationSpec(int displayId, MagnificationSpec spec)263 void setMagnificationSpec(int displayId, MagnificationSpec spec) { 264 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 265 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 266 mAccessibilityTracing.logTrace(TAG + ".setMagnificationSpec", 267 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 268 "displayId=" + displayId + "; spec={" + spec + "}"); 269 } 270 mAccessibilityWindowsPopulator.setMagnificationSpec(displayId, spec); 271 272 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 273 if (displayMagnifier != null) { 274 displayMagnifier.setMagnificationSpec(spec); 275 } 276 final WindowsForAccessibilityObserver windowsForA11yObserver = 277 mWindowsForAccessibilityObserver.get(displayId); 278 if (windowsForA11yObserver != null) { 279 windowsForA11yObserver.scheduleComputeChangedWindows(); 280 } 281 } 282 getMagnificationRegion(int displayId, Region outMagnificationRegion)283 void getMagnificationRegion(int displayId, Region outMagnificationRegion) { 284 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 285 mAccessibilityTracing.logTrace(TAG + ".getMagnificationRegion", 286 FLAGS_MAGNIFICATION_CALLBACK, 287 "displayId=" + displayId + "; outMagnificationRegion={" + outMagnificationRegion 288 + "}"); 289 } 290 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 291 if (displayMagnifier != null) { 292 displayMagnifier.getMagnificationRegion(outMagnificationRegion); 293 } 294 } 295 onWindowLayersChanged(int displayId)296 void onWindowLayersChanged(int displayId) { 297 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 298 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 299 mAccessibilityTracing.logTrace(TAG + ".onWindowLayersChanged", 300 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 301 "displayId=" + displayId); 302 } 303 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 304 if (displayMagnifier != null) { 305 displayMagnifier.onWindowLayersChanged(); 306 } 307 final WindowsForAccessibilityObserver windowsForA11yObserver = 308 mWindowsForAccessibilityObserver.get(displayId); 309 if (windowsForA11yObserver != null) { 310 windowsForA11yObserver.scheduleComputeChangedWindows(); 311 } 312 } 313 onDisplaySizeChanged(DisplayContent displayContent)314 void onDisplaySizeChanged(DisplayContent displayContent) { 315 316 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 317 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 318 mAccessibilityTracing.logTrace(TAG + ".onRotationChanged", 319 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 320 "displayContent={" + displayContent + "}"); 321 } 322 final int displayId = displayContent.getDisplayId(); 323 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 324 if (displayMagnifier != null) { 325 displayMagnifier.onDisplaySizeChanged(displayContent); 326 } 327 } 328 onAppWindowTransition(int displayId, int transition)329 void onAppWindowTransition(int displayId, int transition) { 330 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 331 mAccessibilityTracing.logTrace(TAG + ".onAppWindowTransition", 332 FLAGS_MAGNIFICATION_CALLBACK, 333 "displayId=" + displayId + "; transition=" + transition); 334 } 335 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 336 if (displayMagnifier != null) { 337 displayMagnifier.onAppWindowTransition(displayId, transition); 338 } 339 // Not relevant for the window observer. 340 } 341 onWindowTransition(WindowState windowState, int transition)342 void onWindowTransition(WindowState windowState, int transition) { 343 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 344 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 345 mAccessibilityTracing.logTrace(TAG + ".onWindowTransition", 346 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 347 "windowState={" + windowState + "}; transition=" + transition); 348 } 349 final int displayId = windowState.getDisplayId(); 350 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 351 if (displayMagnifier != null) { 352 displayMagnifier.onWindowTransition(windowState, transition); 353 } 354 } 355 onWindowFocusChangedNot(int displayId)356 void onWindowFocusChangedNot(int displayId) { 357 // Not relevant for the display magnifier. 358 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 359 mAccessibilityTracing.logTrace(TAG + ".onWindowFocusChangedNot", 360 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, "displayId=" + displayId); 361 } 362 WindowsForAccessibilityObserver observer = null; 363 synchronized (mService.mGlobalLock) { 364 final WindowsForAccessibilityObserver windowsForA11yObserver = 365 mWindowsForAccessibilityObserver.get(displayId); 366 if (windowsForA11yObserver != null) { 367 observer = windowsForA11yObserver; 368 } 369 } 370 if (observer != null) { 371 observer.performComputeChangedWindows(false); 372 } 373 // Since we abandon initializing observers if no window has focus, make sure all observers 374 // are initialized. 375 sendCallbackToUninitializedObserversIfNeeded(); 376 } 377 sendCallbackToUninitializedObserversIfNeeded()378 private void sendCallbackToUninitializedObserversIfNeeded() { 379 List<WindowsForAccessibilityObserver> unInitializedObservers; 380 synchronized (mService.mGlobalLock) { 381 if (mAllObserversInitialized) { 382 return; 383 } 384 if (mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus == null) { 385 return; 386 } 387 unInitializedObservers = new ArrayList<>(); 388 for (int i = mWindowsForAccessibilityObserver.size() - 1; i >= 0; --i) { 389 final WindowsForAccessibilityObserver observer = 390 mWindowsForAccessibilityObserver.valueAt(i); 391 if (!observer.mInitialized) { 392 unInitializedObservers.add(observer); 393 } 394 } 395 // Reset the flag to record the new added observer. 396 mAllObserversInitialized = true; 397 } 398 399 boolean areAllObserversInitialized = true; 400 for (int i = unInitializedObservers.size() - 1; i >= 0; --i) { 401 final WindowsForAccessibilityObserver observer = unInitializedObservers.get(i); 402 observer.performComputeChangedWindows(true); 403 areAllObserversInitialized &= observer.mInitialized; 404 } 405 synchronized (mService.mGlobalLock) { 406 mAllObserversInitialized &= areAllObserversInitialized; 407 } 408 } 409 410 /** 411 * Called when the location or the size of the window is changed. Moving the window to 412 * another display is also taken into consideration. 413 * @param displayIds the display ids of displays when the situation happens. 414 */ onSomeWindowResizedOrMoved(int... displayIds)415 void onSomeWindowResizedOrMoved(int... displayIds) { 416 onSomeWindowResizedOrMovedWithCallingUid(Binder.getCallingUid(), displayIds); 417 } 418 onSomeWindowResizedOrMovedWithCallingUid(int callingUid, int... displayIds)419 void onSomeWindowResizedOrMovedWithCallingUid(int callingUid, int... displayIds) { 420 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 421 mAccessibilityTracing.logTrace(TAG + ".onSomeWindowResizedOrMoved", 422 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, 423 "displayIds={" + displayIds.toString() + "}", "".getBytes(), callingUid); 424 } 425 // Not relevant for the display magnifier. 426 for (int i = 0; i < displayIds.length; i++) { 427 final WindowsForAccessibilityObserver windowsForA11yObserver = 428 mWindowsForAccessibilityObserver.get(displayIds[i]); 429 if (windowsForA11yObserver != null) { 430 windowsForA11yObserver.scheduleComputeChangedWindows(); 431 } 432 } 433 } 434 drawMagnifiedRegionBorderIfNeeded(int displayId, SurfaceControl.Transaction t)435 void drawMagnifiedRegionBorderIfNeeded(int displayId, SurfaceControl.Transaction t) { 436 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 437 mAccessibilityTracing.logTrace( 438 TAG + ".drawMagnifiedRegionBorderIfNeeded", 439 FLAGS_MAGNIFICATION_CALLBACK, 440 "displayId=" + displayId + "; transaction={" + t + "}"); 441 } 442 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 443 if (displayMagnifier != null) { 444 displayMagnifier.drawMagnifiedRegionBorderIfNeeded(t); 445 } 446 // Not relevant for the window observer. 447 } 448 getWindowTransformationMatrixAndMagnificationSpec( IBinder token)449 public Pair<Matrix, MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec( 450 IBinder token) { 451 synchronized (mService.mGlobalLock) { 452 final Matrix transformationMatrix = new Matrix(); 453 final MagnificationSpec magnificationSpec = new MagnificationSpec(); 454 455 final WindowState windowState = mService.mWindowMap.get(token); 456 if (windowState != null) { 457 windowState.getTransformationMatrix(new float[9], transformationMatrix); 458 459 if (hasCallbacks()) { 460 final MagnificationSpec otherMagnificationSpec = 461 getMagnificationSpecForWindow(windowState); 462 if (otherMagnificationSpec != null && !otherMagnificationSpec.isNop()) { 463 magnificationSpec.setTo(otherMagnificationSpec); 464 } 465 } 466 } 467 468 return new Pair<>(transformationMatrix, magnificationSpec); 469 } 470 } 471 getMagnificationSpecForWindow(WindowState windowState)472 MagnificationSpec getMagnificationSpecForWindow(WindowState windowState) { 473 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 474 mAccessibilityTracing.logTrace(TAG + ".getMagnificationSpecForWindow", 475 FLAGS_MAGNIFICATION_CALLBACK, 476 "windowState={" + windowState + "}"); 477 } 478 final int displayId = windowState.getDisplayId(); 479 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 480 if (displayMagnifier != null) { 481 return displayMagnifier.getMagnificationSpecForWindow(windowState); 482 } 483 return null; 484 } 485 hasCallbacks()486 boolean hasCallbacks() { 487 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 488 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 489 mAccessibilityTracing.logTrace(TAG + ".hasCallbacks", 490 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK); 491 } 492 return (mDisplayMagnifiers.size() > 0 493 || mWindowsForAccessibilityObserver.size() > 0); 494 } 495 setForceShowMagnifiableBounds(int displayId, boolean show)496 void setForceShowMagnifiableBounds(int displayId, boolean show) { 497 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 498 mAccessibilityTracing.logTrace(TAG + ".setForceShowMagnifiableBounds", 499 FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + "; show=" + show); 500 } 501 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 502 if (displayMagnifier != null) { 503 displayMagnifier.setForceShowMagnifiableBounds(show); 504 displayMagnifier.showMagnificationBoundsIfNeeded(); 505 } 506 } 507 updateImeVisibilityIfNeeded(int displayId, boolean shown)508 void updateImeVisibilityIfNeeded(int displayId, boolean shown) { 509 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 510 mAccessibilityTracing.logTrace(TAG + ".updateImeVisibilityIfNeeded", 511 FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + ";shown=" + shown); 512 } 513 514 final boolean isDisplayImeVisible = mIsImeVisibleArray.get(displayId, false); 515 if (isDisplayImeVisible == shown) { 516 return; 517 } 518 519 mIsImeVisibleArray.put(displayId, shown); 520 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); 521 if (displayMagnifier != null) { 522 displayMagnifier.notifyImeWindowVisibilityChanged(shown); 523 } 524 } 525 populateTransformationMatrix(WindowState windowState, Matrix outMatrix)526 private static void populateTransformationMatrix(WindowState windowState, 527 Matrix outMatrix) { 528 windowState.getTransformationMatrix(sTempFloats, outMatrix); 529 } 530 dump(PrintWriter pw, String prefix)531 void dump(PrintWriter pw, String prefix) { 532 for (int i = 0; i < mDisplayMagnifiers.size(); i++) { 533 final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.valueAt(i); 534 if (displayMagnifier != null) { 535 displayMagnifier.dump(pw, prefix 536 + "Magnification display# " + mDisplayMagnifiers.keyAt(i)); 537 } 538 } 539 pw.println(prefix 540 + "mWindowsForAccessibilityObserver=" + mWindowsForAccessibilityObserver); 541 } 542 onFocusChanged(InputTarget lastTarget, InputTarget newTarget)543 void onFocusChanged(InputTarget lastTarget, InputTarget newTarget) { 544 if (lastTarget != null) { 545 mFocusedWindow.remove(lastTarget.getDisplayId()); 546 } 547 if (newTarget != null) { 548 int displayId = newTarget.getDisplayId(); 549 IBinder clientBinder = newTarget.getIWindow().asBinder(); 550 mFocusedWindow.put(displayId, clientBinder); 551 } 552 } 553 onDisplayRemoved(int displayId)554 public void onDisplayRemoved(int displayId) { 555 mIsImeVisibleArray.delete(displayId); 556 mFocusedWindow.remove(displayId); 557 } 558 setFocusedDisplay(int focusedDisplayId)559 public void setFocusedDisplay(int focusedDisplayId) { 560 mFocusedDisplay = focusedDisplayId; 561 } 562 getFocusedWindowToken()563 @Nullable IBinder getFocusedWindowToken() { 564 return mFocusedWindow.get(mFocusedDisplay); 565 } 566 567 /** 568 * This class encapsulates the functionality related to display magnification. 569 */ 570 private static final class DisplayMagnifier { 571 572 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ? "DisplayMagnifier" : TAG_WM; 573 574 private static final boolean DEBUG_WINDOW_TRANSITIONS = false; 575 private static final boolean DEBUG_DISPLAY_SIZE = false; 576 private static final boolean DEBUG_LAYERS = false; 577 private static final boolean DEBUG_RECTANGLE_REQUESTED = false; 578 private static final boolean DEBUG_VIEWPORT_WINDOW = false; 579 580 private final Rect mTempRect1 = new Rect(); 581 private final Rect mTempRect2 = new Rect(); 582 583 private final Region mTempRegion1 = new Region(); 584 private final Region mTempRegion2 = new Region(); 585 private final Region mTempRegion3 = new Region(); 586 private final Region mTempRegion4 = new Region(); 587 588 private final Context mDisplayContext; 589 private final WindowManagerService mService; 590 private final MagnifiedViewport mMagnifedViewport; 591 private final Handler mHandler; 592 private final DisplayContent mDisplayContent; 593 private final Display mDisplay; 594 private final AccessibilityControllerInternalImpl mAccessibilityTracing; 595 596 private final MagnificationCallbacks mCallbacks; 597 598 private final long mLongAnimationDuration; 599 600 private boolean mForceShowMagnifiableBounds = false; 601 DisplayMagnifier(WindowManagerService windowManagerService, DisplayContent displayContent, Display display, MagnificationCallbacks callbacks)602 DisplayMagnifier(WindowManagerService windowManagerService, 603 DisplayContent displayContent, 604 Display display, 605 MagnificationCallbacks callbacks) { 606 mDisplayContext = windowManagerService.mContext.createDisplayContext(display); 607 mService = windowManagerService; 608 mCallbacks = callbacks; 609 mDisplayContent = displayContent; 610 mDisplay = display; 611 mHandler = new MyHandler(mService.mH.getLooper()); 612 mMagnifedViewport = new MagnifiedViewport(); 613 mAccessibilityTracing = 614 AccessibilityController.getAccessibilityControllerInternal(mService); 615 mLongAnimationDuration = mDisplayContext.getResources().getInteger( 616 com.android.internal.R.integer.config_longAnimTime); 617 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 618 mAccessibilityTracing.logTrace(LOG_TAG + ".DisplayMagnifier.constructor", 619 FLAGS_MAGNIFICATION_CALLBACK, 620 "windowManagerService={" + windowManagerService + "}; displayContent={" 621 + displayContent + "}; display={" + display + "}; callbacks={" 622 + callbacks + "}"); 623 } 624 } 625 setMagnificationSpec(MagnificationSpec spec)626 void setMagnificationSpec(MagnificationSpec spec) { 627 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 628 mAccessibilityTracing.logTrace(LOG_TAG + ".setMagnificationSpec", 629 FLAGS_MAGNIFICATION_CALLBACK, "spec={" + spec + "}"); 630 } 631 mMagnifedViewport.updateMagnificationSpec(spec); 632 mMagnifedViewport.recomputeBounds(); 633 634 mService.applyMagnificationSpecLocked(mDisplay.getDisplayId(), spec); 635 mService.scheduleAnimationLocked(); 636 } 637 setForceShowMagnifiableBounds(boolean show)638 void setForceShowMagnifiableBounds(boolean show) { 639 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 640 mAccessibilityTracing.logTrace(LOG_TAG + ".setForceShowMagnifiableBounds", 641 FLAGS_MAGNIFICATION_CALLBACK, "show=" + show); 642 } 643 mForceShowMagnifiableBounds = show; 644 mMagnifedViewport.setMagnifiedRegionBorderShown(show, true); 645 } 646 isForceShowingMagnifiableBounds()647 boolean isForceShowingMagnifiableBounds() { 648 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 649 mAccessibilityTracing.logTrace(LOG_TAG + ".isForceShowingMagnifiableBounds", 650 FLAGS_MAGNIFICATION_CALLBACK); 651 } 652 return mForceShowMagnifiableBounds; 653 } 654 onWindowLayersChanged()655 void onWindowLayersChanged() { 656 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 657 mAccessibilityTracing.logTrace( 658 LOG_TAG + ".onWindowLayersChanged", FLAGS_MAGNIFICATION_CALLBACK); 659 } 660 if (DEBUG_LAYERS) { 661 Slog.i(LOG_TAG, "Layers changed."); 662 } 663 mMagnifedViewport.recomputeBounds(); 664 mService.scheduleAnimationLocked(); 665 } 666 onDisplaySizeChanged(DisplayContent displayContent)667 void onDisplaySizeChanged(DisplayContent displayContent) { 668 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 669 mAccessibilityTracing.logTrace(LOG_TAG + ".onDisplaySizeChanged", 670 FLAGS_MAGNIFICATION_CALLBACK, "displayContent={" + displayContent + "}"); 671 } 672 if (DEBUG_DISPLAY_SIZE) { 673 final int rotation = displayContent.getRotation(); 674 Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation) 675 + " displayId: " + displayContent.getDisplayId()); 676 } 677 mMagnifedViewport.onDisplaySizeChanged(); 678 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED); 679 } 680 onAppWindowTransition(int displayId, int transition)681 void onAppWindowTransition(int displayId, int transition) { 682 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 683 mAccessibilityTracing.logTrace(LOG_TAG + ".onAppWindowTransition", 684 FLAGS_MAGNIFICATION_CALLBACK, 685 "displayId=" + displayId + "; transition=" + transition); 686 } 687 if (DEBUG_WINDOW_TRANSITIONS) { 688 Slog.i(LOG_TAG, "Window transition: " 689 + AppTransition.appTransitionOldToString(transition) 690 + " displayId: " + displayId); 691 } 692 final boolean magnifying = mMagnifedViewport.isMagnifying(); 693 if (magnifying) { 694 switch (transition) { 695 case WindowManager.TRANSIT_OLD_ACTIVITY_OPEN: 696 case WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN: 697 case WindowManager.TRANSIT_OLD_TASK_OPEN: 698 case WindowManager.TRANSIT_OLD_TASK_TO_FRONT: 699 case WindowManager.TRANSIT_OLD_WALLPAPER_OPEN: 700 case WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE: 701 case WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN: { 702 mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED); 703 } 704 } 705 } 706 } 707 onWindowTransition(WindowState windowState, int transition)708 void onWindowTransition(WindowState windowState, int transition) { 709 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 710 mAccessibilityTracing.logTrace(LOG_TAG + ".onWindowTransition", 711 FLAGS_MAGNIFICATION_CALLBACK, 712 "windowState={" + windowState + "}; transition=" + transition); 713 } 714 if (DEBUG_WINDOW_TRANSITIONS) { 715 Slog.i(LOG_TAG, "Window transition: " 716 + AppTransition.appTransitionOldToString(transition) 717 + " displayId: " + windowState.getDisplayId()); 718 } 719 final boolean magnifying = mMagnifedViewport.isMagnifying(); 720 final int type = windowState.mAttrs.type; 721 switch (transition) { 722 case WindowManagerPolicy.TRANSIT_ENTER: 723 case WindowManagerPolicy.TRANSIT_SHOW: { 724 if (!magnifying) { 725 break; 726 } 727 switch (type) { 728 case WindowManager.LayoutParams.TYPE_APPLICATION: 729 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION: 730 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: 731 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: 732 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: 733 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL: 734 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: 735 case WindowManager.LayoutParams.TYPE_SEARCH_BAR: 736 case WindowManager.LayoutParams.TYPE_PHONE: 737 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: 738 case WindowManager.LayoutParams.TYPE_TOAST: 739 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: 740 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY: 741 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE: 742 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: 743 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: 744 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: 745 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: 746 case WindowManager.LayoutParams.TYPE_QS_DIALOG: 747 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: { 748 Rect magnifiedRegionBounds = mTempRect2; 749 mMagnifedViewport.getMagnifiedFrameInContentCoords( 750 magnifiedRegionBounds); 751 Rect touchableRegionBounds = mTempRect1; 752 windowState.getTouchableRegion(mTempRegion1); 753 mTempRegion1.getBounds(touchableRegionBounds); 754 if (!magnifiedRegionBounds.intersect(touchableRegionBounds)) { 755 mCallbacks.onRectangleOnScreenRequested( 756 touchableRegionBounds.left, 757 touchableRegionBounds.top, 758 touchableRegionBounds.right, 759 touchableRegionBounds.bottom); 760 } 761 } break; 762 } break; 763 } 764 } 765 } 766 notifyImeWindowVisibilityChanged(boolean shown)767 void notifyImeWindowVisibilityChanged(boolean shown) { 768 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 769 mAccessibilityTracing.logTrace(LOG_TAG + ".notifyImeWindowVisibilityChanged", 770 FLAGS_MAGNIFICATION_CALLBACK, "shown=" + shown); 771 } 772 mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED, 773 shown ? 1 : 0, 0).sendToTarget(); 774 } 775 getMagnificationSpecForWindow(WindowState windowState)776 MagnificationSpec getMagnificationSpecForWindow(WindowState windowState) { 777 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 778 mAccessibilityTracing.logTrace(LOG_TAG + ".getMagnificationSpecForWindow", 779 FLAGS_MAGNIFICATION_CALLBACK, "windowState={" + windowState + "}"); 780 } 781 MagnificationSpec spec = mMagnifedViewport.getMagnificationSpec(); 782 if (spec != null && !spec.isNop()) { 783 if (!windowState.shouldMagnify()) { 784 return null; 785 } 786 } 787 return spec; 788 } 789 getMagnificationRegion(Region outMagnificationRegion)790 void getMagnificationRegion(Region outMagnificationRegion) { 791 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 792 mAccessibilityTracing.logTrace(LOG_TAG + ".getMagnificationRegion", 793 FLAGS_MAGNIFICATION_CALLBACK, 794 "outMagnificationRegion={" + outMagnificationRegion + "}"); 795 } 796 // Make sure we're working with the most current bounds 797 mMagnifedViewport.recomputeBounds(); 798 mMagnifedViewport.getMagnificationRegion(outMagnificationRegion); 799 } 800 destroy()801 void destroy() { 802 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 803 mAccessibilityTracing.logTrace(LOG_TAG + ".destroy", FLAGS_MAGNIFICATION_CALLBACK); 804 } 805 mMagnifedViewport.destroyWindow(); 806 } 807 808 // Can be called outside of a surface transaction showMagnificationBoundsIfNeeded()809 void showMagnificationBoundsIfNeeded() { 810 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 811 mAccessibilityTracing.logTrace(LOG_TAG + ".showMagnificationBoundsIfNeeded", 812 FLAGS_MAGNIFICATION_CALLBACK); 813 } 814 mHandler.obtainMessage(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED) 815 .sendToTarget(); 816 } 817 drawMagnifiedRegionBorderIfNeeded(SurfaceControl.Transaction t)818 void drawMagnifiedRegionBorderIfNeeded(SurfaceControl.Transaction t) { 819 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 820 mAccessibilityTracing.logTrace(LOG_TAG + ".drawMagnifiedRegionBorderIfNeeded", 821 FLAGS_MAGNIFICATION_CALLBACK, "transition={" + t + "}"); 822 } 823 mMagnifedViewport.drawWindowIfNeeded(t); 824 } 825 dump(PrintWriter pw, String prefix)826 void dump(PrintWriter pw, String prefix) { 827 mMagnifedViewport.dump(pw, prefix); 828 } 829 830 private final class MagnifiedViewport { 831 832 private final SparseArray<WindowState> mTempWindowStates = 833 new SparseArray<WindowState>(); 834 835 private final RectF mTempRectF = new RectF(); 836 837 private final Point mScreenSize = new Point(); 838 839 private final Matrix mTempMatrix = new Matrix(); 840 841 private final Region mMagnificationRegion = new Region(); 842 private final Region mOldMagnificationRegion = new Region(); 843 844 private final Path mCircularPath; 845 846 private final MagnificationSpec mMagnificationSpec = new MagnificationSpec(); 847 848 private final float mBorderWidth; 849 private final int mHalfBorderWidth; 850 private final int mDrawBorderInset; 851 852 private final ViewportWindow mWindow; 853 854 private boolean mFullRedrawNeeded; 855 private int mTempLayer = 0; 856 MagnifiedViewport()857 MagnifiedViewport() { 858 mBorderWidth = mDisplayContext.getResources().getDimension( 859 com.android.internal.R.dimen.accessibility_magnification_indicator_width); 860 mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2); 861 mDrawBorderInset = (int) mBorderWidth / 2; 862 mWindow = new ViewportWindow(mDisplayContext); 863 864 if (mDisplayContext.getResources().getConfiguration().isScreenRound()) { 865 mCircularPath = new Path(); 866 867 getDisplaySizeLocked(mScreenSize); 868 final int centerXY = mScreenSize.x / 2; 869 mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW); 870 } else { 871 mCircularPath = null; 872 } 873 874 recomputeBounds(); 875 } 876 getMagnificationRegion(@onNull Region outMagnificationRegion)877 void getMagnificationRegion(@NonNull Region outMagnificationRegion) { 878 outMagnificationRegion.set(mMagnificationRegion); 879 } 880 updateMagnificationSpec(MagnificationSpec spec)881 void updateMagnificationSpec(MagnificationSpec spec) { 882 if (spec != null) { 883 mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY); 884 } else { 885 mMagnificationSpec.clear(); 886 } 887 // If this message is pending we are in a rotation animation and do not want 888 // to show the border. We will do so when the pending message is handled. 889 if (!mHandler.hasMessages( 890 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) { 891 setMagnifiedRegionBorderShown( 892 isMagnifying() || isForceShowingMagnifiableBounds(), true); 893 } 894 } 895 recomputeBounds()896 void recomputeBounds() { 897 getDisplaySizeLocked(mScreenSize); 898 final int screenWidth = mScreenSize.x; 899 final int screenHeight = mScreenSize.y; 900 901 mMagnificationRegion.set(0, 0, 0, 0); 902 final Region availableBounds = mTempRegion1; 903 availableBounds.set(0, 0, screenWidth, screenHeight); 904 905 if (mCircularPath != null) { 906 availableBounds.setPath(mCircularPath, availableBounds); 907 } 908 909 Region nonMagnifiedBounds = mTempRegion4; 910 nonMagnifiedBounds.set(0, 0, 0, 0); 911 912 SparseArray<WindowState> visibleWindows = mTempWindowStates; 913 visibleWindows.clear(); 914 populateWindowsOnScreen(visibleWindows); 915 916 final int visibleWindowCount = visibleWindows.size(); 917 for (int i = visibleWindowCount - 1; i >= 0; i--) { 918 WindowState windowState = visibleWindows.valueAt(i); 919 final int windowType = windowState.mAttrs.type; 920 if (isExcludedWindowType(windowType) 921 || ((windowState.mAttrs.privateFlags 922 & PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION) != 0) 923 || ((windowState.mAttrs.privateFlags 924 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0)) { 925 continue; 926 } 927 928 // Consider the touchable portion of the window 929 Matrix matrix = mTempMatrix; 930 populateTransformationMatrix(windowState, matrix); 931 Region touchableRegion = mTempRegion3; 932 windowState.getTouchableRegion(touchableRegion); 933 Rect touchableFrame = mTempRect1; 934 touchableRegion.getBounds(touchableFrame); 935 RectF windowFrame = mTempRectF; 936 windowFrame.set(touchableFrame); 937 windowFrame.offset(-windowState.getFrame().left, 938 -windowState.getFrame().top); 939 matrix.mapRect(windowFrame); 940 Region windowBounds = mTempRegion2; 941 windowBounds.set((int) windowFrame.left, (int) windowFrame.top, 942 (int) windowFrame.right, (int) windowFrame.bottom); 943 // Only update new regions 944 Region portionOfWindowAlreadyAccountedFor = mTempRegion3; 945 portionOfWindowAlreadyAccountedFor.set(mMagnificationRegion); 946 portionOfWindowAlreadyAccountedFor.op(nonMagnifiedBounds, Region.Op.UNION); 947 windowBounds.op(portionOfWindowAlreadyAccountedFor, Region.Op.DIFFERENCE); 948 949 if (windowState.shouldMagnify()) { 950 mMagnificationRegion.op(windowBounds, Region.Op.UNION); 951 mMagnificationRegion.op(availableBounds, Region.Op.INTERSECT); 952 } else { 953 nonMagnifiedBounds.op(windowBounds, Region.Op.UNION); 954 availableBounds.op(windowBounds, Region.Op.DIFFERENCE); 955 } 956 957 // If the navigation bar window doesn't have touchable region, count 958 // navigation bar insets into nonMagnifiedBounds. It happens when 959 // navigation mode is gestural. 960 if (isUntouchableNavigationBar(windowState, mTempRegion3)) { 961 final Rect navBarInsets = getNavBarInsets(mDisplayContent); 962 nonMagnifiedBounds.op(navBarInsets, Region.Op.UNION); 963 availableBounds.op(navBarInsets, Region.Op.DIFFERENCE); 964 } 965 966 // Count letterbox into nonMagnifiedBounds 967 if (windowState.areAppWindowBoundsLetterboxed()) { 968 Region letterboxBounds = getLetterboxBounds(windowState); 969 nonMagnifiedBounds.op(letterboxBounds, Region.Op.UNION); 970 availableBounds.op(letterboxBounds, Region.Op.DIFFERENCE); 971 } 972 973 // Update accounted bounds 974 Region accountedBounds = mTempRegion2; 975 accountedBounds.set(mMagnificationRegion); 976 accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION); 977 accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT); 978 979 if (accountedBounds.isRect()) { 980 Rect accountedFrame = mTempRect1; 981 accountedBounds.getBounds(accountedFrame); 982 if (accountedFrame.width() == screenWidth 983 && accountedFrame.height() == screenHeight) { 984 break; 985 } 986 } 987 } 988 visibleWindows.clear(); 989 990 mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset, 991 screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset, 992 Region.Op.INTERSECT); 993 994 final boolean magnifiedChanged = 995 !mOldMagnificationRegion.equals(mMagnificationRegion); 996 if (magnifiedChanged) { 997 mWindow.setBounds(mMagnificationRegion); 998 final Rect dirtyRect = mTempRect1; 999 if (mFullRedrawNeeded) { 1000 mFullRedrawNeeded = false; 1001 dirtyRect.set(mDrawBorderInset, mDrawBorderInset, 1002 screenWidth - mDrawBorderInset, 1003 screenHeight - mDrawBorderInset); 1004 mWindow.invalidate(dirtyRect); 1005 } else { 1006 final Region dirtyRegion = mTempRegion3; 1007 dirtyRegion.set(mMagnificationRegion); 1008 dirtyRegion.op(mOldMagnificationRegion, Region.Op.XOR); 1009 dirtyRegion.getBounds(dirtyRect); 1010 mWindow.invalidate(dirtyRect); 1011 } 1012 1013 mOldMagnificationRegion.set(mMagnificationRegion); 1014 final SomeArgs args = SomeArgs.obtain(); 1015 args.arg1 = Region.obtain(mMagnificationRegion); 1016 mHandler.obtainMessage( 1017 MyHandler.MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED, args) 1018 .sendToTarget(); 1019 } 1020 } 1021 isExcludedWindowType(int windowType)1022 private boolean isExcludedWindowType(int windowType) { 1023 return windowType == TYPE_MAGNIFICATION_OVERLAY 1024 // Omit the touch region of window magnification to avoid the cut out of the 1025 // magnification and the magnified center of window magnification could be 1026 // in the bounds 1027 || windowType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; 1028 } 1029 onDisplaySizeChanged()1030 void onDisplaySizeChanged() { 1031 // If we are showing the magnification border, hide it immediately so 1032 // the user does not see strange artifacts during display size changed caused by 1033 // rotation or folding/unfolding the device. In the rotation case, the screenshot 1034 // used for rotation already has the border. After the rotation is complete 1035 // we will show the border. 1036 if (isMagnifying() || isForceShowingMagnifiableBounds()) { 1037 setMagnifiedRegionBorderShown(false, false); 1038 final long delay = (long) (mLongAnimationDuration 1039 * mService.getWindowAnimationScaleLocked()); 1040 Message message = mHandler.obtainMessage( 1041 MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED); 1042 mHandler.sendMessageDelayed(message, delay); 1043 } 1044 recomputeBounds(); 1045 mWindow.updateSize(); 1046 } 1047 setMagnifiedRegionBorderShown(boolean shown, boolean animate)1048 void setMagnifiedRegionBorderShown(boolean shown, boolean animate) { 1049 if (shown) { 1050 mFullRedrawNeeded = true; 1051 mOldMagnificationRegion.set(0, 0, 0, 0); 1052 } 1053 mWindow.setShown(shown, animate); 1054 } 1055 getMagnifiedFrameInContentCoords(Rect rect)1056 void getMagnifiedFrameInContentCoords(Rect rect) { 1057 MagnificationSpec spec = mMagnificationSpec; 1058 mMagnificationRegion.getBounds(rect); 1059 rect.offset((int) -spec.offsetX, (int) -spec.offsetY); 1060 rect.scale(1.0f / spec.scale); 1061 } 1062 isMagnifying()1063 boolean isMagnifying() { 1064 return mMagnificationSpec.scale > 1.0f; 1065 } 1066 getMagnificationSpec()1067 MagnificationSpec getMagnificationSpec() { 1068 return mMagnificationSpec; 1069 } 1070 drawWindowIfNeeded(SurfaceControl.Transaction t)1071 void drawWindowIfNeeded(SurfaceControl.Transaction t) { 1072 recomputeBounds(); 1073 mWindow.drawIfNeeded(t); 1074 } 1075 destroyWindow()1076 void destroyWindow() { 1077 mWindow.releaseSurface(); 1078 } 1079 populateWindowsOnScreen(SparseArray<WindowState> outWindows)1080 private void populateWindowsOnScreen(SparseArray<WindowState> outWindows) { 1081 mTempLayer = 0; 1082 mDisplayContent.forAllWindows((w) -> { 1083 if (w.isOnScreen() && w.isVisible() 1084 && (w.mAttrs.alpha != 0)) { 1085 mTempLayer++; 1086 outWindows.put(mTempLayer, w); 1087 } 1088 }, false /* traverseTopToBottom */ ); 1089 } 1090 getDisplaySizeLocked(Point outSize)1091 private void getDisplaySizeLocked(Point outSize) { 1092 final Rect bounds = 1093 mDisplayContent.getConfiguration().windowConfiguration.getBounds(); 1094 outSize.set(bounds.width(), bounds.height()); 1095 } 1096 dump(PrintWriter pw, String prefix)1097 void dump(PrintWriter pw, String prefix) { 1098 mWindow.dump(pw, prefix); 1099 } 1100 1101 private final class ViewportWindow { 1102 private static final String SURFACE_TITLE = "Magnification Overlay"; 1103 1104 private final Region mBounds = new Region(); 1105 private final Rect mDirtyRect = new Rect(); 1106 private final Paint mPaint = new Paint(); 1107 1108 private final SurfaceControl mSurfaceControl; 1109 private final BLASTBufferQueue mBlastBufferQueue; 1110 private final Surface mSurface; 1111 1112 private final AnimationController mAnimationController; 1113 1114 private boolean mShown; 1115 private int mAlpha; 1116 1117 private boolean mInvalidated; 1118 ViewportWindow(Context context)1119 ViewportWindow(Context context) { 1120 SurfaceControl surfaceControl = null; 1121 try { 1122 surfaceControl = mDisplayContent 1123 .makeOverlay() 1124 .setName(SURFACE_TITLE) 1125 .setBLASTLayer() 1126 .setFormat(PixelFormat.TRANSLUCENT) 1127 .setCallsite("ViewportWindow") 1128 .build(); 1129 } catch (OutOfResourcesException oore) { 1130 /* ignore */ 1131 } 1132 mSurfaceControl = surfaceControl; 1133 mDisplay.getRealSize(mScreenSize); 1134 mBlastBufferQueue = new BLASTBufferQueue(SURFACE_TITLE, mSurfaceControl, 1135 mScreenSize.x, mScreenSize.y, PixelFormat.RGBA_8888); 1136 1137 final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); 1138 final int layer = 1139 mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY) * 1140 WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; 1141 t.setLayer(mSurfaceControl, layer).setPosition(mSurfaceControl, 0, 0); 1142 InputMonitor.setTrustedOverlayInputInfo(mSurfaceControl, t, 1143 mDisplayContent.getDisplayId(), "Magnification Overlay"); 1144 t.apply(); 1145 mSurface = mBlastBufferQueue.createSurface(); 1146 1147 mAnimationController = new AnimationController(context, 1148 mService.mH.getLooper()); 1149 1150 TypedValue typedValue = new TypedValue(); 1151 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight, 1152 typedValue, true); 1153 final int borderColor = context.getColor(typedValue.resourceId); 1154 1155 mPaint.setStyle(Paint.Style.STROKE); 1156 mPaint.setStrokeWidth(mBorderWidth); 1157 mPaint.setColor(borderColor); 1158 1159 mInvalidated = true; 1160 } 1161 setShown(boolean shown, boolean animate)1162 void setShown(boolean shown, boolean animate) { 1163 synchronized (mService.mGlobalLock) { 1164 if (mShown == shown) { 1165 return; 1166 } 1167 mShown = shown; 1168 mAnimationController.onFrameShownStateChanged(shown, animate); 1169 if (DEBUG_VIEWPORT_WINDOW) { 1170 Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown); 1171 } 1172 } 1173 } 1174 1175 @SuppressWarnings("unused") 1176 // Called reflectively from an animator. getAlpha()1177 int getAlpha() { 1178 synchronized (mService.mGlobalLock) { 1179 return mAlpha; 1180 } 1181 } 1182 setAlpha(int alpha)1183 void setAlpha(int alpha) { 1184 synchronized (mService.mGlobalLock) { 1185 if (mAlpha == alpha) { 1186 return; 1187 } 1188 mAlpha = alpha; 1189 invalidate(null); 1190 if (DEBUG_VIEWPORT_WINDOW) { 1191 Slog.i(LOG_TAG, "ViewportWindow set alpha: " + alpha); 1192 } 1193 } 1194 } 1195 setBounds(Region bounds)1196 void setBounds(Region bounds) { 1197 synchronized (mService.mGlobalLock) { 1198 if (mBounds.equals(bounds)) { 1199 return; 1200 } 1201 mBounds.set(bounds); 1202 invalidate(mDirtyRect); 1203 if (DEBUG_VIEWPORT_WINDOW) { 1204 Slog.i(LOG_TAG, "ViewportWindow set bounds: " + bounds); 1205 } 1206 } 1207 } 1208 updateSize()1209 void updateSize() { 1210 synchronized (mService.mGlobalLock) { 1211 getDisplaySizeLocked(mScreenSize); 1212 mBlastBufferQueue.update(mSurfaceControl, mScreenSize.x, mScreenSize.y, 1213 PixelFormat.RGBA_8888); 1214 invalidate(mDirtyRect); 1215 } 1216 } 1217 invalidate(Rect dirtyRect)1218 void invalidate(Rect dirtyRect) { 1219 if (dirtyRect != null) { 1220 mDirtyRect.set(dirtyRect); 1221 } else { 1222 mDirtyRect.setEmpty(); 1223 } 1224 mInvalidated = true; 1225 mService.scheduleAnimationLocked(); 1226 } 1227 drawIfNeeded(SurfaceControl.Transaction t)1228 void drawIfNeeded(SurfaceControl.Transaction t) { 1229 synchronized (mService.mGlobalLock) { 1230 if (!mInvalidated) { 1231 return; 1232 } 1233 mInvalidated = false; 1234 if (mAlpha > 0) { 1235 Canvas canvas = null; 1236 try { 1237 // Empty dirty rectangle means unspecified. 1238 if (mDirtyRect.isEmpty()) { 1239 mBounds.getBounds(mDirtyRect); 1240 } 1241 mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth); 1242 canvas = mSurface.lockCanvas(mDirtyRect); 1243 if (DEBUG_VIEWPORT_WINDOW) { 1244 Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect); 1245 } 1246 } catch (IllegalArgumentException iae) { 1247 /* ignore */ 1248 } catch (Surface.OutOfResourcesException oore) { 1249 /* ignore */ 1250 } 1251 if (canvas == null) { 1252 return; 1253 } 1254 if (DEBUG_VIEWPORT_WINDOW) { 1255 Slog.i(LOG_TAG, "Bounds: " + mBounds); 1256 } 1257 canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); 1258 mPaint.setAlpha(mAlpha); 1259 Path path = mBounds.getBoundaryPath(); 1260 canvas.drawPath(path, mPaint); 1261 1262 mSurface.unlockCanvasAndPost(canvas); 1263 t.show(mSurfaceControl); 1264 } else { 1265 t.hide(mSurfaceControl); 1266 } 1267 } 1268 } 1269 releaseSurface()1270 void releaseSurface() { 1271 if (mBlastBufferQueue != null) { 1272 mBlastBufferQueue.destroy(); 1273 } 1274 mService.mTransactionFactory.get().remove(mSurfaceControl).apply(); 1275 mSurface.release(); 1276 } 1277 dump(PrintWriter pw, String prefix)1278 void dump(PrintWriter pw, String prefix) { 1279 pw.println(prefix 1280 + " mBounds= " + mBounds 1281 + " mDirtyRect= " + mDirtyRect 1282 + " mWidth= " + mScreenSize.x 1283 + " mHeight= " + mScreenSize.y); 1284 } 1285 1286 private final class AnimationController extends Handler { 1287 private static final String PROPERTY_NAME_ALPHA = "alpha"; 1288 1289 private static final int MIN_ALPHA = 0; 1290 private static final int MAX_ALPHA = 255; 1291 1292 private static final int MSG_FRAME_SHOWN_STATE_CHANGED = 1; 1293 1294 private final ValueAnimator mShowHideFrameAnimator; 1295 AnimationController(Context context, Looper looper)1296 AnimationController(Context context, Looper looper) { 1297 super(looper); 1298 mShowHideFrameAnimator = ObjectAnimator.ofInt(ViewportWindow.this, 1299 PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA); 1300 1301 Interpolator interpolator = new DecelerateInterpolator(2.5f); 1302 final long longAnimationDuration = context.getResources().getInteger( 1303 com.android.internal.R.integer.config_longAnimTime); 1304 1305 mShowHideFrameAnimator.setInterpolator(interpolator); 1306 mShowHideFrameAnimator.setDuration(longAnimationDuration); 1307 } 1308 onFrameShownStateChanged(boolean shown, boolean animate)1309 void onFrameShownStateChanged(boolean shown, boolean animate) { 1310 obtainMessage(MSG_FRAME_SHOWN_STATE_CHANGED, 1311 shown ? 1 : 0, animate ? 1 : 0).sendToTarget(); 1312 } 1313 1314 @Override handleMessage(Message message)1315 public void handleMessage(Message message) { 1316 switch (message.what) { 1317 case MSG_FRAME_SHOWN_STATE_CHANGED: { 1318 final boolean shown = message.arg1 == 1; 1319 final boolean animate = message.arg2 == 1; 1320 1321 if (animate) { 1322 if (mShowHideFrameAnimator.isRunning()) { 1323 mShowHideFrameAnimator.reverse(); 1324 } else { 1325 if (shown) { 1326 mShowHideFrameAnimator.start(); 1327 } else { 1328 mShowHideFrameAnimator.reverse(); 1329 } 1330 } 1331 } else { 1332 mShowHideFrameAnimator.cancel(); 1333 if (shown) { 1334 setAlpha(MAX_ALPHA); 1335 } else { 1336 setAlpha(MIN_ALPHA); 1337 } 1338 } 1339 } break; 1340 } 1341 } 1342 } 1343 } 1344 } 1345 1346 private class MyHandler extends Handler { 1347 public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1; 1348 public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3; 1349 public static final int MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED = 4; 1350 public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5; 1351 public static final int MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED = 6; 1352 MyHandler(Looper looper)1353 MyHandler(Looper looper) { 1354 super(looper); 1355 } 1356 1357 @Override handleMessage(Message message)1358 public void handleMessage(Message message) { 1359 switch (message.what) { 1360 case MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED: { 1361 final SomeArgs args = (SomeArgs) message.obj; 1362 final Region magnifiedBounds = (Region) args.arg1; 1363 mCallbacks.onMagnificationRegionChanged(magnifiedBounds); 1364 magnifiedBounds.recycle(); 1365 } break; 1366 1367 case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: { 1368 mCallbacks.onUserContextChanged(); 1369 } break; 1370 1371 case MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED: { 1372 mCallbacks.onDisplaySizeChanged(); 1373 } break; 1374 1375 case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : { 1376 synchronized (mService.mGlobalLock) { 1377 if (mMagnifedViewport.isMagnifying() 1378 || isForceShowingMagnifiableBounds()) { 1379 mMagnifedViewport.setMagnifiedRegionBorderShown(true, true); 1380 mService.scheduleAnimationLocked(); 1381 } 1382 } 1383 } break; 1384 1385 case MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED: { 1386 final boolean shown = message.arg1 == 1; 1387 mCallbacks.onImeWindowVisibilityChanged(shown); 1388 } break; 1389 } 1390 } 1391 } 1392 } 1393 isUntouchableNavigationBar(WindowState windowState, Region touchableRegion)1394 static boolean isUntouchableNavigationBar(WindowState windowState, 1395 Region touchableRegion) { 1396 if (windowState.mAttrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR) { 1397 return false; 1398 } 1399 1400 // Gets the touchable region. 1401 windowState.getTouchableRegion(touchableRegion); 1402 1403 return touchableRegion.isEmpty(); 1404 } 1405 getNavBarInsets(DisplayContent displayContent)1406 static Rect getNavBarInsets(DisplayContent displayContent) { 1407 final InsetsSource source = displayContent.getInsetsStateController().getRawInsetsState() 1408 .peekSource(ITYPE_NAVIGATION_BAR); 1409 return source != null ? source.getFrame() : EMPTY_RECT; 1410 } 1411 getLetterboxBounds(WindowState windowState)1412 static Region getLetterboxBounds(WindowState windowState) { 1413 final ActivityRecord appToken = windowState.mActivityRecord; 1414 if (appToken == null) { 1415 return new Region(); 1416 } 1417 final Rect letterboxInsets = appToken.getLetterboxInsets(); 1418 final Rect nonLetterboxRect = windowState.getBounds(); 1419 nonLetterboxRect.inset(letterboxInsets); 1420 final Region letterboxBounds = new Region(); 1421 letterboxBounds.set(windowState.getBounds()); 1422 letterboxBounds.op(nonLetterboxRect, Region.Op.DIFFERENCE); 1423 return letterboxBounds; 1424 } 1425 1426 /** 1427 * This class encapsulates the functionality related to computing the windows 1428 * reported for accessibility purposes. These windows are all windows a sighted 1429 * user can see on the screen. 1430 */ 1431 private static final class WindowsForAccessibilityObserver { 1432 private static final String LOG_TAG = TAG_WITH_CLASS_NAME ? 1433 "WindowsForAccessibilityObserver" : TAG_WM; 1434 1435 private static final boolean DEBUG = false; 1436 1437 private final List<AccessibilityWindow> mTempA11yWindows = new ArrayList<>(); 1438 1439 private final Set<IBinder> mTempBinderSet = new ArraySet<>(); 1440 1441 private final Point mTempPoint = new Point(); 1442 1443 private final Region mTempRegion = new Region(); 1444 1445 private final Region mTempRegion1 = new Region(); 1446 1447 private final Region mTempRegion2 = new Region(); 1448 1449 private final WindowManagerService mService; 1450 1451 private final Handler mHandler; 1452 1453 private final AccessibilityControllerInternalImpl mAccessibilityTracing; 1454 1455 private final WindowsForAccessibilityCallback mCallback; 1456 1457 private final int mDisplayId; 1458 1459 private final long mRecurringAccessibilityEventsIntervalMillis; 1460 1461 // Set to true if initializing window population complete. 1462 private boolean mInitialized; 1463 private final AccessibilityWindowsPopulator mA11yWindowsPopulator; 1464 WindowsForAccessibilityObserver(WindowManagerService windowManagerService, int displayId, WindowsForAccessibilityCallback callback, AccessibilityWindowsPopulator accessibilityWindowsPopulator)1465 WindowsForAccessibilityObserver(WindowManagerService windowManagerService, 1466 int displayId, WindowsForAccessibilityCallback callback, 1467 AccessibilityWindowsPopulator accessibilityWindowsPopulator) { 1468 mService = windowManagerService; 1469 mCallback = callback; 1470 mDisplayId = displayId; 1471 mHandler = new MyHandler(mService.mH.getLooper()); 1472 mAccessibilityTracing = 1473 AccessibilityController.getAccessibilityControllerInternal(mService); 1474 mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration 1475 .getSendRecurringAccessibilityEventsInterval(); 1476 mA11yWindowsPopulator = accessibilityWindowsPopulator; 1477 computeChangedWindows(true); 1478 } 1479 performComputeChangedWindows(boolean forceSend)1480 void performComputeChangedWindows(boolean forceSend) { 1481 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 1482 mAccessibilityTracing.logTrace(LOG_TAG + ".performComputeChangedWindows", 1483 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, "forceSend=" + forceSend); 1484 } 1485 mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS); 1486 computeChangedWindows(forceSend); 1487 } 1488 scheduleComputeChangedWindows()1489 void scheduleComputeChangedWindows() { 1490 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 1491 mAccessibilityTracing.logTrace(LOG_TAG + ".scheduleComputeChangedWindows", 1492 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK); 1493 } 1494 if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) { 1495 mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS, 1496 mRecurringAccessibilityEventsIntervalMillis); 1497 } 1498 } 1499 1500 /** 1501 * Check if windows have changed, and send them to the accessibility subsystem if they have. 1502 * 1503 * @param forceSend Send the windows the accessibility even if they haven't changed. 1504 */ computeChangedWindows(boolean forceSend)1505 void computeChangedWindows(boolean forceSend) { 1506 if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 1507 mAccessibilityTracing.logTrace(LOG_TAG + ".computeChangedWindows", 1508 FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK, "forceSend=" + forceSend); 1509 } 1510 if (DEBUG) { 1511 Slog.i(LOG_TAG, "computeChangedWindows()"); 1512 } 1513 1514 List<WindowInfo> windows = new ArrayList<>(); 1515 final int topFocusedDisplayId; 1516 IBinder topFocusedWindowToken = null; 1517 1518 synchronized (mService.mGlobalLock) { 1519 // If there is a recents animation running, then use the animation target as the 1520 // top window state. Otherwise,do not send the windows if there is no top focus as 1521 // the window manager is still looking for where to put it. We will do the work when 1522 // we get a focus change callback. 1523 final RecentsAnimationController controller = 1524 mService.getRecentsAnimationController(); 1525 final WindowState topFocusedWindowState = controller != null 1526 ? controller.getTargetAppMainWindow() 1527 : getTopFocusWindow(); 1528 if (topFocusedWindowState == null) { 1529 if (DEBUG) { 1530 Slog.d(LOG_TAG, "top focused window is null, compute it again later"); 1531 } 1532 return; 1533 } 1534 1535 final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); 1536 if (dc == null) { 1537 //It should not happen because it is created while adding the callback. 1538 Slog.w(LOG_TAG, "display content is null, should be created later"); 1539 return; 1540 } 1541 final Display display = dc.getDisplay(); 1542 display.getRealSize(mTempPoint); 1543 final int screenWidth = mTempPoint.x; 1544 final int screenHeight = mTempPoint.y; 1545 1546 Region unaccountedSpace = mTempRegion; 1547 unaccountedSpace.set(0, 0, screenWidth, screenHeight); 1548 1549 final List<AccessibilityWindow> visibleWindows = mTempA11yWindows; 1550 mA11yWindowsPopulator.populateVisibleWindowsOnScreenLocked( 1551 mDisplayId, visibleWindows); 1552 Set<IBinder> addedWindows = mTempBinderSet; 1553 addedWindows.clear(); 1554 1555 boolean focusedWindowAdded = false; 1556 1557 final int visibleWindowCount = visibleWindows.size(); 1558 1559 // Iterate until we figure out what is touchable for the entire screen. 1560 for (int i = 0; i < visibleWindowCount; i++) { 1561 final AccessibilityWindow a11yWindow = visibleWindows.get(i); 1562 final Region regionInWindow = new Region(); 1563 a11yWindow.getTouchableRegionInWindow(regionInWindow); 1564 if (windowMattersToAccessibility(a11yWindow, regionInWindow, 1565 unaccountedSpace)) { 1566 addPopulatedWindowInfo(a11yWindow, regionInWindow, windows, addedWindows); 1567 if (windowMattersToUnaccountedSpaceComputation(a11yWindow)) { 1568 updateUnaccountedSpace(a11yWindow, unaccountedSpace); 1569 } 1570 focusedWindowAdded |= a11yWindow.isFocused(); 1571 } else if (a11yWindow.isUntouchableNavigationBar()) { 1572 // If this widow is navigation bar without touchable region, accounting the 1573 // region of navigation bar inset because all touch events from this region 1574 // would be received by launcher, i.e. this region is a un-touchable one 1575 // for the application. 1576 unaccountedSpace.op(getNavBarInsets(dc), unaccountedSpace, 1577 Region.Op.REVERSE_DIFFERENCE); 1578 } 1579 1580 if (unaccountedSpace.isEmpty() && focusedWindowAdded) { 1581 break; 1582 } 1583 } 1584 1585 // Remove child/parent references to windows that were not added. 1586 final int windowCount = windows.size(); 1587 for (int i = 0; i < windowCount; i++) { 1588 WindowInfo window = windows.get(i); 1589 if (!addedWindows.contains(window.parentToken)) { 1590 window.parentToken = null; 1591 } 1592 if (window.childTokens != null) { 1593 final int childTokenCount = window.childTokens.size(); 1594 for (int j = childTokenCount - 1; j >= 0; j--) { 1595 if (!addedWindows.contains(window.childTokens.get(j))) { 1596 window.childTokens.remove(j); 1597 } 1598 } 1599 // Leave the child token list if empty. 1600 } 1601 } 1602 1603 visibleWindows.clear(); 1604 addedWindows.clear(); 1605 1606 // Gets the top focused display Id and window token for supporting multi-display. 1607 topFocusedDisplayId = mService.mRoot.getTopFocusedDisplayContent().getDisplayId(); 1608 topFocusedWindowToken = topFocusedWindowState.mClient.asBinder(); 1609 } 1610 mCallback.onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId, 1611 topFocusedWindowToken, windows); 1612 1613 // Recycle the windows as we do not need them. 1614 clearAndRecycleWindows(windows); 1615 mInitialized = true; 1616 } 1617 1618 // Some windows should be excluded from unaccounted space computation, though they still 1619 // should be reported windowMattersToUnaccountedSpaceComputation(AccessibilityWindow a11yWindow)1620 private boolean windowMattersToUnaccountedSpaceComputation(AccessibilityWindow a11yWindow) { 1621 // Do not account space of trusted non-touchable windows, except the split-screen 1622 // divider. 1623 // If it's not trusted, touch events are not sent to the windows behind it. 1624 if (!a11yWindow.isTouchable() 1625 && (a11yWindow.getType() != TYPE_DOCK_DIVIDER) 1626 && a11yWindow.isTrustedOverlay()) { 1627 return false; 1628 } 1629 1630 if (a11yWindow.getType() == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) { 1631 return false; 1632 } 1633 return true; 1634 } 1635 windowMattersToAccessibility(AccessibilityWindow a11yWindow, Region regionInScreen, Region unaccountedSpace)1636 private boolean windowMattersToAccessibility(AccessibilityWindow a11yWindow, 1637 Region regionInScreen, Region unaccountedSpace) { 1638 if (a11yWindow.ignoreRecentsAnimationForAccessibility()) { 1639 return false; 1640 } 1641 1642 if (a11yWindow.isFocused()) { 1643 return true; 1644 } 1645 1646 // Ignore non-touchable windows, except the split-screen divider, which is 1647 // occasionally non-touchable but still useful for identifying split-screen 1648 // mode and the PIP menu. 1649 if (!a11yWindow.isTouchable() 1650 && (a11yWindow.getType() != TYPE_DOCK_DIVIDER 1651 && !a11yWindow.isPIPMenu())) { 1652 return false; 1653 } 1654 1655 // If the window is completely covered by other windows - ignore. 1656 if (unaccountedSpace.quickReject(regionInScreen)) { 1657 return false; 1658 } 1659 1660 // Add windows of certain types not covered by modal windows. 1661 if (isReportedWindowType(a11yWindow.getType())) { 1662 return true; 1663 } 1664 1665 return false; 1666 } 1667 updateUnaccountedSpace(AccessibilityWindow a11yWindow, Region unaccountedSpace)1668 private void updateUnaccountedSpace(AccessibilityWindow a11yWindow, 1669 Region unaccountedSpace) { 1670 if (a11yWindow.getType() 1671 != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) { 1672 // Account for the space this window takes if the window 1673 // is not an accessibility overlay which does not change 1674 // the reported windows. 1675 final Region touchableRegion = mTempRegion2; 1676 a11yWindow.getTouchableRegionInScreen(touchableRegion); 1677 unaccountedSpace.op(touchableRegion, unaccountedSpace, 1678 Region.Op.REVERSE_DIFFERENCE); 1679 // Account for the space of letterbox. 1680 final Region letterboxBounds = mTempRegion1; 1681 if (a11yWindow.setLetterBoxBoundsIfNeeded(letterboxBounds)) { 1682 unaccountedSpace.op(letterboxBounds, 1683 unaccountedSpace, Region.Op.REVERSE_DIFFERENCE); 1684 } 1685 } 1686 } 1687 addPopulatedWindowInfo(AccessibilityWindow a11yWindow, Region regionInScreen, List<WindowInfo> out, Set<IBinder> tokenOut)1688 private static void addPopulatedWindowInfo(AccessibilityWindow a11yWindow, 1689 Region regionInScreen, List<WindowInfo> out, Set<IBinder> tokenOut) { 1690 final WindowInfo window = a11yWindow.getWindowInfo(); 1691 window.regionInScreen.set(regionInScreen); 1692 window.layer = tokenOut.size(); 1693 out.add(window); 1694 tokenOut.add(window.token); 1695 } 1696 clearAndRecycleWindows(List<WindowInfo> windows)1697 private static void clearAndRecycleWindows(List<WindowInfo> windows) { 1698 final int windowCount = windows.size(); 1699 for (int i = windowCount - 1; i >= 0; i--) { 1700 windows.remove(i).recycle(); 1701 } 1702 } 1703 isReportedWindowType(int windowType)1704 private static boolean isReportedWindowType(int windowType) { 1705 return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER 1706 && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS 1707 && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY 1708 && windowType != WindowManager.LayoutParams.TYPE_DRAG 1709 && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER 1710 && windowType != WindowManager.LayoutParams.TYPE_POINTER 1711 && windowType != TYPE_MAGNIFICATION_OVERLAY 1712 && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY 1713 && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY 1714 && windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION); 1715 } 1716 getTopFocusWindow()1717 private WindowState getTopFocusWindow() { 1718 return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus; 1719 } 1720 1721 @Override toString()1722 public String toString() { 1723 return "WindowsForAccessibilityObserver{" 1724 + "mDisplayId=" + mDisplayId 1725 + ", mInitialized=" + mInitialized 1726 + '}'; 1727 } 1728 1729 private class MyHandler extends Handler { 1730 public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1; 1731 MyHandler(Looper looper)1732 public MyHandler(Looper looper) { 1733 super(looper, null, false); 1734 } 1735 1736 @Override 1737 @SuppressWarnings("unchecked") handleMessage(Message message)1738 public void handleMessage(Message message) { 1739 switch (message.what) { 1740 case MESSAGE_COMPUTE_CHANGED_WINDOWS: { 1741 computeChangedWindows(false); 1742 } break; 1743 } 1744 } 1745 } 1746 } 1747 1748 static final class AccessibilityControllerInternalImpl 1749 implements AccessibilityControllerInternal { 1750 1751 private static AccessibilityControllerInternalImpl sInstance; getInstance(WindowManagerService service)1752 static AccessibilityControllerInternalImpl getInstance(WindowManagerService service) { 1753 synchronized (STATIC_LOCK) { 1754 if (sInstance == null) { 1755 sInstance = new AccessibilityControllerInternalImpl(service); 1756 } 1757 return sInstance; 1758 } 1759 } 1760 1761 private final AccessibilityTracing mTracing; 1762 private volatile long mEnabledTracingFlags; 1763 private UiChangesForAccessibilityCallbacksDispatcher mCallbacksDispatcher; 1764 private final Looper mLooper; 1765 AccessibilityControllerInternalImpl(WindowManagerService service)1766 private AccessibilityControllerInternalImpl(WindowManagerService service) { 1767 mLooper = service.mH.getLooper(); 1768 mTracing = AccessibilityTracing.getInstance(service); 1769 mEnabledTracingFlags = 0L; 1770 } 1771 1772 @Override startTrace(long loggingTypes)1773 public void startTrace(long loggingTypes) { 1774 mEnabledTracingFlags = loggingTypes; 1775 mTracing.startTrace(); 1776 } 1777 1778 @Override stopTrace()1779 public void stopTrace() { 1780 mTracing.stopTrace(); 1781 mEnabledTracingFlags = 0L; 1782 } 1783 1784 @Override isAccessibilityTracingEnabled()1785 public boolean isAccessibilityTracingEnabled() { 1786 return mTracing.isEnabled(); 1787 } 1788 isTracingEnabled(long flags)1789 boolean isTracingEnabled(long flags) { 1790 return (flags & mEnabledTracingFlags) != 0L; 1791 } 1792 logTrace(String where, long loggingTypes)1793 void logTrace(String where, long loggingTypes) { 1794 logTrace(where, loggingTypes, ""); 1795 } 1796 logTrace(String where, long loggingTypes, String callingParams)1797 void logTrace(String where, long loggingTypes, String callingParams) { 1798 logTrace(where, loggingTypes, callingParams, "".getBytes(), Binder.getCallingUid()); 1799 } 1800 logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid)1801 void logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, 1802 int callingUid) { 1803 mTracing.logState(where, loggingTypes, callingParams, a11yDump, callingUid, 1804 new HashSet<String>(Arrays.asList("logTrace"))); 1805 } 1806 1807 @Override logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] stackTrace, Set<String> ignoreStackEntries)1808 public void logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, 1809 int callingUid, StackTraceElement[] stackTrace, Set<String> ignoreStackEntries) { 1810 mTracing.logState(where, loggingTypes, callingParams, a11yDump, callingUid, stackTrace, 1811 ignoreStackEntries); 1812 } 1813 1814 @Override logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] callStack, long timeStamp, int processId, long threadId, Set<String> ignoreStackEntries)1815 public void logTrace(String where, long loggingTypes, String callingParams, byte[] a11yDump, 1816 int callingUid, StackTraceElement[] callStack, long timeStamp, int processId, 1817 long threadId, Set<String> ignoreStackEntries) { 1818 mTracing.logState(where, loggingTypes, callingParams, a11yDump, callingUid, callStack, 1819 timeStamp, processId, threadId, ignoreStackEntries); 1820 } 1821 1822 @Override setUiChangesForAccessibilityCallbacks( UiChangesForAccessibilityCallbacks callbacks)1823 public void setUiChangesForAccessibilityCallbacks( 1824 UiChangesForAccessibilityCallbacks callbacks) { 1825 if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 1826 logTrace( 1827 TAG + ".setAccessibilityWindowManagerCallbacks", 1828 FLAGS_MAGNIFICATION_CALLBACK, 1829 "callbacks={" + callbacks + "}"); 1830 } 1831 if (callbacks != null) { 1832 if (mCallbacksDispatcher != null) { 1833 throw new IllegalStateException("Accessibility window manager callback already " 1834 + "set!"); 1835 } 1836 mCallbacksDispatcher = 1837 new UiChangesForAccessibilityCallbacksDispatcher(this, mLooper, 1838 callbacks); 1839 } else { 1840 if (mCallbacksDispatcher == null) { 1841 throw new IllegalStateException("Accessibility window manager callback already " 1842 + "cleared!"); 1843 } 1844 mCallbacksDispatcher = null; 1845 } 1846 } 1847 hasWindowManagerEventDispatcher()1848 public boolean hasWindowManagerEventDispatcher() { 1849 if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK 1850 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { 1851 logTrace(TAG + ".hasCallbacks", 1852 FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK); 1853 } 1854 return mCallbacksDispatcher != null; 1855 } 1856 onRectangleOnScreenRequested(int displayId, Rect rectangle)1857 public void onRectangleOnScreenRequested(int displayId, Rect rectangle) { 1858 if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 1859 logTrace( 1860 TAG + ".onRectangleOnScreenRequested", 1861 FLAGS_MAGNIFICATION_CALLBACK, 1862 "rectangle={" + rectangle + "}"); 1863 } 1864 if (mCallbacksDispatcher != null) { 1865 mCallbacksDispatcher.onRectangleOnScreenRequested(displayId, rectangle); 1866 } 1867 } 1868 1869 private static final class UiChangesForAccessibilityCallbacksDispatcher { 1870 1871 private static final String LOG_TAG = TAG_WITH_CLASS_NAME 1872 ? "WindowManagerEventDispatcher" : TAG_WM; 1873 1874 private static final boolean DEBUG_RECTANGLE_REQUESTED = false; 1875 1876 private final AccessibilityControllerInternalImpl mAccessibilityTracing; 1877 1878 @NonNull 1879 private final UiChangesForAccessibilityCallbacks mCallbacks; 1880 1881 private final Handler mHandler; 1882 UiChangesForAccessibilityCallbacksDispatcher( AccessibilityControllerInternalImpl accessibilityControllerInternal, Looper looper, @NonNull UiChangesForAccessibilityCallbacks callbacks)1883 UiChangesForAccessibilityCallbacksDispatcher( 1884 AccessibilityControllerInternalImpl accessibilityControllerInternal, 1885 Looper looper, @NonNull UiChangesForAccessibilityCallbacks callbacks) { 1886 mAccessibilityTracing = accessibilityControllerInternal; 1887 mCallbacks = callbacks; 1888 mHandler = new Handler(looper); 1889 } 1890 onRectangleOnScreenRequested(int displayId, Rect rectangle)1891 void onRectangleOnScreenRequested(int displayId, Rect rectangle) { 1892 if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { 1893 mAccessibilityTracing.logTrace(LOG_TAG + ".onRectangleOnScreenRequested", 1894 FLAGS_MAGNIFICATION_CALLBACK, "rectangle={" + rectangle + "}"); 1895 } 1896 if (DEBUG_RECTANGLE_REQUESTED) { 1897 Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle); 1898 } 1899 final Message m = PooledLambda.obtainMessage( 1900 mCallbacks::onRectangleOnScreenRequested, displayId, rectangle.left, 1901 rectangle.top, rectangle.right, rectangle.bottom); 1902 mHandler.sendMessage(m); 1903 } 1904 } 1905 } 1906 1907 private static final class AccessibilityTracing { 1908 private static AccessibilityTracing sInstance; getInstance(WindowManagerService service)1909 static AccessibilityTracing getInstance(WindowManagerService service) { 1910 synchronized (STATIC_LOCK) { 1911 if (sInstance == null) { 1912 sInstance = new AccessibilityTracing(service); 1913 } 1914 return sInstance; 1915 } 1916 } 1917 1918 private static final int CPU_STATS_COUNT = 5; 1919 private static final int BUFFER_CAPACITY = 1024 * 1024 * 12; 1920 private static final String TRACE_FILENAME = "/data/misc/a11ytrace/a11y_trace" 1921 + WINSCOPE_EXT; 1922 private static final String TAG = "AccessibilityTracing"; 1923 private static final long MAGIC_NUMBER_VALUE = 1924 ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L; 1925 1926 private final Object mLock = new Object(); 1927 private final WindowManagerService mService; 1928 private final File mTraceFile; 1929 private final TraceBuffer mBuffer; 1930 private final LogHandler mHandler; 1931 private volatile boolean mEnabled; 1932 AccessibilityTracing(WindowManagerService service)1933 AccessibilityTracing(WindowManagerService service) { 1934 mService = service; 1935 mTraceFile = new File(TRACE_FILENAME); 1936 mBuffer = new TraceBuffer(BUFFER_CAPACITY); 1937 HandlerThread workThread = new HandlerThread(TAG); 1938 workThread.start(); 1939 mHandler = new LogHandler(workThread.getLooper()); 1940 } 1941 1942 /** 1943 * Start the trace. 1944 */ startTrace()1945 void startTrace() { 1946 if (IS_USER) { 1947 Slog.e(TAG, "Error: Tracing is not supported on user builds."); 1948 return; 1949 } 1950 synchronized (mLock) { 1951 mEnabled = true; 1952 mBuffer.resetBuffer(); 1953 } 1954 } 1955 1956 /** 1957 * Stops the trace and write the current buffer to disk 1958 */ stopTrace()1959 void stopTrace() { 1960 if (IS_USER) { 1961 Slog.e(TAG, "Error: Tracing is not supported on user builds."); 1962 return; 1963 } 1964 synchronized (mLock) { 1965 mEnabled = false; 1966 if (mEnabled) { 1967 Slog.e(TAG, "Error: tracing enabled while waiting for flush."); 1968 return; 1969 } 1970 writeTraceToFile(); 1971 } 1972 } 1973 isEnabled()1974 boolean isEnabled() { 1975 return mEnabled; 1976 } 1977 1978 /** 1979 * Write an accessibility trace log entry. 1980 */ logState(String where, long loggingTypes)1981 void logState(String where, long loggingTypes) { 1982 if (!mEnabled) { 1983 return; 1984 } 1985 logState(where, loggingTypes, ""); 1986 } 1987 1988 /** 1989 * Write an accessibility trace log entry. 1990 */ logState(String where, long loggingTypes, String callingParams)1991 void logState(String where, long loggingTypes, String callingParams) { 1992 if (!mEnabled) { 1993 return; 1994 } 1995 logState(where, loggingTypes, callingParams, "".getBytes()); 1996 } 1997 1998 /** 1999 * Write an accessibility trace log entry. 2000 */ logState(String where, long loggingTypes, String callingParams, byte[] a11yDump)2001 void logState(String where, long loggingTypes, String callingParams, byte[] a11yDump) { 2002 if (!mEnabled) { 2003 return; 2004 } 2005 logState(where, loggingTypes, callingParams, a11yDump, Binder.getCallingUid(), 2006 new HashSet<String>(Arrays.asList("logState"))); 2007 } 2008 2009 /** 2010 * Write an accessibility trace log entry. 2011 */ logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, Set<String> ignoreStackEntries)2012 void logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, 2013 int callingUid, Set<String> ignoreStackEntries) { 2014 if (!mEnabled) { 2015 return; 2016 } 2017 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 2018 ignoreStackEntries.add("logState"); 2019 logState(where, loggingTypes, callingParams, a11yDump, callingUid, stackTraceElements, 2020 ignoreStackEntries); 2021 } 2022 2023 /** 2024 * Write an accessibility trace log entry. 2025 */ logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] stackTrace, Set<String> ignoreStackEntries)2026 void logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, 2027 int callingUid, StackTraceElement[] stackTrace, Set<String> ignoreStackEntries) { 2028 if (!mEnabled) { 2029 return; 2030 } 2031 log(where, loggingTypes, callingParams, a11yDump, callingUid, stackTrace, 2032 SystemClock.elapsedRealtimeNanos(), 2033 Process.myPid() + ":" + Application.getProcessName(), 2034 Thread.currentThread().getId() + ":" + Thread.currentThread().getName(), 2035 ignoreStackEntries); 2036 } 2037 2038 /** 2039 * Write an accessibility trace log entry. 2040 */ logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] callingStack, long timeStamp, int processId, long threadId, Set<String> ignoreStackEntries)2041 void logState(String where, long loggingTypes, String callingParams, byte[] a11yDump, 2042 int callingUid, StackTraceElement[] callingStack, long timeStamp, int processId, 2043 long threadId, Set<String> ignoreStackEntries) { 2044 if (!mEnabled) { 2045 return; 2046 } 2047 log(where, loggingTypes, callingParams, a11yDump, callingUid, callingStack, timeStamp, 2048 String.valueOf(processId), String.valueOf(threadId), ignoreStackEntries); 2049 } 2050 toStackTraceString(StackTraceElement[] stackTraceElements, Set<String> ignoreStackEntries)2051 private String toStackTraceString(StackTraceElement[] stackTraceElements, 2052 Set<String> ignoreStackEntries) { 2053 2054 if (stackTraceElements == null) { 2055 return ""; 2056 } 2057 2058 StringBuilder stringBuilder = new StringBuilder(); 2059 int i = 0; 2060 2061 // Skip the first a few elements until after any ignoreStackEntries 2062 int firstMatch = -1; 2063 while (i < stackTraceElements.length) { 2064 for (String ele : ignoreStackEntries) { 2065 if (stackTraceElements[i].toString().contains(ele)) { 2066 // found the first stack element containing the ignorable stack entries 2067 firstMatch = i; 2068 break; 2069 } 2070 } 2071 if (firstMatch < 0) { 2072 // Haven't found the first match yet, continue 2073 i++; 2074 } else { 2075 break; 2076 } 2077 } 2078 int lastMatch = firstMatch; 2079 if (i < stackTraceElements.length) { 2080 i++; 2081 // Found the first match. Now look for the last match. 2082 while (i < stackTraceElements.length) { 2083 for (String ele : ignoreStackEntries) { 2084 if (stackTraceElements[i].toString().contains(ele)) { 2085 // This is a match. Look at the next stack element. 2086 lastMatch = i; 2087 break; 2088 } 2089 } 2090 if (lastMatch != i) { 2091 // Found a no-match. 2092 break; 2093 } 2094 i++; 2095 } 2096 } 2097 2098 i = lastMatch + 1; 2099 while (i < stackTraceElements.length) { 2100 stringBuilder.append(stackTraceElements[i].toString()).append("\n"); 2101 i++; 2102 } 2103 return stringBuilder.toString(); 2104 } 2105 2106 /** 2107 * Write the current state to the buffer 2108 */ log(String where, long loggingTypes, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] callingStack, long timeStamp, String processName, String threadName, Set<String> ignoreStackEntries)2109 private void log(String where, long loggingTypes, String callingParams, byte[] a11yDump, 2110 int callingUid, StackTraceElement[] callingStack, long timeStamp, 2111 String processName, String threadName, Set<String> ignoreStackEntries) { 2112 SomeArgs args = SomeArgs.obtain(); 2113 args.argl1 = timeStamp; 2114 args.argl2 = loggingTypes; 2115 args.arg1 = where; 2116 args.arg2 = processName; 2117 args.arg3 = threadName; 2118 args.arg4 = ignoreStackEntries; 2119 args.arg5 = callingParams; 2120 args.arg6 = callingStack; 2121 args.arg7 = a11yDump; 2122 2123 mHandler.obtainMessage( 2124 LogHandler.MESSAGE_LOG_TRACE_ENTRY, callingUid, 0, args).sendToTarget(); 2125 } 2126 2127 /** 2128 * Writes the trace buffer to new file for the bugreport. 2129 */ writeTraceToFile()2130 void writeTraceToFile() { 2131 mHandler.sendEmptyMessage(LogHandler.MESSAGE_WRITE_FILE); 2132 } 2133 2134 private class LogHandler extends Handler { 2135 public static final int MESSAGE_LOG_TRACE_ENTRY = 1; 2136 public static final int MESSAGE_WRITE_FILE = 2; 2137 LogHandler(Looper looper)2138 LogHandler(Looper looper) { 2139 super(looper); 2140 } 2141 2142 @Override handleMessage(Message message)2143 public void handleMessage(Message message) { 2144 switch (message.what) { 2145 case MESSAGE_LOG_TRACE_ENTRY: { 2146 final SomeArgs args = (SomeArgs) message.obj; 2147 try { 2148 ProtoOutputStream os = new ProtoOutputStream(); 2149 PackageManagerInternal pmInternal = 2150 LocalServices.getService(PackageManagerInternal.class); 2151 2152 long tokenOuter = os.start(ENTRY); 2153 2154 long reportedTimeStampNanos = args.argl1; 2155 long currentElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos(); 2156 long timeDiffNanos = 2157 currentElapsedRealtimeNanos - reportedTimeStampNanos; 2158 long currentTimeMillis = (new Date()).getTime(); 2159 long reportedTimeMillis = 2160 currentTimeMillis - (long) (timeDiffNanos / 1000000); 2161 SimpleDateFormat fm = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); 2162 2163 os.write(ELAPSED_REALTIME_NANOS, reportedTimeStampNanos); 2164 os.write(CALENDAR_TIME, fm.format(reportedTimeMillis).toString()); 2165 2166 long loggingTypes = args.argl2; 2167 List<String> loggingTypeNames = 2168 AccessibilityTrace.getNamesOfLoggingTypes(loggingTypes); 2169 2170 for (String type : loggingTypeNames) { 2171 os.write(LOGGING_TYPE, type); 2172 } 2173 os.write(WHERE, (String) args.arg1); 2174 os.write(PROCESS_NAME, (String) args.arg2); 2175 os.write(THREAD_ID_NAME, (String) args.arg3); 2176 os.write(CALLING_PKG, pmInternal.getNameForUid(message.arg1)); 2177 os.write(CALLING_PARAMS, (String) args.arg5); 2178 2179 String callingStack = toStackTraceString( 2180 (StackTraceElement[]) args.arg6, (Set<String>) args.arg4); 2181 2182 os.write(CALLING_STACKS, callingStack); 2183 os.write(ACCESSIBILITY_SERVICE, (byte[]) args.arg7); 2184 2185 long tokenInner = os.start(WINDOW_MANAGER_SERVICE); 2186 synchronized (mService.mGlobalLock) { 2187 mService.dumpDebugLocked(os, WindowTraceLogLevel.ALL); 2188 } 2189 os.end(tokenInner); 2190 os.write(CPU_STATS, printCpuStats(reportedTimeStampNanos)); 2191 2192 os.end(tokenOuter); 2193 synchronized (mLock) { 2194 mBuffer.add(os); 2195 } 2196 } catch (Exception e) { 2197 Slog.e(TAG, "Exception while tracing state", e); 2198 } 2199 break; 2200 } 2201 case MESSAGE_WRITE_FILE: { 2202 synchronized (mLock) { 2203 writeTraceToFileInternal(); 2204 } 2205 break; 2206 } 2207 } 2208 } 2209 } 2210 2211 /** 2212 * Writes the trace buffer to disk. 2213 */ writeTraceToFileInternal()2214 private void writeTraceToFileInternal() { 2215 try { 2216 ProtoOutputStream proto = new ProtoOutputStream(); 2217 proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE); 2218 mBuffer.writeTraceToFile(mTraceFile, proto); 2219 } catch (IOException e) { 2220 Slog.e(TAG, "Unable to write buffer to file", e); 2221 } 2222 } 2223 2224 /** 2225 * Returns the string of CPU stats. 2226 */ printCpuStats(long timeStampNanos)2227 private String printCpuStats(long timeStampNanos) { 2228 Pair<String, String> stats = mService.mAmInternal.getAppProfileStatsForDebugging( 2229 timeStampNanos, CPU_STATS_COUNT); 2230 2231 return stats.first + stats.second; 2232 } 2233 } 2234 } 2235