• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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