• 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_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