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