diff options
| author | 2023-03-25 01:09:40 +0000 | |
|---|---|---|
| committer | 2023-03-25 01:09:40 +0000 | |
| commit | 9c31e2931ae9e74d854c51f6337d9d1fbbfe4c06 (patch) | |
| tree | 2b387b27d32f5613d90fe22cb7018efd6208b27d | |
| parent | 19c0b7ee063448cbaa99e5f7d44eb100a8dc1c2a (diff) | |
| parent | 65dbc73925f16d9b33468e1d39ab810048b0b8d4 (diff) | |
Merge changes from topic "magnification_settings" into udc-dev
* changes:
fix(#MagSettingsPanel): modify content desription for buttons
chore(#MagSettingsPanel): adjust magnification settings panel ui when showing for fullscreen magnifier
chore(#MagSettingsPanel): modify MagnificationModeSwitch icon
feat(#MagSettingsPanel)!: support WindowMagnificationSettings for fullscreen magnifier
feat(#MagSettingsPanel): add removeMagnificationSettingsPanel method in WindowMagnificationConnection
feat(#MagSettingsPanel): add MagnificationSettingsController to interact with WindowMagnificationSetting
29 files changed, 1126 insertions, 363 deletions
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl index 62d029bd1be6..8a30f8cebc3d 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl @@ -103,6 +103,13 @@ oneway interface IWindowMagnificationConnection { void removeMagnificationButton(int displayId); /** + * Requests System UI remove magnification settings panel on the specified display. + * + * @param displayId the logical display id. + */ + void removeMagnificationSettingsPanel(int displayId); + + /** * Sets {@link IWindowMagnificationConnectionCallback} to receive the request or the callback. * * @param callback the interface to be called. diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml index f41f78431788..ef450afb18de 100644 --- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml +++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml @@ -17,29 +17,26 @@ <item> <shape android:shape="rectangle"> - <solid android:color="@color/magnification_switch_button_color" /> + <stroke + android:color="@android:color/black" + android:width="@dimen/magnifier_stroke_width"/> + <corners android:radius="@dimen/magnification_setting_drag_corner_radius" /> + <solid android:color="@color/magnification_border_color" /> <size - android:width="48dp" - android:height="48dp" /> + android:width="@dimen/magnification_setting_drag_size" + android:height="@dimen/magnification_setting_drag_size" /> </shape> </item> - <item - android:gravity="center"> - <vector - android:width="36dp" - android:height="36dp" - android:viewportWidth="24" - android:viewportHeight="24"> + <item android:gravity="center"> + <vector android:autoMirrored="true" + android:width="36dp" + android:height="36dp" + android:viewportWidth="48" + android:viewportHeight="48"> <path - android:pathData="M2,12.05V22.05H22V2.05H12V4.05H20V20.05H4V12.05H2Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M10,2.05H2V10.05H10V2.05Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M18,11.05V13.05H14.41L18.95,17.59L17.54,19L13,14.46V18.05H11V11.05H18Z" - android:fillColor="#ffffff"/> + android:pathData="m19.4,44 l-1,-6.3q-0.95,-0.35 -2,-0.95t-1.85,-1.25l-5.9,2.7L4,30l5.4,-3.95q-0.1,-0.45 -0.125,-1.025Q9.25,24.45 9.25,24q0,-0.45 0.025,-1.025T9.4,21.95L4,18l4.65,-8.2 5.9,2.7q0.8,-0.65 1.85,-1.25t2,-0.9l1,-6.35h9.2l1,6.3q0.95,0.35 2.025,0.925Q32.7,11.8 33.45,12.5l5.9,-2.7L44,18l-5.4,3.85q0.1,0.5 0.125,1.075 0.025,0.575 0.025,1.075t-0.025,1.05q-0.025,0.55 -0.125,1.05L44,30l-4.65,8.2 -5.9,-2.7q-0.8,0.65 -1.825,1.275 -1.025,0.625 -2.025,0.925l-1,6.3ZM21.8,41h4.4l0.7,-5.6q1.65,-0.4 3.125,-1.25T32.7,32.1l5.3,2.3 2,-3.6 -4.7,-3.45q0.2,-0.85 0.325,-1.675 0.125,-0.825 0.125,-1.675 0,-0.85 -0.1,-1.675 -0.1,-0.825 -0.35,-1.675L40,17.2l-2,-3.6 -5.3,2.3q-1.15,-1.3 -2.6,-2.175 -1.45,-0.875 -3.2,-1.125L26.2,7h-4.4l-0.7,5.6q-1.7,0.35 -3.175,1.2 -1.475,0.85 -2.625,2.1L10,13.6l-2,3.6 4.7,3.45q-0.2,0.85 -0.325,1.675 -0.125,0.825 -0.125,1.675 0,0.85 0.125,1.675 0.125,0.825 0.325,1.675L8,30.8l2,3.6 5.3,-2.3q1.2,1.2 2.675,2.05Q19.45,35 21.1,35.4ZM24,30.5q2.7,0 4.6,-1.9 1.9,-1.9 1.9,-4.6 0,-2.7 -1.9,-4.6 -1.9,-1.9 -4.6,-1.9 -2.7,0 -4.6,1.9 -1.9,1.9 -1.9,4.6 0,2.7 1.9,4.6 1.9,1.9 4.6,1.9ZM24,24Z" + android:fillColor="#000000"/> </vector> </item> diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml index 3d0741c80450..db8191baa790 100644 --- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml +++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml @@ -63,7 +63,8 @@ android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg" android:src="@drawable/ic_magnification_menu_small" android:tint="@color/accessibility_magnification_image_button_tint" - android:tintMode="src_atop" /> + android:tintMode="src_atop" + android:contentDescription="@string/accessibility_magnification_small" /> <ImageButton android:id="@+id/magnifier_medium_button" @@ -74,7 +75,8 @@ android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg" android:src="@drawable/ic_magnification_menu_medium" android:tint="@color/accessibility_magnification_image_button_tint" - android:tintMode="src_atop" /> + android:tintMode="src_atop" + android:contentDescription="@string/accessibility_magnification_medium" /> <ImageButton android:id="@+id/magnifier_large_button" @@ -85,7 +87,8 @@ android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg" android:src="@drawable/ic_magnification_menu_large" android:tint="@color/accessibility_magnification_image_button_tint" - android:tintMode="src_atop" /> + android:tintMode="src_atop" + android:contentDescription="@string/accessibility_magnification_large" /> <ImageButton android:id="@+id/magnifier_full_button" @@ -96,15 +99,16 @@ android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg" android:src="@drawable/ic_open_in_full" android:tint="@color/accessibility_magnification_image_button_tint" - android:tintMode="src_atop" /> + android:tintMode="src_atop" + android:contentDescription="@string/accessibility_magnification_fullscreen" /> </LinearLayout> <LinearLayout + android:id="@+id/magnifier_horizontal_lock_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="@dimen/magnification_setting_view_margin" - android:layout_marginBottom="@dimen/magnification_setting_view_margin" android:focusable="true"> <TextView @@ -132,6 +136,7 @@ android:layout_height="wrap_content" android:text="@string/accessibility_magnification_zoom" android:textAppearance="@style/TextAppearance.MagnificationSetting.Title" + android:layout_marginTop="@dimen/magnification_setting_view_margin" android:focusable="true" /> <com.android.systemui.common.ui.view.SeekBarWithIconButtonsView diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 0d638f6e68e3..96e6d4e1a234 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -162,7 +162,6 @@ <!-- Window magnification colors --> <color name="magnification_border_color">#F29900</color> - <color name="magnification_switch_button_color">#7F000000</color> <color name="magnification_drag_corner_background">#E5FFFFFF</color> <color name="magnification_drag_handle_stroke">#000000</color> <color name="magnification_drag_handle_background_change">#111111</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 3ab654f63f2a..249fc8664c7e 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1175,6 +1175,8 @@ <dimen name="magnification_setting_image_button_padding_horizontal">24dp</dimen> <dimen name="magnification_setting_image_button_open_in_full_padding_vertical">16dp</dimen> <dimen name="magnification_setting_image_button_open_in_full_padding_horizontal">28dp</dimen> + <dimen name="magnification_setting_drag_corner_radius">28dp</dimen> + <dimen name="magnification_setting_drag_size">56dp</dimen> <!-- Seekbar with icon buttons --> <dimen name="seekbar_icon_size">24dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 2aa912ce250d..e7be6fc80d1c 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2335,8 +2335,6 @@ <string name="magnification_mode_switch_state_full_screen">Magnify full screen</string> <!-- A11y state description for magnification mode switch that device is in window mode. [CHAR LIMIT=NONE] --> <string name="magnification_mode_switch_state_window">Magnify part of screen</string> - <!-- Click action label for magnification switch. [CHAR LIMIT=NONE] --> - <string name="magnification_mode_switch_click_label">Switch</string> <!-- Click action label for magnification settings panel. [CHAR LIMIT=NONE] --> <string name="magnification_open_settings_click_label">Open magnification settings</string> <!-- Label of the corner of a rectangle that you can tap and drag to resize the magnification area. [CHAR LIMIT=NONE] --> @@ -2372,6 +2370,8 @@ <string name="accessibility_magnification_small">Small</string> <!-- Click action label for magnification panel large size [CHAR LIMIT=NONE]--> <string name="accessibility_magnification_large">Large</string> + <!-- Click action label for magnification panel full screen size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_fullscreen">Full screen</string> <!-- Click action label for magnification panel Done [CHAR LIMIT=20]--> <string name="accessibility_magnification_done">Done</string> <!-- Click action label for edit magnification size [CHAR LIMIT=20]--> diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index 59a5b1534990..f817c3cb90a7 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -77,7 +77,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE; private final LayoutParams mParams; - private final SwitchListener mSwitchListener; + private final ClickListener mClickListener; private final Configuration mConfiguration; @VisibleForTesting final Rect mDraggableWindowBounds = new Rect(); @@ -86,30 +86,28 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL private boolean mSingleTapDetected = false; private boolean mToLeftScreenEdge = false; - public interface SwitchListener { + public interface ClickListener { /** * Called when the switch is clicked to change the magnification mode. * @param displayId the display id of the display to which the view's window has been * attached - * @param magnificationMode the magnification mode */ - void onSwitch(int displayId, int magnificationMode); + void onClick(int displayId); } - MagnificationModeSwitch(@UiContext Context context, - SwitchListener switchListener) { - this(context, createView(context), new SfVsyncFrameCallbackProvider(), switchListener); + MagnificationModeSwitch(@UiContext Context context, ClickListener clickListener) { + this(context, createView(context), new SfVsyncFrameCallbackProvider(), clickListener); } @VisibleForTesting MagnificationModeSwitch(Context context, @NonNull ImageView imageView, - SfVsyncFrameCallbackProvider sfVsyncFrameProvider, SwitchListener switchListener) { + SfVsyncFrameCallbackProvider sfVsyncFrameProvider, ClickListener clickListener) { mContext = context; mConfiguration = new Configuration(context.getResources().getConfiguration()); mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); mWindowManager = mContext.getSystemService(WindowManager.class); mSfVsyncFrameProvider = sfVsyncFrameProvider; - mSwitchListener = switchListener; + mClickListener = clickListener; mParams = createLayoutParams(context); mImageView = imageView; mImageView.setOnTouchListener(this::onTouch); @@ -122,7 +120,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL R.string.magnification_mode_switch_description)); final AccessibilityAction clickAction = new AccessibilityAction( AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString( - R.string.magnification_mode_switch_click_label)); + R.string.magnification_open_settings_click_label)); info.addAction(clickAction); info.setClickable(true); info.addAction(new AccessibilityAction(R.id.accessibility_action_move_up, @@ -396,22 +394,14 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL } } - private void toggleMagnificationMode() { - final int newMode = - mMagnificationMode ^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; - mMagnificationMode = newMode; - mImageView.setImageResource(getIconResId(newMode)); - mSwitchListener.onSwitch(mContext.getDisplayId(), newMode); - } - private void handleSingleTap() { removeButton(); - toggleMagnificationMode(); + mClickListener.onClick(mContext.getDisplayId()); } private static ImageView createView(Context context) { ImageView imageView = new ImageView(context); - imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setClickable(true); imageView.setFocusable(true); imageView.setAlpha(0f); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java new file mode 100644 index 000000000000..b6ee4cbc7641 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility; + +import static com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize; + +import android.annotation.NonNull; +import android.annotation.UiContext; +import android.content.ComponentCallbacks; +import android.content.Context; +import android.content.res.Configuration; +import android.util.Range; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; +import com.android.systemui.util.settings.SecureSettings; + +/** + * A class to control {@link WindowMagnificationSettings} and receive settings panel callbacks by + * {@link WindowMagnificationSettingsCallback}. + * The settings panel callbacks will be delegated through + * {@link MagnificationSettingsController.Callback} to {@link WindowMagnification}. + */ + +public class MagnificationSettingsController implements ComponentCallbacks { + + // It should be consistent with the value defined in WindowMagnificationGestureHandler. + private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f); + + private final Context mContext; + + private final int mDisplayId; + + @NonNull + private final Callback mSettingsControllerCallback; + + // Window Magnification Setting view + private WindowMagnificationSettings mWindowMagnificationSettings; + + private final Configuration mConfiguration; + + MagnificationSettingsController( + @UiContext Context context, + SfVsyncFrameCallbackProvider sfVsyncFrameProvider, + @NonNull Callback settingsControllerCallback, + SecureSettings secureSettings) { + this(context, sfVsyncFrameProvider, settingsControllerCallback, secureSettings, null); + } + + @VisibleForTesting + MagnificationSettingsController( + @UiContext Context context, + SfVsyncFrameCallbackProvider sfVsyncFrameProvider, + @NonNull Callback settingsControllerCallback, + SecureSettings secureSettings, + WindowMagnificationSettings windowMagnificationSettings) { + mContext = context; + mDisplayId = mContext.getDisplayId(); + mConfiguration = new Configuration(context.getResources().getConfiguration()); + mSettingsControllerCallback = settingsControllerCallback; + if (windowMagnificationSettings != null) { + mWindowMagnificationSettings = windowMagnificationSettings; + } else { + mWindowMagnificationSettings = new WindowMagnificationSettings(context, + mWindowMagnificationSettingsCallback, + sfVsyncFrameProvider, secureSettings); + } + } + + /** + * Shows magnification settings panel {@link WindowMagnificationSettings}. The panel ui would be + * various for different magnification mode. + * + * @param mode The magnification mode + * @see android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW + * @see android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN + */ + void showMagnificationSettings(int mode) { + if (!mWindowMagnificationSettings.isSettingPanelShowing()) { + onConfigurationChanged(mContext.getResources().getConfiguration()); + mContext.registerComponentCallbacks(this); + } + mWindowMagnificationSettings.showSettingPanel(mode); + } + + void closeMagnificationSettings() { + mContext.unregisterComponentCallbacks(this); + mWindowMagnificationSettings.hideSettingPanel(); + } + + boolean isMagnificationSettingsShowing() { + return mWindowMagnificationSettings.isSettingPanelShowing(); + } + + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + final int configDiff = newConfig.diff(mConfiguration); + mConfiguration.setTo(newConfig); + onConfigurationChanged(configDiff); + } + + @VisibleForTesting + void onConfigurationChanged(int configDiff) { + mWindowMagnificationSettings.onConfigurationChanged(configDiff); + } + + @Override + public void onLowMemory() { + + } + + interface Callback { + + /** + * Called when change magnification size. + * + * @param displayId The logical display id. + * @param index Magnification size index. + * 0 : MagnificationSize.NONE, + * 1 : MagnificationSize.SMALL, + * 2 : MagnificationSize.MEDIUM, + * 3 : MagnificationSize.LARGE, + * 4 : MagnificationSize.FULLSCREEN + */ + void onSetMagnifierSize(int displayId, @MagnificationSize int index); + + /** + * Called when set allow diagonal scrolling. + * + * @param displayId The logical display id. + * @param enable Allow diagonal scrolling enable value. + */ + void onSetDiagonalScrolling(int displayId, boolean enable); + + /** + * Called when change magnification size on free mode. + * + * @param displayId The logical display id. + * @param enable Free mode enable value. + */ + void onEditMagnifierSizeMode(int displayId, boolean enable); + + /** + * Called when set magnification scale. + * + * @param displayId The logical display id. + * @param scale Magnification scale value. + */ + void onMagnifierScale(int displayId, float scale); + + /** + * Called when magnification mode changed. + * + * @param displayId The logical display id. + * @param newMode Magnification mode + * 1 : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, + * 2 : ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW + */ + void onModeSwitch(int displayId, int newMode); + + /** + * Called when the visibility of the magnification settings panel changed. + * + * @param displayId The logical display id. + * @param shown The visibility of the magnification settings panel. + */ + void onSettingsPanelVisibilityChanged(int displayId, boolean shown); + } + + @VisibleForTesting + final WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback = + new WindowMagnificationSettingsCallback() { + @Override + public void onSetDiagonalScrolling(boolean enable) { + mSettingsControllerCallback.onSetDiagonalScrolling(mDisplayId, enable); + } + + @Override + public void onModeSwitch(int newMode) { + mSettingsControllerCallback.onModeSwitch(mDisplayId, newMode); + } + + @Override + public void onSettingsPanelVisibilityChanged(boolean shown) { + mSettingsControllerCallback.onSettingsPanelVisibilityChanged(mDisplayId, shown); + } + + @Override + public void onSetMagnifierSize(@MagnificationSize int index) { + mSettingsControllerCallback.onSetMagnifierSize(mDisplayId, index); + } + + @Override + public void onEditMagnifierSizeMode(boolean enable) { + mSettingsControllerCallback.onEditMagnifierSizeMode(mDisplayId, enable); + } + + @Override + public void onMagnifierScale(float scale) { + mSettingsControllerCallback.onMagnifierScale(mDisplayId, + A11Y_ACTION_SCALE_RANGE.clamp(scale)); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java index 0cc1b2d92e00..63f9cc2c1b53 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java @@ -18,7 +18,7 @@ package com.android.systemui.accessibility; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; -import static com.android.systemui.accessibility.MagnificationModeSwitch.SwitchListener; +import static com.android.systemui.accessibility.MagnificationModeSwitch.ClickListener; import android.annotation.MainThread; import android.content.Context; @@ -37,19 +37,18 @@ import javax.inject.Inject; * <li> Both full-screen and window magnification mode are capable.</li> * <li> The magnification scale is changed by a user.</li> * <ol> - * The switch action will be handled by {@link #mSwitchListenerDelegate} which informs the system - * server about the changed mode. + * The click action will be handled by {@link #mClickListenerDelegate} which opens the + * {@link WindowMagnificationSettings} panel. */ @SysUISingleton -public class ModeSwitchesController implements SwitchListener { +public class ModeSwitchesController implements ClickListener { private final DisplayIdIndexSupplier<MagnificationModeSwitch> mSwitchSupplier; - private SwitchListener mSwitchListenerDelegate; + private ClickListener mClickListenerDelegate; @Inject - public ModeSwitchesController(Context context) { - mSwitchSupplier = new SwitchSupplier(context, - context.getSystemService(DisplayManager.class), this::onSwitch); + public ModeSwitchesController(Context context, DisplayManager displayManager) { + mSwitchSupplier = new SwitchSupplier(context, displayManager, this::onClick); } @VisibleForTesting @@ -102,40 +101,40 @@ public class ModeSwitchesController implements SwitchListener { } @Override - public void onSwitch(int displayId, int magnificationMode) { - if (mSwitchListenerDelegate != null) { - mSwitchListenerDelegate.onSwitch(displayId, magnificationMode); + public void onClick(int displayId) { + if (mClickListenerDelegate != null) { + mClickListenerDelegate.onClick(displayId); } } - public void setSwitchListenerDelegate(SwitchListener switchListenerDelegate) { - mSwitchListenerDelegate = switchListenerDelegate; + public void setClickListenerDelegate(ClickListener clickListenerDelegate) { + mClickListenerDelegate = clickListenerDelegate; } private static class SwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> { private final Context mContext; - private final SwitchListener mSwitchListener; + private final ClickListener mClickListener; /** * Supplies the switch for the given display. * * @param context Context * @param displayManager DisplayManager - * @param switchListener The callback that will run when the switch is clicked + * @param clickListener The callback that will run when the switch is clicked */ SwitchSupplier(Context context, DisplayManager displayManager, - SwitchListener switchListener) { + ClickListener clickListener) { super(displayManager); mContext = context; - mSwitchListener = switchListener; + mClickListener = clickListener; } @Override protected MagnificationModeSwitch createInstance(Display display) { final Context uiContext = mContext.createWindowContext(display, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null); - return new MagnificationModeSwitch(uiContext, mSwitchListener); + return new MagnificationModeSwitch(uiContext, mClickListener); } } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 3653bc80e8ad..1c030da99e15 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -16,6 +16,8 @@ package com.android.systemui.accessibility; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; @@ -55,8 +57,7 @@ import javax.inject.Inject; * when {@code IStatusBar#requestWindowMagnificationConnection(boolean)} is called. */ @SysUISingleton -public class WindowMagnification implements CoreStartable, WindowMagnifierCallback, - CommandQueue.Callbacks { +public class WindowMagnification implements CoreStartable, CommandQueue.Callbacks { private static final String TAG = "WindowMagnification"; private final ModeSwitchesController mModeSwitchesController; @@ -113,11 +114,45 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba @VisibleForTesting DisplayIdIndexSupplier<WindowMagnificationController> mMagnificationControllerSupplier; + private static class SettingsSupplier extends + DisplayIdIndexSupplier<MagnificationSettingsController> { + + private final Context mContext; + private final MagnificationSettingsController.Callback mSettingsControllerCallback; + private final SecureSettings mSecureSettings; + + SettingsSupplier(Context context, + MagnificationSettingsController.Callback settingsControllerCallback, + DisplayManager displayManager, + SecureSettings secureSettings) { + super(displayManager); + mContext = context; + mSettingsControllerCallback = settingsControllerCallback; + mSecureSettings = secureSettings; + } + + @Override + protected MagnificationSettingsController createInstance(Display display) { + final Context windowContext = mContext.createWindowContext(display, + TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null); + windowContext.setTheme(com.android.systemui.R.style.Theme_SystemUI); + return new MagnificationSettingsController( + windowContext, + new SfVsyncFrameCallbackProvider(), + mSettingsControllerCallback, + mSecureSettings); + } + } + + @VisibleForTesting + DisplayIdIndexSupplier<MagnificationSettingsController> mMagnificationSettingsSupplier; + @Inject public WindowMagnification(Context context, @Main Handler mainHandler, CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, SysUiState sysUiState, OverviewProxyService overviewProxyService, - SecureSettings secureSettings, DisplayTracker displayTracker) { + SecureSettings secureSettings, DisplayTracker displayTracker, + DisplayManager displayManager) { mContext = context; mHandler = mainHandler; mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); @@ -127,8 +162,16 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba mOverviewProxyService = overviewProxyService; mDisplayTracker = displayTracker; mMagnificationControllerSupplier = new ControllerSupplier(context, - mHandler, this, context.getSystemService(DisplayManager.class), sysUiState, - secureSettings); + mHandler, mWindowMagnifierCallback, + displayManager, sysUiState, secureSettings); + mMagnificationSettingsSupplier = new SettingsSupplier(context, + mMagnificationSettingsControllerCallback, displayManager, secureSettings); + + mModeSwitchesController.setClickListenerDelegate( + displayId -> mHandler.post(() -> { + showMagnificationSettingsPanel(displayId, + ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + })); } @Override @@ -209,45 +252,181 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba } } - @Override - public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame); + @MainThread + void showMagnificationSettingsPanel(int displayId, int mode) { + final MagnificationSettingsController magnificationSettingsController = + mMagnificationSettingsSupplier.get(displayId); + if (magnificationSettingsController != null) { + magnificationSettingsController.showMagnificationSettings(mode); } } - @Override - public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); + @MainThread + void hideMagnificationSettingsPanel(int displayId) { + final MagnificationSettingsController magnificationSettingsController = + mMagnificationSettingsSupplier.get(displayId); + if (magnificationSettingsController != null) { + magnificationSettingsController.closeMagnificationSettings(); } } - @Override - public void onPerformScaleAction(int displayId, float scale) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onPerformScaleAction(displayId, scale); + boolean isMagnificationSettingsPanelShowing(int displayId) { + final MagnificationSettingsController magnificationSettingsController = + mMagnificationSettingsSupplier.get(displayId); + if (magnificationSettingsController != null) { + return magnificationSettingsController.isMagnificationSettingsShowing(); } + return false; } - @Override - public void onAccessibilityActionPerformed(int displayId) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); + @MainThread + void showMagnificationButton(int displayId, int magnificationMode) { + // not to show mode switch button if settings panel is already showing to + // prevent settings panel be covered by the button. + if (isMagnificationSettingsPanelShowing(displayId)) { + return; } + mModeSwitchesController.showButton(displayId, magnificationMode); } - @Override - public void onMove(int displayId) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onMove(displayId); + @MainThread + void removeMagnificationButton(int displayId) { + mModeSwitchesController.removeButton(displayId); + } + + @VisibleForTesting + final WindowMagnifierCallback mWindowMagnifierCallback = new WindowMagnifierCallback() { + @Override + public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame); + } + } + + @Override + public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); + } + } + + @Override + public void onPerformScaleAction(int displayId, float scale) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onPerformScaleAction(displayId, scale); + } + } + + @Override + public void onAccessibilityActionPerformed(int displayId) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); + } + } + + @Override + public void onMove(int displayId) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onMove(displayId); + } + } + + @Override + public void onClickSettingsButton(int displayId) { + mHandler.post(() -> { + showMagnificationSettingsPanel(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + }); + } + }; + + @VisibleForTesting + final MagnificationSettingsController.Callback mMagnificationSettingsControllerCallback = + new MagnificationSettingsController.Callback() { + @Override + public void onSetMagnifierSize(int displayId, int index) { + mHandler.post(() -> onSetMagnifierSizeInternal(displayId, index)); + } + + @Override + public void onSetDiagonalScrolling(int displayId, boolean enable) { + mHandler.post(() -> onSetDiagonalScrollingInternal(displayId, enable)); + } + + @Override + public void onEditMagnifierSizeMode(int displayId, boolean enable) { + mHandler.post(() -> onEditMagnifierSizeModeInternal(displayId, enable)); + } + + @Override + public void onMagnifierScale(int displayId, float scale) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onPerformScaleAction(displayId, scale); + } + } + + @Override + public void onModeSwitch(int displayId, int newMode) { + mHandler.post(() -> onModeSwitchInternal(displayId, newMode)); + } + + @Override + public void onSettingsPanelVisibilityChanged(int displayId, boolean shown) { + mHandler.post(() -> onSettingsPanelVisibilityChangedInternal(displayId, shown)); + } + }; + + @MainThread + private void onSetMagnifierSizeInternal(int displayId, int index) { + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null) { + windowMagnificationController.changeMagnificationSize(index); } } - @Override - public void onModeSwitch(int displayId, int newMode) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); + @MainThread + private void onSetDiagonalScrollingInternal(int displayId, boolean enable) { + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null) { + windowMagnificationController.setDiagonalScrolling(enable); + } + } + + @MainThread + private void onEditMagnifierSizeModeInternal(int displayId, boolean enable) { + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null && windowMagnificationController.isActivated()) { + windowMagnificationController.setEditMagnifierSizeMode(enable); + } + } + + @MainThread + private void onModeSwitchInternal(int displayId, int newMode) { + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + final boolean isWindowMagnifierActivated = windowMagnificationController.isActivated(); + final boolean isSwitchToWindowMode = (newMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + final boolean changed = isSwitchToWindowMode ^ isWindowMagnifierActivated; + if (changed) { + final MagnificationSettingsController magnificationSettingsController = + mMagnificationSettingsSupplier.get(displayId); + if (magnificationSettingsController != null) { + magnificationSettingsController.closeMagnificationSettings(); + } + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); + } + } + } + + @MainThread + private void onSettingsPanelVisibilityChangedInternal(int displayId, boolean shown) { + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null && windowMagnificationController.isActivated()) { + windowMagnificationController.updateDragHandleResourcesIfNeeded(shown); } } @@ -270,17 +449,14 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba private void setWindowMagnificationConnection() { if (mWindowMagnificationConnectionImpl == null) { mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this, - mHandler, mModeSwitchesController); + mHandler); } - mModeSwitchesController.setSwitchListenerDelegate( - mWindowMagnificationConnectionImpl::onChangeMagnificationMode); mAccessibilityManager.setWindowMagnificationConnection( mWindowMagnificationConnectionImpl); } private void clearWindowMagnificationConnection() { mAccessibilityManager.setWindowMagnificationConnection(null); - mModeSwitchesController.setSwitchListenerDelegate(null); //TODO: destroy controllers. } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java index aa684faee5ab..c081893eac8b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java @@ -39,13 +39,11 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S private IWindowMagnificationConnectionCallback mConnectionCallback; private final WindowMagnification mWindowMagnification; private final Handler mHandler; - private final ModeSwitchesController mModeSwitchesController; WindowMagnificationConnectionImpl(@NonNull WindowMagnification windowMagnification, - @Main Handler mainHandler, ModeSwitchesController modeSwitchesController) { + @Main Handler mainHandler) { mWindowMagnification = windowMagnification; mHandler = mainHandler; - mModeSwitchesController = modeSwitchesController; } @Override @@ -86,13 +84,18 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S @Override public void showMagnificationButton(int displayId, int magnificationMode) { mHandler.post( - () -> mModeSwitchesController.showButton(displayId, magnificationMode)); + () -> mWindowMagnification.showMagnificationButton(displayId, magnificationMode)); } @Override public void removeMagnificationButton(int displayId) { mHandler.post( - () -> mModeSwitchesController.removeButton(displayId)); + () -> mWindowMagnification.removeMagnificationButton(displayId)); + } + + @Override + public void removeMagnificationSettingsPanel(int display) { + mHandler.post(() -> mWindowMagnification.hideMagnificationSettingsPanel(display)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 57c99187c302..a67f706777d9 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -51,6 +51,7 @@ import android.provider.Settings; import android.util.Log; import android.util.Range; import android.util.Size; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Choreographer; import android.view.Display; @@ -103,7 +104,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f); private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f; - private static final float[] MAGNIFICATION_SCALE_OPTIONS = {1.0f, 1.4f, 1.8f, 2.5f}; + private final SparseArray<Float> mMagnificationSizeScaleOptions = new SparseArray<>(); private final Context mContext; private final Resources mResources; @@ -210,9 +211,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private boolean mOverlapWithGestureInsets; private boolean mIsDragging; - // Window Magnification Setting view - private WindowMagnificationSettings mWindowMagnificationSettings; - private static final int MAX_HORIZONTAL_MOVE_ANGLE = 50; private static final int HORIZONTAL = 1; private static final int VERTICAL = 0; @@ -261,6 +259,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mResources.getInteger(R.integer.magnification_default_scale), UserHandle.USER_CURRENT); + setupMagnificationSizeScaleOptions(); mBounceEffectDuration = mResources.getInteger( com.android.internal.R.integer.config_shortAnimTime); @@ -279,10 +278,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mGestureDetector = new MagnificationGestureDetector(mContext, handler, this); - mWindowMagnificationSettings = - new WindowMagnificationSettings(mContext, mWindowMagnificationSettingsCallback, - mSfVsyncFrameProvider, secureSettings); - // Initialize listeners. mMirrorViewRunnable = () -> { if (mMirrorView != null) { @@ -311,7 +306,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorViewGeometryVsyncCallback = l -> { - if (isWindowVisible() && mMirrorSurface != null && calculateSourceBounds( + if (isActivated() && mMirrorSurface != null && calculateSourceBounds( mMagnificationFrame, mScale)) { // The final destination for the magnification surface should be at 0,0 // since the ViewRootImpl's position will change @@ -328,13 +323,20 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } }; mUpdateStateDescriptionRunnable = () -> { - if (isWindowVisible()) { + if (isActivated()) { mMirrorView.setStateDescription(formatStateDescription(mScale)); } }; mWindowInsetChangeRunnable = this::onWindowInsetChanged; } + private void setupMagnificationSizeScaleOptions() { + mMagnificationSizeScaleOptions.clear(); + mMagnificationSizeScaleOptions.put(MagnificationSize.SMALL, 1.4f); + mMagnificationSizeScaleOptions.put(MagnificationSize.MEDIUM, 1.8f); + mMagnificationSizeScaleOptions.put(MagnificationSize.LARGE, 2.5f); + } + private void updateDimensions() { mMirrorSurfaceMargin = mResources.getDimensionPixelSize( R.dimen.magnification_mirror_surface_margin); @@ -368,25 +370,27 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return false; } - @VisibleForTesting void changeMagnificationSize(@MagnificationSize int index) { + if (!mMagnificationSizeScaleOptions.contains(index)) { + return; + } + final float scale = mMagnificationSizeScaleOptions.get(index, 1.0f); final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3; - int size = (int) (initSize * MAGNIFICATION_SCALE_OPTIONS[index]); + int size = (int) (initSize * scale); setWindowSize(size, size); } - @VisibleForTesting void setEditMagnifierSizeMode(boolean enable) { mEditSizeEnable = enable; applyResourcesValues(); - if (isWindowVisible()) { + if (isActivated()) { updateDimensions(); applyTapExcludeRegion(); } } - private void setDiagonalScrolling(boolean enable) { + void setDiagonalScrolling(boolean enable) { mAllowDiagonalScrolling = enable; } @@ -403,22 +407,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mAnimationController.deleteWindowMagnification(animationCallback); } - void deleteWindowMagnification() { - deleteWindowMagnification(/* closeSettingPanel= */ true); - } - /** * Deletes the magnification window. */ - void deleteWindowMagnification(boolean closeSettingPanel) { - if (!isWindowVisible()) { + void deleteWindowMagnification() { + if (!isActivated()) { return; } - if (closeSettingPanel) { - closeMagnificationSettings(); - } - if (mMirrorSurface != null) { mTransaction.remove(mMirrorSurface).apply(); mMirrorSurface = null; @@ -453,7 +449,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold final int configDiff = newConfig.diff(mConfiguration); mConfiguration.setTo(newConfig); onConfigurationChanged(configDiff); - mWindowMagnificationSettings.onConfigurationChanged(configDiff); } @Override @@ -494,8 +489,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // Recreate the window again to correct the window appearance due to density or // window size changed not caused by rotation. - if (isWindowVisible() && reCreateWindow) { - deleteWindowMagnification(/* closeSettingPanel= */ false); + if (isActivated() && reCreateWindow) { + deleteWindowMagnification(); enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); } } @@ -532,7 +527,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } private void updateAccessibilityWindowTitleIfNeeded() { - if (!isWindowVisible()) return; + if (!isActivated()) return; LayoutParams params = (LayoutParams) mMirrorView.getLayoutParams(); params.accessibilityTitle = getAccessibilityWindowTitle(); mWm.updateViewLayout(mMirrorView, params); @@ -703,23 +698,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } } - private void showMagnificationSettings() { - if (mWindowMagnificationSettings != null) { - mWindowMagnificationSettings.showSettingPanel(); - } - } - - private void closeMagnificationSettings() { - if (mWindowMagnificationSettings != null) { - mWindowMagnificationSettings.hideSettingPanel(); - } - } - - @VisibleForTesting - WindowMagnificationSettings getMagnificationSettings() { - return mWindowMagnificationSettings; - } - /** * Sets the window size with given width and height in pixels without changing the * window center. The width or the height will be clamped in the range @@ -845,7 +823,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * {@link #mMagnificationFrame}. */ private void updateMirrorViewLayout(boolean computeWindowSize) { - if (!isWindowVisible()) { + if (!isActivated()) { return; } final int maxMirrorViewX = mWindowBounds.width() - mMirrorView.getWidth(); @@ -1018,7 +996,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } private void updateSysUIState(boolean force) { - final boolean overlap = isWindowVisible() && mSystemGestureTop > 0 + final boolean overlap = isActivated() && mSystemGestureTop > 0 && mMirrorViewBounds.bottom > mSystemGestureTop; if (force || overlap != mOverlapWithGestureInsets) { mOverlapWithGestureInsets = overlap; @@ -1113,7 +1091,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold deleteWindowMagnification(); return; } - if (!isWindowVisible()) { + if (!isActivated()) { onConfigurationChanged(mResources.getConfiguration()); mContext.registerComponentCallbacks(this); } @@ -1138,7 +1116,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold calculateMagnificationFrameBoundary(); updateMagnificationFramePosition((int) offsetX, (int) offsetY); - if (!isWindowVisible()) { + if (!isActivated()) { createMirrorWindow(); showControls(); applyResourcesValues(); @@ -1147,13 +1125,19 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } } + // The magnifier is activated when the window is visible, + // and the window is visible when it is existed. + boolean isActivated() { + return mMirrorView != null; + } + /** * Sets the scale of the magnified region if it's visible. * * @param scale the target scale, or {@link Float#NaN} to leave unchanged */ void setScale(float scale) { - if (mAnimationController.isAnimating() || !isWindowVisible() || mScale == scale) { + if (mAnimationController.isAnimating() || !isActivated() || mScale == scale) { return; } @@ -1216,7 +1200,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @return {@link Float#NaN} if the window is invisible. */ float getScale() { - return isWindowVisible() ? mScale : Float.NaN; + return isActivated() ? mScale : Float.NaN; } /** @@ -1225,7 +1209,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @return the X coordinate. {@link Float#NaN} if the window is invisible. */ float getCenterX() { - return isWindowVisible() ? mMagnificationFrame.exactCenterX() : Float.NaN; + return isActivated() ? mMagnificationFrame.exactCenterX() : Float.NaN; } /** @@ -1234,12 +1218,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @return the Y coordinate. {@link Float#NaN} if the window is invisible. */ float getCenterY() { - return isWindowVisible() ? mMagnificationFrame.exactCenterY() : Float.NaN; - } - - //The window is visible when it is existed. - private boolean isWindowVisible() { - return mMirrorView != null; + return isActivated() ? mMagnificationFrame.exactCenterY() : Float.NaN; } private CharSequence formatStateDescription(float scale) { @@ -1273,7 +1252,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private void handleSingleTap(View view) { int id = view.getId(); if (id == R.id.drag_handle) { - showMagnificationSettings(); + mWindowMagnifierCallback.onClickSettingsButton(mDisplayId); } else if (id == R.id.close_button) { setEditMagnifierSizeMode(false); } else { @@ -1379,40 +1358,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold == Configuration.SCREENLAYOUT_LAYOUTDIR_RTL; } - private WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback = - new WindowMagnificationSettingsCallback() { - @Override - public void onSetDiagonalScrolling(boolean enable) { - setDiagonalScrolling(enable); - } - - @Override - public void onModeSwitch(int newMode) { - mWindowMagnifierCallback.onModeSwitch(mDisplayId, newMode); - } - - @Override - public void onSetMagnifierSize(@MagnificationSize int index) { - changeMagnificationSize(index); - } - - @Override - public void onEditMagnifierSizeMode(boolean enable) { - setEditMagnifierSizeMode(enable); - } - - @Override - public void onMagnifierScale(float scale) { - mWindowMagnifierCallback.onPerformScaleAction(mDisplayId, - A11Y_ACTION_SCALE_RANGE.clamp(scale)); - } - - @Override - public void onSettingsPanelVisibilityChanged(boolean shown) { - updateDragHandleResourcesIfNeeded(/* settingsPanelIsShown= */ shown); - } - }; - @Override public boolean onStart(float x, float y) { mIsDragging = true; @@ -1449,7 +1394,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } } - private void updateDragHandleResourcesIfNeeded(boolean settingsPanelIsShown) { + void updateDragHandleResourcesIfNeeded(boolean settingsPanelIsShown) { + if (!isActivated()) { + return; + } + mDragView.setBackground(mContext.getResources().getDrawable(settingsPanelIsShown ? R.drawable.accessibility_window_magnification_drag_handle_background_change : R.drawable.accessibility_window_magnification_drag_handle_background)); @@ -1476,11 +1425,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold pw.println(" mOverlapWithGestureInsets:" + mOverlapWithGestureInsets); pw.println(" mScale:" + mScale); pw.println(" mWindowBounds:" + mWindowBounds); - pw.println(" mMirrorViewBounds:" + (isWindowVisible() ? mMirrorViewBounds : "empty")); + pw.println(" mMirrorViewBounds:" + (isActivated() ? mMirrorViewBounds : "empty")); pw.println(" mMagnificationFrameBoundary:" - + (isWindowVisible() ? mMagnificationFrameBoundary : "empty")); + + (isActivated() ? mMagnificationFrameBoundary : "empty")); pw.println(" mMagnificationFrame:" - + (isWindowVisible() ? mMagnificationFrame : "empty")); + + (isActivated() ? mMagnificationFrame : "empty")); pw.println(" mSourceBounds:" + (mSourceBounds.isEmpty() ? "empty" : mSourceBounds)); pw.println(" mSystemGestureTop:" + mSystemGestureTop); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java index d9f5544c39b9..71c5f247b899 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java @@ -17,6 +17,8 @@ package com.android.systemui.accessibility; import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import android.annotation.IntDef; @@ -82,6 +84,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest private boolean mSingleTapDetected = false; private SeekBarWithIconButtonsView mZoomSeekbar; + private LinearLayout mAllowDiagonalScrollingView; private Switch mAllowDiagonalScrollingSwitch; private LinearLayout mPanelView; private LinearLayout mSettingView; @@ -91,19 +94,23 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest private ImageButton mLargeButton; private Button mDoneButton; private Button mEditButton; - private ImageButton mChangeModeButton; + private ImageButton mFullScreenButton; private int mLastSelectedButtonIndex = MagnificationSize.NONE; private boolean mAllowDiagonalScrolling = false; private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float A11Y_SCALE_MIN_VALUE = 1.0f; private WindowMagnificationSettingsCallback mCallback; + // the magnification mode that triggers showing the panel + private int mTriggeringMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE; + @Retention(RetentionPolicy.SOURCE) @IntDef({ MagnificationSize.NONE, MagnificationSize.SMALL, MagnificationSize.MEDIUM, MagnificationSize.LARGE, + MagnificationSize.FULLSCREEN }) /** Denotes the Magnification size type. */ public @interface MagnificationSize { @@ -111,6 +118,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest int SMALL = 1; int MEDIUM = 2; int LARGE = 3; + int FULLSCREEN = 4; } @VisibleForTesting @@ -162,39 +170,11 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest } } - private CharSequence formatContentDescription(int viewId) { - if (viewId == R.id.magnifier_small_button) { - return mContext.getResources().getString( - R.string.accessibility_magnification_small); - } else if (viewId == R.id.magnifier_medium_button) { - return mContext.getResources().getString( - R.string.accessibility_magnification_medium); - } else if (viewId == R.id.magnifier_large_button) { - return mContext.getResources().getString( - R.string.accessibility_magnification_large); - } else if (viewId == R.id.magnifier_done_button) { - return mContext.getResources().getString( - R.string.accessibility_magnification_done); - } else if (viewId == R.id.magnifier_edit_button) { - return mContext.getResources().getString( - R.string.accessibility_resize); - } else { - return mContext.getResources().getString( - R.string.magnification_mode_switch_description); - } - } - - private final AccessibilityDelegate mButtonDelegate = new AccessibilityDelegate() { + private final AccessibilityDelegate mPanelDelegate = new AccessibilityDelegate() { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); - info.setContentDescription(formatContentDescription(host.getId())); - final AccessibilityAction clickAction = new AccessibilityAction( - AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString( - R.string.magnification_mode_switch_click_label)); - info.addAction(clickAction); - info.setClickable(true); info.addAction(new AccessibilityAction(R.id.accessibility_action_move_up, mContext.getString(R.string.accessibility_control_move_up))); info.addAction(new AccessibilityAction(R.id.accessibility_action_move_down, @@ -247,13 +227,12 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest setMagnifierSize(MagnificationSize.MEDIUM); } else if (id == R.id.magnifier_large_button) { setMagnifierSize(MagnificationSize.LARGE); + } else if (id == R.id.magnifier_full_button) { + setMagnifierSize(MagnificationSize.FULLSCREEN); } else if (id == R.id.magnifier_edit_button) { editMagnifierSizeMode(true); } else if (id == R.id.magnifier_done_button) { hideSettingPanel(); - } else if (id == R.id.magnifier_full_button) { - hideSettingPanel(); - toggleMagnificationMode(); } } }; @@ -278,7 +257,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest @Override public boolean onFinish(float xOffset, float yOffset) { if (!mSingleTapDetected) { - showSettingPanel(); + showSettingPanel(mTriggeringMode); } mSingleTapDetected = false; return true; @@ -318,27 +297,43 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest mCallback.onSettingsPanelVisibilityChanged(/* shown= */ false); } - public void showSettingPanel() { - showSettingPanel(true); + /** + * Shows magnification settings panel. The panel ui would be various for + * different magnification mode. + * + * @param mode The magnification mode + * @see android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW + * @see android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN + */ + public void showSettingPanel(int mode) { + showSettingPanel(mode, true); + } + + public boolean isSettingPanelShowing() { + return mIsVisible; } public void setScaleSeekbar(float scale) { setSeekbarProgress(scale); } - private void toggleMagnificationMode() { - mCallback.onModeSwitch(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + private void transitToMagnificationMode(int mode) { + mCallback.onModeSwitch(mode); } /** - * Shows magnification panel for set window magnification. + * Shows magnification panel for set magnification. * When the panel is going to be visible by calling this method, the layout position can be * reset depending on the flag. * + * @param mode The magnification mode * @param resetPosition if the button position needs be reset */ - private void showSettingPanel(boolean resetPosition) { + private void showSettingPanel(int mode, boolean resetPosition) { if (!mIsVisible) { + updateUIControlsIfNeed(mode); + mTriggeringMode = mode; + if (resetPosition) { mDraggableWindowBounds.set(getDraggableWindowBounds()); mParams.x = mDraggableWindowBounds.right; @@ -355,6 +350,37 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); } + private void updateUIControlsIfNeed(int mode) { + if (mode == mTriggeringMode) { + return; + } + + int selectedButtonIndex = mLastSelectedButtonIndex; + switch (mode) { + case ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN: + // set the edit button visibility to View.INVISIBLE to keep the height, to prevent + // the size title from too close to the size buttons + mEditButton.setVisibility(View.INVISIBLE); + mAllowDiagonalScrollingView.setVisibility(View.GONE); + // force the fullscreen button showing + selectedButtonIndex = MagnificationSize.FULLSCREEN; + break; + + case ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW: + mEditButton.setVisibility(View.VISIBLE); + mAllowDiagonalScrollingView.setVisibility(View.VISIBLE); + if (selectedButtonIndex == MagnificationSize.FULLSCREEN) { + selectedButtonIndex = MagnificationSize.NONE; + } + break; + + default: + break; + } + + updateSelectedButton(selectedButtonIndex); + } + private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -378,13 +404,15 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest mSettingView.setFocusableInTouchMode(true); mSettingView.setOnTouchListener(this::onTouch); + mSettingView.setAccessibilityDelegate(mPanelDelegate); + mPanelView = mSettingView.findViewById(R.id.magnifier_panel_view); mSmallButton = mSettingView.findViewById(R.id.magnifier_small_button); mMediumButton = mSettingView.findViewById(R.id.magnifier_medium_button); mLargeButton = mSettingView.findViewById(R.id.magnifier_large_button); mDoneButton = mSettingView.findViewById(R.id.magnifier_done_button); mEditButton = mSettingView.findViewById(R.id.magnifier_edit_button); - mChangeModeButton = mSettingView.findViewById(R.id.magnifier_full_button); + mFullScreenButton = mSettingView.findViewById(R.id.magnifier_full_button); mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_slider); float scale = mSecureSettings.getFloatForUser( @@ -393,6 +421,8 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest setSeekbarProgress(scale); mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener()); + mAllowDiagonalScrollingView = + (LinearLayout) mSettingView.findViewById(R.id.magnifier_horizontal_lock_view); mAllowDiagonalScrollingSwitch = (Switch) mSettingView.findViewById(R.id.magnifier_horizontal_lock_switch); mAllowDiagonalScrollingSwitch.setChecked(mAllowDiagonalScrolling); @@ -400,22 +430,11 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest toggleDiagonalScrolling(); }); - mSmallButton.setAccessibilityDelegate(mButtonDelegate); mSmallButton.setOnClickListener(mButtonClickListener); - - mMediumButton.setAccessibilityDelegate(mButtonDelegate); mMediumButton.setOnClickListener(mButtonClickListener); - - mLargeButton.setAccessibilityDelegate(mButtonDelegate); mLargeButton.setOnClickListener(mButtonClickListener); - - mDoneButton.setAccessibilityDelegate(mButtonDelegate); mDoneButton.setOnClickListener(mButtonClickListener); - - mChangeModeButton.setAccessibilityDelegate(mButtonDelegate); - mChangeModeButton.setOnClickListener(mButtonClickListener); - - mEditButton.setAccessibilityDelegate(mButtonDelegate); + mFullScreenButton.setOnClickListener(mButtonClickListener); mEditButton.setOnClickListener(mButtonClickListener); mSettingView.setOnApplyWindowInsetsListener((v, insets) -> { @@ -446,7 +465,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest hideSettingPanel(/* resetPosition= */ false); inflateView(); if (showSettingPanelAfterThemeChange) { - showSettingPanel(/* resetPosition= */ false); + showSettingPanel(mTriggeringMode, /* resetPosition= */ false); } return; } @@ -501,7 +520,18 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest } private void setMagnifierSize(@MagnificationSize int index) { - mCallback.onSetMagnifierSize(index); + if (index == MagnificationSize.FULLSCREEN) { + // transit to fullscreen magnifier if needed + transitToMagnificationMode(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + } else if (index != MagnificationSize.NONE) { + // update the window magnifier size + mCallback.onSetMagnifierSize(index); + // transit to window magnifier if needed + transitToMagnificationMode(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + } else { + return; + } + updateSelectedButton(index); } @@ -573,6 +603,8 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest mMediumButton.setSelected(false); } else if (mLastSelectedButtonIndex == MagnificationSize.LARGE) { mLargeButton.setSelected(false); + } else if (mLastSelectedButtonIndex == MagnificationSize.FULLSCREEN) { + mFullScreenButton.setSelected(false); } // Set the state for selected button @@ -582,6 +614,8 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest mMediumButton.setSelected(true); } else if (index == MagnificationSize.LARGE) { mLargeButton.setSelected(true); + } else if (index == MagnificationSize.FULLSCREEN) { + mFullScreenButton.setSelected(true); } mLastSelectedButtonIndex = index; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java index 1d833402b1f4..3dbff5d7898f 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java @@ -29,7 +29,8 @@ public interface WindowMagnificationSettingsCallback { * * @param index Magnification size index. * 0 : MagnificationSize.NONE, 1 : MagnificationSize.SMALL, - * 2 : MagnificationSize.MEDIUM, 3: MagnificationSize.LARGE + * 2 : MagnificationSize.MEDIUM, 3: MagnificationSize.LARGE, + * 4 : MagnificationSize.FULLSCREEN */ void onSetMagnifierSize(@MagnificationSize int index); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java index 19caaf431e0a..e18161d658a8 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java @@ -62,10 +62,9 @@ interface WindowMagnifierCallback { void onMove(int displayId); /** - * Called when magnification mode changed. + * Called when magnification settings button clicked. * * @param displayId The logical display id. - * @param newMode Magnification mode. */ - void onModeSwitch(int displayId, int newMode); + void onClickSettingsButton(int displayId); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index 213ce9e4d6a1..eff8c019efb4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -16,6 +16,7 @@ package com.android.systemui.accessibility; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -68,6 +69,8 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Mock private WindowMagnificationController mWindowMagnificationController; @Mock + private MagnificationSettingsController mMagnificationSettingsController; + @Mock private ModeSwitchesController mModeSwitchesController; @Mock private SysUiState mSysUiState; @@ -94,9 +97,11 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mWindowMagnification = new WindowMagnification(getContext(), getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController, mSysUiState, mOverviewProxyService, mSecureSettings, - mDisplayTracker); + mDisplayTracker, getContext().getSystemService(DisplayManager.class)); mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier( mContext.getSystemService(DisplayManager.class)); + mWindowMagnification.mMagnificationSettingsSupplier = new FakeSettingsSupplier( + mContext.getSystemService(DisplayManager.class)); mWindowMagnification.requestWindowMagnificationConnection(true); assertNotNull(mIWindowMagnificationConnection); @@ -151,6 +156,9 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Test public void showMagnificationButton() throws RemoteException { + // magnification settings panel should not be showing + assertFalse(mWindowMagnification.isMagnificationSettingsPanelShowing(TEST_DISPLAY)); + mIWindowMagnificationConnection.showMagnificationButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); waitForIdleSync(); @@ -167,6 +175,14 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { verify(mModeSwitchesController).removeButton(TEST_DISPLAY); } + @Test + public void removeMagnificationSettingsPanel() throws RemoteException { + mIWindowMagnificationConnection.removeMagnificationSettingsPanel(TEST_DISPLAY); + waitForIdleSync(); + + verify(mMagnificationSettingsController).closeMagnificationSettings(); + } + private class FakeControllerSupplier extends DisplayIdIndexSupplier<WindowMagnificationController> { @@ -179,5 +195,18 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { return mWindowMagnificationController; } } + + private class FakeSettingsSupplier extends + DisplayIdIndexSupplier<MagnificationSettingsController> { + + FakeSettingsSupplier(DisplayManager displayManager) { + super(displayManager); + } + + @Override + protected MagnificationSettingsController createInstance(Display display) { + return mMagnificationSettingsController; + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index 00cb49169048..79dc057e4f28 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -17,7 +17,6 @@ package com.android.systemui.accessibility; import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; -import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; @@ -45,6 +44,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -57,7 +57,6 @@ import android.os.Handler; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import android.util.SparseIntArray; import android.view.Choreographer; import android.view.MotionEvent; import android.view.View; @@ -100,7 +99,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { private AccessibilityManager mAccessibilityManager; @Mock private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; - private SwitchListenerStub mSwitchListener; + @Mock + private MagnificationModeSwitch.ClickListener mClickListener; private TestableWindowManager mWindowManager; private ViewPropertyAnimator mViewPropertyAnimator; private MagnificationModeSwitch mMagnificationModeSwitch; @@ -113,7 +113,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mContext = Mockito.spy(getContext()); final WindowManager wm = mContext.getSystemService(WindowManager.class); - mSwitchListener = new SwitchListenerStub(); mWindowManager = spy(new TestableWindowManager(wm)); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager); @@ -132,7 +131,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { }).when(mSfVsyncFrameProvider).postFrameCallback( any(Choreographer.FrameCallback.class)); mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView, - mSfVsyncFrameProvider, mSwitchListener); + mSfVsyncFrameProvider, mClickListener); assertNotNull(mTouchListener); } @@ -286,7 +285,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test - public void performSingleTap_fullscreenMode_removeViewAndChangeSettingsValue() { + public void performSingleTap_fullscreenMode_callbackTriggered() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetAndStubMockImageViewAndAnimator(); @@ -298,7 +297,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(downTime, downTime, ACTION_UP, 100, 100)); - verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + verify(mClickListener).onClick(eq(mContext.getDisplayId())); } @Test @@ -347,7 +346,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { mTouchListener.onTouch(mSpyImageView, obtainMotionEvent( downTime, downTime, ACTION_UP, 100 + offset, 100)); - assertModeUnchanged(); + verify(mClickListener, never()).onClick(anyInt()); assertShowFadingAnimation(FADE_OUT_ALPHA); } @@ -363,7 +362,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { mTouchListener.onTouch(mSpyImageView, obtainMotionEvent( downTime, downTime, ACTION_CANCEL, 100, 100)); - assertModeUnchanged(); + verify(mClickListener, never()).onClick(anyInt()); assertShowFadingAnimation(FADE_OUT_ALPHA); } @@ -383,7 +382,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { mTouchListener.onTouch(mSpyImageView, obtainMotionEvent( downTime, downTime, ACTION_CANCEL, 100 + offset, 100)); - assertModeUnchanged(); + verify(mClickListener, never()).onClick(anyInt()); assertShowFadingAnimation(FADE_OUT_ALPHA); } @@ -401,7 +400,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { assertThat(nodeInfo.getActionList(), hasItems(new AccessibilityNodeInfo.AccessibilityAction( ACTION_CLICK.getId(), mContext.getResources().getString( - R.string.magnification_mode_switch_click_label)))); + R.string.magnification_open_settings_click_label)))); assertThat(nodeInfo.getActionList(), hasItems(new AccessibilityNodeInfo.AccessibilityAction( R.id.accessibility_action_move_up, mContext.getResources().getString( @@ -421,14 +420,14 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test - public void performClickA11yActions_showWindowModeButton_verifyTapAction() { + public void performClickA11yActions_showWindowModeButton_callbackTriggered() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetAndStubMockImageViewAndAnimator(); mSpyImageView.performAccessibilityAction( ACTION_CLICK.getId(), null); - verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + verify(mClickListener).onClick(mContext.getDisplayId()); } @Test @@ -534,11 +533,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { assertEquals(expectedY, mWindowManager.getLayoutParamsFromAttachedView().y); } - private void assertModeUnchanged() { - assertEquals(SwitchListenerStub.MODE_INVALID, - mSwitchListener.getChangedMode(mContext.getDisplayId())); - } - private void assertShowFadingAnimation(float alpha) { final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); if (alpha == FADE_IN_ALPHA) { // Fade-in @@ -588,20 +582,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { doNothing().when(mViewPropertyAnimator).start(); } - /** - * Verifies the tap behaviour including the image of the button and the magnification mode. - * - * @param expectedMode the expected mode after tapping - */ - private void verifyTapAction(int expectedMode) { - verify(mViewPropertyAnimator).cancel(); - verify(mSpyImageView).setImageResource( - getIconResId(expectedMode)); - verify(mWindowManager).removeView(mSpyImageView); - final int changedMode = mSwitchListener.getChangedMode(mContext.getDisplayId()); - assertEquals(expectedMode, changedMode); - } - private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action, float x, float y) { return mMotionEventHelper.obtainMotionEvent(downTime, eventTime, action, x, y); @@ -624,20 +604,4 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { assertEquals(expectedX, layoutParams.x); assertEquals(expectedY, layoutParams.y); } - - private static class SwitchListenerStub implements MagnificationModeSwitch.SwitchListener { - - private static final int MODE_INVALID = -1; - - private final SparseIntArray mModes = new SparseIntArray(); - - @Override - public void onSwitch(int displayId, int magnificationMode) { - mModes.put(displayId, magnificationMode); - } - - int getChangedMode(int displayId) { - return mModes.get(displayId, MODE_INVALID); - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java new file mode 100644 index 000000000000..30cbc5242a81 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility; + +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.content.pm.ActivityInfo; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize; +import com.android.systemui.util.settings.SecureSettings; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +/** Tests the MagnificationSettingsController. */ +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class MagnificationSettingsControllerTest extends SysuiTestCase { + + private MagnificationSettingsController mMagnificationSettingsController; + @Mock + private MagnificationSettingsController.Callback mMagnificationSettingControllerCallback; + + @Mock + private WindowMagnificationSettings mWindowMagnificationSettings; + + @Mock + private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; + @Mock + private SecureSettings mSecureSettings; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mMagnificationSettingsController = new MagnificationSettingsController( + mContext, mSfVsyncFrameProvider, + mMagnificationSettingControllerCallback, mSecureSettings, + mWindowMagnificationSettings); + } + + @After + public void tearDown() { + mMagnificationSettingsController.closeMagnificationSettings(); + } + + @Test + public void testShowSettingsPanel() { + final int mode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; + mMagnificationSettingsController.showMagnificationSettings(mode); + + verify(mWindowMagnificationSettings).showSettingPanel(eq(mode)); + } + + @Test + public void testHideSettingsPanel() { + mMagnificationSettingsController.closeMagnificationSettings(); + + verify(mWindowMagnificationSettings).hideSettingPanel(); + } + + @Test + public void testOnConfigurationChanged_notifySettingsPanel() { + mMagnificationSettingsController.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); + + verify(mWindowMagnificationSettings).onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); + } + + @Test + public void testPanelOnSetDiagonalScrolling_delegateToCallback() { + final boolean enable = true; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onSetDiagonalScrolling(enable); + + verify(mMagnificationSettingControllerCallback).onSetDiagonalScrolling( + eq(mContext.getDisplayId()), eq(enable)); + } + + @Test + public void testPanelOnModeSwitch_delegateToCallback() { + final int newMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onModeSwitch(newMode); + + verify(mMagnificationSettingControllerCallback).onModeSwitch( + eq(mContext.getDisplayId()), eq(newMode)); + } + + @Test + public void testPanelOnSettingsPanelVisibilityChanged_delegateToCallback() { + final boolean shown = true; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onSettingsPanelVisibilityChanged(shown); + + verify(mMagnificationSettingControllerCallback).onSettingsPanelVisibilityChanged( + eq(mContext.getDisplayId()), eq(shown)); + } + + @Test + public void testPanelOnSetMagnifierSize_delegateToCallback() { + final @MagnificationSize int index = MagnificationSize.SMALL; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onSetMagnifierSize(index); + + verify(mMagnificationSettingControllerCallback).onSetMagnifierSize( + eq(mContext.getDisplayId()), eq(index)); + } + + @Test + public void testPanelOnEditMagnifierSizeMode_delegateToCallback() { + final boolean enable = true; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onEditMagnifierSizeMode(enable); + + verify(mMagnificationSettingControllerCallback).onEditMagnifierSizeMode( + eq(mContext.getDisplayId()), eq(enable)); + } + + @Test + public void testPanelOnMagnifierScale_delegateToCallback() { + final float scale = 3.0f; + mMagnificationSettingsController.mWindowMagnificationSettingsCallback + .onMagnifierScale(scale); + + verify(mMagnificationSettingControllerCallback).onMagnifierScale( + eq(mContext.getDisplayId()), eq(scale)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java index 82ae6ff1e945..3c974232990a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java @@ -49,7 +49,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { private ModeSwitchesController mModeSwitchesController; private View mSpyView; @Mock - private MagnificationModeSwitch.SwitchListener mListener; + private MagnificationModeSwitch.ClickListener mListener; @Before @@ -57,7 +57,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mSupplier = new FakeSwitchSupplier(mContext.getSystemService(DisplayManager.class)); mModeSwitchesController = new ModeSwitchesController(mSupplier); - mModeSwitchesController.setSwitchListenerDelegate(mListener); + mModeSwitchesController.setClickListenerDelegate(mListener); mModeSwitch = Mockito.spy(new MagnificationModeSwitch(mContext, mModeSwitchesController)); mSpyView = Mockito.spy(new View(mContext)); } @@ -101,8 +101,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { mModeSwitch.onSingleTap(mSpyView); - verify(mListener).onSwitch(mContext.getDisplayId(), - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + verify(mListener).onClick(mContext.getDisplayId()); } private class FakeSwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index de152e4a93d8..b5e0df5d733c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -790,7 +790,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { // should move with both offsetX and offsetY without regrading offsetY/offsetX mInstrumentation.runOnMainSync( () -> { - mController.getMagnificationSettings().setDiagonalScrolling(true); + mController.setDiagonalScrolling(true); mController.moveWindowMagnifier(offsetX, offsetY); }); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 6e4a20aaf6fe..0978c824cb15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -640,6 +640,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { assertTrue( mirrorView.performAccessibilityAction(R.id.accessibility_action_move_left, null)); verify(mWindowMagnifierCallback, times(4)).onMove(eq(displayId)); + + assertTrue(mirrorView.performAccessibilityAction( + AccessibilityAction.ACTION_CLICK.getId(), null)); + verify(mWindowMagnifierCallback).onClickSettingsButton(eq(displayId)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java index 47c91911e52a..c08b5b47cb06 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java @@ -16,6 +16,9 @@ package com.android.systemui.accessibility; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; + import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; @@ -34,7 +37,9 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; +import android.widget.Button; import android.widget.CompoundButton; +import android.widget.LinearLayout; import androidx.test.filters.SmallTest; @@ -97,7 +102,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { @Test public void showSettingPanel_hasAccessibilityWindowTitle() { - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); final WindowManager.LayoutParams layoutPrams = mWindowManager.getLayoutParamsFromAttachedView(); @@ -108,51 +113,77 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { } @Test - public void performClick_smallSizeButton_changeMagnifierSizeSmall() { + public void showSettingPanel_windowMode_showEditButtonAndDiagonalView() { + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + + final Button editButton = getInternalView(R.id.magnifier_edit_button); + assertEquals(editButton.getVisibility(), View.VISIBLE); + + final LinearLayout diagonalView = getInternalView(R.id.magnifier_horizontal_lock_view); + assertEquals(diagonalView.getVisibility(), View.VISIBLE); + } + + @Test + public void showSettingPanel_fullScreenMode_hideEditButtonAndDiagonalView() { + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + + final Button editButton = getInternalView(R.id.magnifier_edit_button); + assertEquals(editButton.getVisibility(), View.INVISIBLE); + + final LinearLayout diagonalView = getInternalView(R.id.magnifier_horizontal_lock_view); + assertEquals(diagonalView.getVisibility(), View.GONE); + } + + @Test + public void performClick_smallSizeButton_changeMagnifierSizeSmallAndSwitchToWindowMode() { // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); - verifyOnSetMagnifierSize(R.id.magnifier_small_button, MAGNIFICATION_SIZE_SMALL); + verifyOnSetMagnifierSizeAndOnModeSwitch( + R.id.magnifier_small_button, MAGNIFICATION_SIZE_SMALL); } @Test - public void performClick_mediumSizeButton_changeMagnifierSizeMedium() { + public void performClick_mediumSizeButton_changeMagnifierSizeMediumAndSwitchToWindowMode() { // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); - verifyOnSetMagnifierSize(R.id.magnifier_medium_button, MAGNIFICATION_SIZE_MEDIUM); + verifyOnSetMagnifierSizeAndOnModeSwitch( + R.id.magnifier_medium_button, MAGNIFICATION_SIZE_MEDIUM); } @Test - public void performClick_largeSizeButton_changeMagnifierSizeLarge() { + public void performClick_largeSizeButton_changeMagnifierSizeLargeAndSwitchToWindowMode() { // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); - verifyOnSetMagnifierSize(R.id.magnifier_large_button, MAGNIFICATION_SIZE_LARGE); + verifyOnSetMagnifierSizeAndOnModeSwitch( + R.id.magnifier_large_button, MAGNIFICATION_SIZE_LARGE); } - private void verifyOnSetMagnifierSize(@IdRes int viewId, int expectedSizeIndex) { + private void verifyOnSetMagnifierSizeAndOnModeSwitch(@IdRes int viewId, int expectedSizeIndex) { View changeSizeButton = getInternalView(viewId); // Perform click changeSizeButton.performClick(); verify(mWindowMagnificationSettingsCallback).onSetMagnifierSize(expectedSizeIndex); + verify(mWindowMagnificationSettingsCallback) + .onModeSwitch(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); } @Test - public void performClick_fullScreenModeButton_setEditMagnifierSizeMode() { + public void performClick_fullScreenModeButton_switchToFullScreenMode() { View fullScreenModeButton = getInternalView(R.id.magnifier_full_button); getInternalView(R.id.magnifier_panel_view); // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); // Perform click fullScreenModeButton.performClick(); - verify(mWindowManager).removeView(mSettingView); verify(mWindowMagnificationSettingsCallback) .onModeSwitch(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } @@ -162,7 +193,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { View editButton = getInternalView(R.id.magnifier_edit_button); // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); // Perform click editButton.performClick(); @@ -178,7 +209,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { final boolean currentCheckedState = diagonalScrollingSwitch.isChecked(); // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); // Perform click diagonalScrollingSwitch.performClick(); @@ -189,7 +220,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { @Test public void onConfigurationChanged_selectedButtonIsStillSelected() { // Open view - mWindowMagnificationSettings.showSettingPanel(); + mWindowMagnificationSettings.showSettingPanel(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); View magnifierMediumButton = getInternalView(R.id.magnifier_medium_button); magnifierMediumButton.performClick(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index 583f2db20570..239b5bd39430 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -16,16 +16,21 @@ package com.android.systemui.accessibility; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; + +import static com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize; import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -80,6 +85,11 @@ public class WindowMagnificationTest extends SysuiTestCase { private OverviewProxyListener mOverviewProxyListener; private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext); + @Mock + private WindowMagnificationController mWindowMagnificationController; + @Mock + private MagnificationSettingsController mMagnificationSettingsController; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -96,7 +106,12 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue = new CommandQueue(getContext(), mDisplayTracker); mWindowMagnification = new WindowMagnification(getContext(), getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController, - mSysUiState, mOverviewProxyService, mSecureSettings, mDisplayTracker); + mSysUiState, mOverviewProxyService, mSecureSettings, mDisplayTracker, + getContext().getSystemService(DisplayManager.class)); + mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier( + mContext.getSystemService(DisplayManager.class), mWindowMagnificationController); + mWindowMagnification.mMagnificationSettingsSupplier = new FakeSettingsSupplier( + mContext.getSystemService(DisplayManager.class), mMagnificationSettingsController); mWindowMagnification.start(); final ArgumentCaptor<OverviewProxyListener> listenerArgumentCaptor = @@ -112,13 +127,11 @@ public class WindowMagnificationTest extends SysuiTestCase { verify(mAccessibilityManager).setWindowMagnificationConnection(any( IWindowMagnificationConnection.class)); - verify(mModeSwitchesController).setSwitchListenerDelegate(notNull()); mCommandQueue.requestWindowMagnificationConnection(false); waitForIdleSync(); verify(mAccessibilityManager).setWindowMagnificationConnection(isNull()); - verify(mModeSwitchesController).setSwitchListenerDelegate(isNull()); } @Test @@ -127,7 +140,8 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onWindowMagnifierBoundsChanged(TEST_DISPLAY, testBounds); + mWindowMagnification.mWindowMagnifierCallback + .onWindowMagnifierBoundsChanged(TEST_DISPLAY, testBounds); verify(mConnectionCallback).onWindowMagnifierBoundsChanged(TEST_DISPLAY, testBounds); } @@ -138,7 +152,8 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onPerformScaleAction(TEST_DISPLAY, newScale); + mWindowMagnification.mWindowMagnifierCallback + .onPerformScaleAction(TEST_DISPLAY, newScale); verify(mConnectionCallback).onPerformScaleAction(TEST_DISPLAY, newScale); } @@ -148,7 +163,8 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onAccessibilityActionPerformed(TEST_DISPLAY); + mWindowMagnification.mWindowMagnifierCallback + .onAccessibilityActionPerformed(TEST_DISPLAY); verify(mConnectionCallback).onAccessibilityActionPerformed(TEST_DISPLAY); } @@ -158,21 +174,101 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onMove(TEST_DISPLAY); + mWindowMagnification.mWindowMagnifierCallback.onMove(TEST_DISPLAY); verify(mConnectionCallback).onMove(TEST_DISPLAY); } @Test - public void onModeSwitch_enabled_notifyCallback() throws RemoteException { - final int magnificationModeFullScreen = 1; + public void onClickSettingsButton_enabled_showPanelForWindowMode() { + mWindowMagnification.mWindowMagnifierCallback.onClickSettingsButton(TEST_DISPLAY); + waitForIdleSync(); + + verify(mMagnificationSettingsController).showMagnificationSettings( + eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); + } + + @Test + public void onSetMagnifierSize_delegateToMagnifier() { + final @MagnificationSize int index = MagnificationSize.SMALL; + mWindowMagnification.mMagnificationSettingsControllerCallback.onSetMagnifierSize( + TEST_DISPLAY, index); + waitForIdleSync(); + + verify(mWindowMagnificationController).changeMagnificationSize(eq(index)); + } + + @Test + public void onSetDiagonalScrolling_delegateToMagnifier() { + mWindowMagnification.mMagnificationSettingsControllerCallback.onSetDiagonalScrolling( + TEST_DISPLAY, /* enable= */ true); + waitForIdleSync(); + + verify(mWindowMagnificationController).setDiagonalScrolling(eq(true)); + } + + @Test + public void onEditMagnifierSizeMode_windowActivated_delegateToMagnifier() { + when(mWindowMagnificationController.isActivated()).thenReturn(true); + mWindowMagnification.mMagnificationSettingsControllerCallback.onEditMagnifierSizeMode( + TEST_DISPLAY, /* enable= */ true); + waitForIdleSync(); + + verify(mWindowMagnificationController).setEditMagnifierSizeMode(eq(true)); + } + + @Test + public void onMagnifierScale_notifyCallback() throws RemoteException { + mCommandQueue.requestWindowMagnificationConnection(true); + waitForIdleSync(); + final float scale = 3.0f; + mWindowMagnification.mMagnificationSettingsControllerCallback.onMagnifierScale( + TEST_DISPLAY, scale); + + verify(mConnectionCallback).onPerformScaleAction(eq(TEST_DISPLAY), eq(scale)); + } + + @Test + public void onModeSwitch_windowEnabledAndSwitchToFullscreen_hidePanelAndNotifyCallback() + throws RemoteException { + when(mWindowMagnificationController.isActivated()).thenReturn(true); + mCommandQueue.requestWindowMagnificationConnection(true); + waitForIdleSync(); + + mWindowMagnification.mMagnificationSettingsControllerCallback.onModeSwitch( + TEST_DISPLAY, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + waitForIdleSync(); + + verify(mMagnificationSettingsController).closeMagnificationSettings(); + verify(mConnectionCallback).onChangeMagnificationMode(eq(TEST_DISPLAY), + eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); + } + + @Test + public void onModeSwitch_switchToSameMode_doNothing() + throws RemoteException { + when(mWindowMagnificationController.isActivated()).thenReturn(true); mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onModeSwitch(TEST_DISPLAY, magnificationModeFullScreen); + mWindowMagnification.mMagnificationSettingsControllerCallback.onModeSwitch( + TEST_DISPLAY, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + waitForIdleSync(); + + verify(mMagnificationSettingsController, never()).closeMagnificationSettings(); + verify(mConnectionCallback, never()).onChangeMagnificationMode(eq(TEST_DISPLAY), + /* magnificationMode = */ anyInt()); + } + + @Test + public void onSettingsPanelVisibilityChanged_windowActivated_delegateToMagnifier() { + when(mWindowMagnificationController.isActivated()).thenReturn(true); + final boolean shown = false; + mWindowMagnification.mMagnificationSettingsControllerCallback + .onSettingsPanelVisibilityChanged(TEST_DISPLAY, shown); + waitForIdleSync(); - verify(mConnectionCallback).onChangeMagnificationMode(TEST_DISPLAY, - magnificationModeFullScreen); + verify(mWindowMagnificationController).updateDragHandleResourcesIfNeeded(eq(shown)); } @Test @@ -211,4 +307,21 @@ public class WindowMagnificationTest extends SysuiTestCase { return mController; } } + + private static class FakeSettingsSupplier extends + DisplayIdIndexSupplier<MagnificationSettingsController> { + + private final MagnificationSettingsController mController; + + FakeSettingsSupplier(DisplayManager displayManager, + MagnificationSettingsController controller) { + super(displayManager); + mController = controller; + } + + @Override + protected MagnificationSettingsController createInstance(Display display) { + return mController; + } + } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index 4753a545adb0..22e742bc0973 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -167,13 +167,19 @@ public class MagnificationController implements WindowMagnificationManager.Callb @Override public void onPerformScaleAction(int displayId, float scale) { - getWindowMagnificationMgr().setScale(displayId, scale); - getWindowMagnificationMgr().persistScale(displayId); + if (getFullScreenMagnificationController().isActivated(displayId)) { + getFullScreenMagnificationController().setScaleAndCenter(displayId, scale, + Float.NaN, Float.NaN, false, MAGNIFICATION_GESTURE_HANDLER_ID); + getFullScreenMagnificationController().persistScale(displayId); + } else if (getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId)) { + getWindowMagnificationMgr().setScale(displayId, scale); + getWindowMagnificationMgr().persistScale(displayId); + } } @Override public void onAccessibilityActionPerformed(int displayId) { - updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + updateMagnificationUIControls(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); } @Override @@ -190,21 +196,22 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (mMagnificationCapabilities != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL) { return; } - if (isActivated(displayId, mode)) { - getWindowMagnificationMgr().showMagnificationButton(displayId, mode); - } + updateMagnificationUIControls(displayId, mode); } - private void updateMagnificationButton(int displayId, int mode) { + private void updateMagnificationUIControls(int displayId, int mode) { final boolean isActivated = isActivated(displayId, mode); - final boolean showButton; + final boolean showUIControls; synchronized (mLock) { - showButton = isActivated && mMagnificationCapabilities + showUIControls = isActivated && mMagnificationCapabilities == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; } - if (showButton) { + if (showUIControls) { + // we only need to show magnification button, the settings panel showing should be + // triggered only on sysui side. getWindowMagnificationMgr().showMagnificationButton(displayId, mode); } else { + getWindowMagnificationMgr().removeMagnificationSettingsPanel(displayId); getWindowMagnificationMgr().removeMagnificationButton(displayId); } } @@ -427,7 +434,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb public void onRequestMagnificationSpec(int displayId, int serviceId) { final WindowMagnificationManager windowMagnificationManager; synchronized (mLock) { - updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + updateMagnificationUIControls(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); windowMagnificationManager = mWindowMagnificationMgr; } if (windowMagnificationManager != null) { @@ -456,7 +463,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, duration); } - updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + updateMagnificationUIControls(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); } @Override @@ -554,7 +561,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, duration); } - updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + updateMagnificationUIControls(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } private void disableWindowMagnificationIfNeeded(int displayId) { @@ -872,7 +879,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb mAms.notifyMagnificationChanged(mDisplayId, region, configBuilder.build()); } } - updateMagnificationButton(mDisplayId, mTargetMode); + updateMagnificationUIControls(mDisplayId, mTargetMode); if (mTransitionCallBack != null) { mTransitionCallBack.onResult(mDisplayId, success); } @@ -900,7 +907,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb setExpiredAndRemoveFromListLocked(); setTransitionState(mDisplayId, null); applyMagnificationModeLocked(mCurrentMode); - updateMagnificationButton(mDisplayId, mCurrentMode); + updateMagnificationUIControls(mDisplayId, mCurrentMode); if (mTransitionCallBack != null) { mTransitionCallBack.onResult(mDisplayId, true); } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java index 041eece5ce48..1202cfadb44e 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java @@ -185,6 +185,22 @@ class WindowMagnificationConnectionWrapper { return true; } + boolean removeMagnificationSettingsPanel(int displayId) { + if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) { + mTrace.logTrace(TAG + ".removeMagnificationSettingsPanel", + FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId); + } + try { + mConnection.removeMagnificationSettingsPanel(displayId); + } catch (RemoteException e) { + if (DBG) { + Slog.e(TAG, "Error calling removeMagnificationSettingsPanel()", e); + } + return false; + } + return true; + } + boolean setConnectionCallback(IWindowMagnificationConnectionCallback connectionCallback) { if (mTrace.isA11yTracingEnabledForTypes( FLAGS_WINDOW_MAGNIFICATION_CONNECTION diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index d9391f422dc7..ce18b2cf9bad 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -779,8 +779,10 @@ public class WindowMagnificationManager implements * @return {@code true} if the event was handled, {@code false} otherwise */ public boolean showMagnificationButton(int displayId, int magnificationMode) { - return mConnectionWrapper != null && mConnectionWrapper.showMagnificationButton( - displayId, magnificationMode); + synchronized (mLock) { + return mConnectionWrapper != null + && mConnectionWrapper.showMagnificationButton(displayId, magnificationMode); + } } /** @@ -790,8 +792,23 @@ public class WindowMagnificationManager implements * @return {@code true} if the event was handled, {@code false} otherwise */ public boolean removeMagnificationButton(int displayId) { - return mConnectionWrapper != null && mConnectionWrapper.removeMagnificationButton( - displayId); + synchronized (mLock) { + return mConnectionWrapper != null + && mConnectionWrapper.removeMagnificationButton(displayId); + } + } + + /** + * Requests System UI remove magnification settings panel on the specified display. + * + * @param displayId The logical display id. + * @return {@code true} if the event was handled, {@code false} otherwise + */ + public boolean removeMagnificationSettingsPanel(int displayId) { + synchronized (mLock) { + return mConnectionWrapper != null + && mConnectionWrapper.removeMagnificationSettingsPanel(displayId); + } } /** diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java index bbcb376180b7..913d8c1dda20 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java @@ -559,7 +559,21 @@ public class MagnificationControllerTest { } @Test - public void onPerformScaleAction_magnifierEnabled_handleScaleChange() throws RemoteException { + public void onPerformScaleAction_fullScreenMagnifierEnabled_handleScaleChange() + throws RemoteException { + final float newScale = 4.0f; + setMagnificationEnabled(MODE_FULLSCREEN); + + mMagnificationController.onPerformScaleAction(TEST_DISPLAY, newScale); + + verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), eq(newScale), + anyFloat(), anyFloat(), anyBoolean(), anyInt()); + verify(mScreenMagnificationController).persistScale(eq(TEST_DISPLAY)); + } + + @Test + public void onPerformScaleAction_windowMagnifierEnabled_handleScaleChange() + throws RemoteException { final float newScale = 4.0f; setMagnificationEnabled(MODE_WINDOW); @@ -1035,6 +1049,25 @@ public class MagnificationControllerTest { } @Test + public void disableWindowMode_windowEnabled_removeMagnificationSettingsPanel() + throws RemoteException { + setMagnificationEnabled(MODE_WINDOW); + + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + + verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + } + + @Test + public void onFullScreenDeactivated_fullScreenEnabled_removeMagnificationSettingsPanel() + throws RemoteException { + setMagnificationEnabled(MODE_FULLSCREEN); + mScreenMagnificationController.reset(TEST_DISPLAY, /* animate= */ true); + + verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + } + + @Test public void imeWindowStateShown_windowMagnifying_logWindowMode() { MagnificationController spyController = spy(mMagnificationController); spyController.onWindowMagnificationActivationState(TEST_DISPLAY, true); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java index 4b77764c41e5..2357e65871e6 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java @@ -116,6 +116,12 @@ public class WindowMagnificationConnectionWrapperTest { } @Test + public void removeMagnificationSettingsPanel() throws RemoteException { + mConnectionWrapper.removeMagnificationSettingsPanel(TEST_DISPLAY); + verify(mConnection).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + } + + @Test public void setMirrorWindowCallback() throws RemoteException { mConnectionWrapper.setConnectionCallback(mCallback); verify(mConnection).setConnectionCallback(mCallback); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java index d841dfc2d54b..b0fd64976c48 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java @@ -537,6 +537,15 @@ public class WindowMagnificationManagerTest { } @Test + public void removeMagnificationSettingsPanel_hasConnection_invokeConnectionMethod() + throws RemoteException { + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + + mWindowMagnificationManager.removeMagnificationSettingsPanel(TEST_DISPLAY); + verify(mMockConnection.getConnection()).removeMagnificationSettingsPanel(TEST_DISPLAY); + } + + @Test public void pointersInWindow_magnifierEnabled_returnCorrectValue() throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); |