1 /* 2 * Copyright (C) 2019 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.systemui.accessibility; 18 19 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 20 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; 21 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; 22 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 23 24 import static com.android.systemui.accessibility.AccessibilityLogger.MagnificationSettingsEvent; 25 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; 26 27 import android.annotation.MainThread; 28 import android.annotation.Nullable; 29 import android.content.Context; 30 import android.graphics.Rect; 31 import android.hardware.display.DisplayManager; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.util.SparseArray; 36 import android.view.Display; 37 import android.view.IWindowManager; 38 import android.view.SurfaceControl; 39 import android.view.SurfaceControlViewHost; 40 import android.view.WindowManager; 41 import android.view.WindowManagerGlobal; 42 import android.view.accessibility.AccessibilityManager; 43 import android.view.accessibility.IMagnificationConnection; 44 import android.view.accessibility.IRemoteMagnificationAnimationCallback; 45 import android.window.InputTransferToken; 46 47 import androidx.annotation.NonNull; 48 49 import com.android.internal.annotations.VisibleForTesting; 50 import com.android.internal.graphics.SfVsyncFrameCallbackProvider; 51 import com.android.systemui.CoreStartable; 52 import com.android.systemui.Flags; 53 import com.android.systemui.dagger.SysUISingleton; 54 import com.android.systemui.dagger.qualifiers.Main; 55 import com.android.systemui.model.SysUiState; 56 import com.android.systemui.recents.OverviewProxyService; 57 import com.android.systemui.settings.DisplayTracker; 58 import com.android.systemui.statusbar.CommandQueue; 59 import com.android.systemui.util.settings.SecureSettings; 60 61 import java.io.PrintWriter; 62 import java.util.concurrent.Executor; 63 import java.util.function.Supplier; 64 65 import javax.inject.Inject; 66 67 /** 68 * Class to handle the interaction with 69 * {@link com.android.server.accessibility.AccessibilityManagerService}. It invokes 70 * {@link AccessibilityManager#setMagnificationConnection(IMagnificationConnection)} 71 * when {@code IStatusBar#requestWindowMagnificationConnection(boolean)} is called. 72 */ 73 @SysUISingleton 74 public class Magnification implements CoreStartable, CommandQueue.Callbacks { 75 private static final String TAG = "Magnification"; 76 77 @VisibleForTesting static final int DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS = 300; 78 private static final int MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL = 1; 79 80 private final ModeSwitchesController mModeSwitchesController; 81 private final Context mContext; 82 private final Handler mHandler; 83 private final Executor mExecutor; 84 private final AccessibilityManager mAccessibilityManager; 85 private final CommandQueue mCommandQueue; 86 private final OverviewProxyService mOverviewProxyService; 87 private final DisplayTracker mDisplayTracker; 88 private final AccessibilityLogger mA11yLogger; 89 90 private MagnificationConnectionImpl mMagnificationConnectionImpl; 91 private SysUiState mSysUiState; 92 93 @VisibleForTesting 94 SparseArray<SparseArray<Float>> mUsersScales = new SparseArray(); 95 96 private static class WindowMagnificationControllerSupplier extends 97 DisplayIdIndexSupplier<WindowMagnificationController> { 98 99 private final Context mContext; 100 private final Handler mHandler; 101 private final WindowMagnifierCallback mWindowMagnifierCallback; 102 private final SysUiState mSysUiState; 103 private final SecureSettings mSecureSettings; 104 WindowMagnificationControllerSupplier(Context context, Handler handler, WindowMagnifierCallback windowMagnifierCallback, DisplayManager displayManager, SysUiState sysUiState, SecureSettings secureSettings)105 WindowMagnificationControllerSupplier(Context context, Handler handler, 106 WindowMagnifierCallback windowMagnifierCallback, 107 DisplayManager displayManager, SysUiState sysUiState, 108 SecureSettings secureSettings) { 109 super(displayManager); 110 mContext = context; 111 mHandler = handler; 112 mWindowMagnifierCallback = windowMagnifierCallback; 113 mSysUiState = sysUiState; 114 mSecureSettings = secureSettings; 115 } 116 117 @Override createInstance(Display display)118 protected WindowMagnificationController createInstance(Display display) { 119 final Context windowContext = mContext.createWindowContext(display, 120 Flags.createWindowlessWindowMagnifier() 121 ? TYPE_ACCESSIBILITY_OVERLAY 122 : TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, 123 /* options */ null); 124 windowContext.setTheme(com.android.systemui.res.R.style.Theme_SystemUI); 125 126 Supplier<SurfaceControlViewHost> scvhSupplier = () -> 127 Flags.createWindowlessWindowMagnifier() ? new SurfaceControlViewHost(mContext, 128 mContext.getDisplay(), new InputTransferToken(), TAG) : null; 129 130 return new WindowMagnificationController( 131 windowContext, 132 mHandler, 133 new WindowMagnificationAnimationController(windowContext), 134 /* mirrorWindowControl= */ null, 135 new SurfaceControl.Transaction(), 136 mWindowMagnifierCallback, 137 mSysUiState, 138 mSecureSettings, 139 scvhSupplier, 140 new SfVsyncFrameCallbackProvider(), 141 WindowManagerGlobal::getWindowSession); 142 } 143 } 144 145 @VisibleForTesting 146 DisplayIdIndexSupplier<WindowMagnificationController> mWindowMagnificationControllerSupplier; 147 148 private static class FullscreenMagnificationControllerSupplier extends 149 DisplayIdIndexSupplier<FullscreenMagnificationController> { 150 151 private final Context mContext; 152 private final Handler mHandler; 153 private final Executor mExecutor; 154 private final IWindowManager mIWindowManager; 155 FullscreenMagnificationControllerSupplier(Context context, DisplayManager displayManager, Handler handler, Executor executor, IWindowManager iWindowManager)156 FullscreenMagnificationControllerSupplier(Context context, 157 DisplayManager displayManager, 158 Handler handler, 159 Executor executor, IWindowManager iWindowManager) { 160 super(displayManager); 161 mContext = context; 162 mHandler = handler; 163 mExecutor = executor; 164 mIWindowManager = iWindowManager; 165 } 166 167 @Override createInstance(Display display)168 protected FullscreenMagnificationController createInstance(Display display) { 169 final Context windowContext = mContext.createWindowContext(display, 170 TYPE_ACCESSIBILITY_OVERLAY, /* options */ null); 171 Supplier<SurfaceControlViewHost> scvhSupplier = () -> new SurfaceControlViewHost( 172 mContext, mContext.getDisplay(), new InputTransferToken(), TAG); 173 windowContext.setTheme(com.android.systemui.res.R.style.Theme_SystemUI); 174 return new FullscreenMagnificationController( 175 windowContext, 176 mHandler, 177 mExecutor, 178 windowContext.getSystemService(AccessibilityManager.class), 179 windowContext.getSystemService(WindowManager.class), 180 mIWindowManager, 181 scvhSupplier); 182 } 183 } 184 185 @VisibleForTesting 186 DisplayIdIndexSupplier<FullscreenMagnificationController> 187 mFullscreenMagnificationControllerSupplier; 188 189 private static class SettingsSupplier extends 190 DisplayIdIndexSupplier<MagnificationSettingsController> { 191 192 private final Context mContext; 193 private final MagnificationSettingsController.Callback mSettingsControllerCallback; 194 private final SecureSettings mSecureSettings; 195 SettingsSupplier(Context context, MagnificationSettingsController.Callback settingsControllerCallback, DisplayManager displayManager, SecureSettings secureSettings)196 SettingsSupplier(Context context, 197 MagnificationSettingsController.Callback settingsControllerCallback, 198 DisplayManager displayManager, 199 SecureSettings secureSettings) { 200 super(displayManager); 201 mContext = context; 202 mSettingsControllerCallback = settingsControllerCallback; 203 mSecureSettings = secureSettings; 204 } 205 206 @Override createInstance(Display display)207 protected MagnificationSettingsController createInstance(Display display) { 208 final Context windowContext = mContext.createWindowContext(display, 209 TYPE_ACCESSIBILITY_OVERLAY, /* options */ null); 210 windowContext.setTheme(com.android.systemui.res.R.style.Theme_SystemUI); 211 return new MagnificationSettingsController( 212 windowContext, 213 new SfVsyncFrameCallbackProvider(), 214 mSettingsControllerCallback, 215 mSecureSettings); 216 } 217 } 218 219 @VisibleForTesting 220 DisplayIdIndexSupplier<MagnificationSettingsController> mMagnificationSettingsSupplier; 221 222 @Inject Magnification(Context context, @Main Handler mainHandler, @Main Executor executor, CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, SysUiState sysUiState, OverviewProxyService overviewProxyService, SecureSettings secureSettings, DisplayTracker displayTracker, DisplayManager displayManager, AccessibilityLogger a11yLogger, IWindowManager iWindowManager)223 public Magnification(Context context, 224 @Main Handler mainHandler, @Main Executor executor, 225 CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, 226 SysUiState sysUiState, OverviewProxyService overviewProxyService, 227 SecureSettings secureSettings, DisplayTracker displayTracker, 228 DisplayManager displayManager, AccessibilityLogger a11yLogger, 229 IWindowManager iWindowManager) { 230 this(context, mainHandler.getLooper(), executor, commandQueue, 231 modeSwitchesController, sysUiState, overviewProxyService, secureSettings, 232 displayTracker, displayManager, a11yLogger, iWindowManager); 233 } 234 235 @VisibleForTesting Magnification(Context context, Looper looper, @Main Executor executor, CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, SysUiState sysUiState, OverviewProxyService overviewProxyService, SecureSettings secureSettings, DisplayTracker displayTracker, DisplayManager displayManager, AccessibilityLogger a11yLogger, IWindowManager iWindowManager)236 public Magnification(Context context, Looper looper, @Main Executor executor, 237 CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, 238 SysUiState sysUiState, OverviewProxyService overviewProxyService, 239 SecureSettings secureSettings, DisplayTracker displayTracker, 240 DisplayManager displayManager, AccessibilityLogger a11yLogger, 241 IWindowManager iWindowManager) { 242 mContext = context; 243 mHandler = new Handler(looper) { 244 @Override 245 public void handleMessage(@NonNull Message msg) { 246 if (msg.what == MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL) { 247 showMagnificationButtonInternal(msg.arg1, msg.arg2); 248 } 249 } 250 }; 251 mExecutor = executor; 252 mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); 253 mCommandQueue = commandQueue; 254 mModeSwitchesController = modeSwitchesController; 255 mSysUiState = sysUiState; 256 mOverviewProxyService = overviewProxyService; 257 mDisplayTracker = displayTracker; 258 mA11yLogger = a11yLogger; 259 mWindowMagnificationControllerSupplier = new WindowMagnificationControllerSupplier(context, 260 mHandler, mWindowMagnifierCallback, 261 displayManager, sysUiState, secureSettings); 262 mFullscreenMagnificationControllerSupplier = new FullscreenMagnificationControllerSupplier( 263 context, displayManager, mHandler, mExecutor, iWindowManager); 264 mMagnificationSettingsSupplier = new SettingsSupplier(context, 265 mMagnificationSettingsControllerCallback, displayManager, secureSettings); 266 267 mModeSwitchesController.setClickListenerDelegate( 268 displayId -> mHandler.post(() -> { 269 toggleSettingsPanelVisibility(displayId); 270 })); 271 } 272 273 @Override start()274 public void start() { 275 mCommandQueue.addCallback(this); 276 mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() { 277 @Override 278 public void onConnectionChanged(boolean isConnected) { 279 if (isConnected) { 280 updateSysUiStateFlag(); 281 } 282 } 283 }); 284 } 285 updateSysUiStateFlag()286 private void updateSysUiStateFlag() { 287 //TODO(b/187510533): support multi-display once SysuiState supports it. 288 final WindowMagnificationController controller = 289 mWindowMagnificationControllerSupplier.valueAt( 290 mDisplayTracker.getDefaultDisplayId()); 291 if (controller != null) { 292 controller.updateSysUIStateFlag(); 293 } else { 294 // The instance is initialized when there is an IPC request. Considering 295 // self-crash cases, we need to reset the flag in such situation. 296 mSysUiState.setFlag(SYSUI_STATE_MAGNIFICATION_OVERLAP, false) 297 .commitUpdate(mDisplayTracker.getDefaultDisplayId()); 298 } 299 } 300 301 @MainThread enableWindowMagnification(int displayId, float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, @Nullable IRemoteMagnificationAnimationCallback callback)302 void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, 303 float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, 304 @Nullable IRemoteMagnificationAnimationCallback callback) { 305 final WindowMagnificationController windowMagnificationController = 306 mWindowMagnificationControllerSupplier.get(displayId); 307 if (windowMagnificationController != null) { 308 windowMagnificationController.enableWindowMagnification(scale, centerX, centerY, 309 magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, callback); 310 } 311 } 312 313 @MainThread setScaleForWindowMagnification(int displayId, float scale)314 void setScaleForWindowMagnification(int displayId, float scale) { 315 final WindowMagnificationController windowMagnificationController = 316 mWindowMagnificationControllerSupplier.get(displayId); 317 if (windowMagnificationController != null) { 318 windowMagnificationController.setScale(scale); 319 } 320 } 321 322 @MainThread moveWindowMagnifier(int displayId, float offsetX, float offsetY)323 void moveWindowMagnifier(int displayId, float offsetX, float offsetY) { 324 final WindowMagnificationController windowMagnificationcontroller = 325 mWindowMagnificationControllerSupplier.get(displayId); 326 if (windowMagnificationcontroller != null) { 327 windowMagnificationcontroller.moveWindowMagnifier(offsetX, offsetY); 328 } 329 } 330 331 @MainThread moveWindowMagnifierToPositionInternal(int displayId, float positionX, float positionY, IRemoteMagnificationAnimationCallback callback)332 void moveWindowMagnifierToPositionInternal(int displayId, float positionX, float positionY, 333 IRemoteMagnificationAnimationCallback callback) { 334 final WindowMagnificationController windowMagnificationController = 335 mWindowMagnificationControllerSupplier.get(displayId); 336 if (windowMagnificationController != null) { 337 windowMagnificationController.moveWindowMagnifierToPosition(positionX, positionY, 338 callback); 339 } 340 } 341 342 @MainThread disableWindowMagnification(int displayId, @Nullable IRemoteMagnificationAnimationCallback callback)343 void disableWindowMagnification(int displayId, 344 @Nullable IRemoteMagnificationAnimationCallback callback) { 345 final WindowMagnificationController windowMagnificationController = 346 mWindowMagnificationControllerSupplier.get(displayId); 347 if (windowMagnificationController != null) { 348 windowMagnificationController.deleteWindowMagnification(callback); 349 } 350 } 351 352 @MainThread onFullscreenMagnificationActivationChanged(int displayId, boolean activated)353 void onFullscreenMagnificationActivationChanged(int displayId, boolean activated) { 354 final FullscreenMagnificationController fullscreenMagnificationController = 355 mFullscreenMagnificationControllerSupplier.get(displayId); 356 if (fullscreenMagnificationController != null) { 357 fullscreenMagnificationController.onFullscreenMagnificationActivationChanged(activated); 358 } 359 } 360 361 @MainThread toggleSettingsPanelVisibility(int displayId)362 void toggleSettingsPanelVisibility(int displayId) { 363 final MagnificationSettingsController magnificationSettingsController = 364 mMagnificationSettingsSupplier.get(displayId); 365 if (magnificationSettingsController != null) { 366 magnificationSettingsController.toggleSettingsPanelVisibility(); 367 } 368 } 369 370 @MainThread hideMagnificationSettingsPanel(int displayId)371 void hideMagnificationSettingsPanel(int displayId) { 372 final MagnificationSettingsController magnificationSettingsController = 373 mMagnificationSettingsSupplier.get(displayId); 374 if (magnificationSettingsController != null) { 375 magnificationSettingsController.closeMagnificationSettings(); 376 } 377 } 378 isMagnificationSettingsPanelShowing(int displayId)379 boolean isMagnificationSettingsPanelShowing(int displayId) { 380 final MagnificationSettingsController magnificationSettingsController = 381 mMagnificationSettingsSupplier.get(displayId); 382 if (magnificationSettingsController != null) { 383 return magnificationSettingsController.isMagnificationSettingsShowing(); 384 } 385 return false; 386 } 387 388 @MainThread showMagnificationButton(int displayId, int magnificationMode)389 void showMagnificationButton(int displayId, int magnificationMode) { 390 if (Flags.delayShowMagnificationButton()) { 391 if (mHandler.hasMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL)) { 392 return; 393 } 394 mHandler.sendMessageDelayed( 395 mHandler.obtainMessage( 396 MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL, displayId, magnificationMode), 397 DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS); 398 } else { 399 showMagnificationButtonInternal(displayId, magnificationMode); 400 } 401 } 402 403 @MainThread showMagnificationButtonInternal(int displayId, int magnificationMode)404 private void showMagnificationButtonInternal(int displayId, int magnificationMode) { 405 // not to show mode switch button if settings panel is already showing to 406 // prevent settings panel be covered by the button. 407 if (isMagnificationSettingsPanelShowing(displayId)) { 408 return; 409 } 410 mModeSwitchesController.showButton(displayId, magnificationMode); 411 } 412 413 @MainThread removeMagnificationButton(int displayId)414 void removeMagnificationButton(int displayId) { 415 if (Flags.delayShowMagnificationButton()) { 416 mHandler.removeMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL); 417 } 418 mModeSwitchesController.removeButton(displayId); 419 } 420 421 @MainThread setUserMagnificationScale(int userId, int displayId, float scale)422 void setUserMagnificationScale(int userId, int displayId, float scale) { 423 SparseArray<Float> scales = mUsersScales.get(userId); 424 if (scales == null) { 425 scales = new SparseArray<>(); 426 mUsersScales.put(userId, scales); 427 } 428 if (scales.contains(displayId) && scales.get(displayId) == scale) { 429 return; 430 } 431 scales.put(displayId, scale); 432 433 final MagnificationSettingsController magnificationSettingsController = 434 mMagnificationSettingsSupplier.get(displayId); 435 magnificationSettingsController.setMagnificationScale(scale); 436 } 437 438 @VisibleForTesting 439 final WindowMagnifierCallback mWindowMagnifierCallback = new WindowMagnifierCallback() { 440 @Override 441 public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) { 442 if (mMagnificationConnectionImpl != null) { 443 mMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame); 444 } 445 } 446 447 @Override 448 public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { 449 if (mMagnificationConnectionImpl != null) { 450 mMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); 451 } 452 } 453 454 @Override 455 public void onPerformScaleAction(int displayId, float scale, boolean updatePersistence) { 456 if (mMagnificationConnectionImpl != null) { 457 mMagnificationConnectionImpl.onPerformScaleAction( 458 displayId, scale, updatePersistence); 459 } 460 } 461 462 @Override 463 public void onAccessibilityActionPerformed(int displayId) { 464 if (mMagnificationConnectionImpl != null) { 465 mMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); 466 } 467 } 468 469 @Override 470 public void onMove(int displayId) { 471 if (mMagnificationConnectionImpl != null) { 472 mMagnificationConnectionImpl.onMove(displayId); 473 } 474 } 475 476 @Override 477 public void onClickSettingsButton(int displayId) { 478 mHandler.post(() -> { 479 toggleSettingsPanelVisibility(displayId); 480 }); 481 } 482 }; 483 484 @VisibleForTesting 485 final MagnificationSettingsController.Callback mMagnificationSettingsControllerCallback = 486 new MagnificationSettingsController.Callback() { 487 @Override 488 public void onSetMagnifierSize(int displayId, int index) { 489 mHandler.post(() -> onSetMagnifierSizeInternal(displayId, index)); 490 mA11yLogger.logWithPosition( 491 MagnificationSettingsEvent.MAGNIFICATION_SETTINGS_WINDOW_SIZE_SELECTED, 492 index 493 ); 494 } 495 496 @Override 497 public void onSetDiagonalScrolling(int displayId, boolean enable) { 498 mHandler.post(() -> onSetDiagonalScrollingInternal(displayId, enable)); 499 } 500 501 @Override 502 public void onEditMagnifierSizeMode(int displayId, boolean enable) { 503 mHandler.post(() -> onEditMagnifierSizeModeInternal(displayId, enable)); 504 mA11yLogger.log(enable 505 ? 506 MagnificationSettingsEvent 507 .MAGNIFICATION_SETTINGS_SIZE_EDITING_ACTIVATED 508 : MagnificationSettingsEvent 509 .MAGNIFICATION_SETTINGS_SIZE_EDITING_DEACTIVATED); 510 } 511 512 @Override 513 public void onMagnifierScale(int displayId, float scale, 514 boolean updatePersistence) { 515 if (mMagnificationConnectionImpl != null) { 516 mMagnificationConnectionImpl.onPerformScaleAction( 517 displayId, scale, updatePersistence); 518 } 519 mA11yLogger.logThrottled( 520 MagnificationSettingsEvent.MAGNIFICATION_SETTINGS_ZOOM_SLIDER_CHANGED 521 ); 522 } 523 524 @Override 525 public void onModeSwitch(int displayId, int newMode) { 526 mHandler.post(() -> onModeSwitchInternal(displayId, newMode)); 527 } 528 529 @Override 530 public void onSettingsPanelVisibilityChanged(int displayId, boolean shown) { 531 mHandler.post(() -> onSettingsPanelVisibilityChangedInternal(displayId, shown)); 532 } 533 }; 534 535 @MainThread onSetMagnifierSizeInternal(int displayId, int index)536 private void onSetMagnifierSizeInternal(int displayId, int index) { 537 final WindowMagnificationController windowMagnificationController = 538 mWindowMagnificationControllerSupplier.get(displayId); 539 if (windowMagnificationController != null) { 540 windowMagnificationController.changeMagnificationSize(index); 541 } 542 } 543 544 @MainThread onSetDiagonalScrollingInternal(int displayId, boolean enable)545 private void onSetDiagonalScrollingInternal(int displayId, boolean enable) { 546 final WindowMagnificationController windowMagnificationController = 547 mWindowMagnificationControllerSupplier.get(displayId); 548 if (windowMagnificationController != null) { 549 windowMagnificationController.setDiagonalScrolling(enable); 550 } 551 } 552 553 @MainThread onEditMagnifierSizeModeInternal(int displayId, boolean enable)554 private void onEditMagnifierSizeModeInternal(int displayId, boolean enable) { 555 final WindowMagnificationController windowMagnificationController = 556 mWindowMagnificationControllerSupplier.get(displayId); 557 if (windowMagnificationController != null && windowMagnificationController.isActivated()) { 558 windowMagnificationController.setEditMagnifierSizeMode(enable); 559 } 560 } 561 562 @MainThread onModeSwitchInternal(int displayId, int newMode)563 private void onModeSwitchInternal(int displayId, int newMode) { 564 final WindowMagnificationController windowMagnificationController = 565 mWindowMagnificationControllerSupplier.get(displayId); 566 final boolean isWindowMagnifierActivated = windowMagnificationController.isActivated(); 567 final boolean isSwitchToWindowMode = (newMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); 568 final boolean changed = isSwitchToWindowMode ^ isWindowMagnifierActivated; 569 if (changed) { 570 final MagnificationSettingsController magnificationSettingsController = 571 mMagnificationSettingsSupplier.get(displayId); 572 if (magnificationSettingsController != null) { 573 magnificationSettingsController.closeMagnificationSettings(); 574 } 575 if (mMagnificationConnectionImpl != null) { 576 mMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); 577 } 578 } 579 } 580 581 @MainThread onSettingsPanelVisibilityChangedInternal(int displayId, boolean shown)582 private void onSettingsPanelVisibilityChangedInternal(int displayId, boolean shown) { 583 final WindowMagnificationController windowMagnificationController = 584 mWindowMagnificationControllerSupplier.get(displayId); 585 if (windowMagnificationController != null) { 586 boolean isWindowMagnifierActivated = windowMagnificationController.isActivated(); 587 if (isWindowMagnifierActivated) { 588 windowMagnificationController.updateDragHandleResourcesIfNeeded(shown); 589 } 590 591 if (shown) { 592 mA11yLogger.logWithPosition( 593 MagnificationSettingsEvent.MAGNIFICATION_SETTINGS_PANEL_OPENED, 594 isWindowMagnifierActivated 595 ? ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW 596 : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN 597 ); 598 } else { 599 mA11yLogger.log(MagnificationSettingsEvent.MAGNIFICATION_SETTINGS_PANEL_CLOSED); 600 } 601 } 602 } 603 604 @Override requestMagnificationConnection(boolean connect)605 public void requestMagnificationConnection(boolean connect) { 606 if (connect) { 607 setMagnificationConnection(); 608 } else { 609 clearMagnificationConnection(); 610 } 611 } 612 613 @Override dump(PrintWriter pw, String[] args)614 public void dump(PrintWriter pw, String[] args) { 615 pw.println(TAG); 616 mWindowMagnificationControllerSupplier.forEach( 617 magnificationController -> magnificationController.dump(pw)); 618 } 619 setMagnificationConnection()620 private void setMagnificationConnection() { 621 if (mMagnificationConnectionImpl == null) { 622 mMagnificationConnectionImpl = new MagnificationConnectionImpl(this, 623 mHandler); 624 } 625 mAccessibilityManager.setMagnificationConnection( 626 mMagnificationConnectionImpl); 627 } 628 clearMagnificationConnection()629 private void clearMagnificationConnection() { 630 mAccessibilityManager.setMagnificationConnection(null); 631 //TODO: destroy controllers. 632 } 633 } 634