Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c16a826d authored by Jason Chang's avatar Jason Chang Committed by Android (Google) Code Review
Browse files

Merge "Fix Talk back announces "Exit one handed mode" on every orientation...

Merge "Fix Talk back announces "Exit one handed mode" on every orientation change though one-handed mode is off" into sc-dev
parents 0e8b4aef 327e463a
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.wm.shell.onehanded;

import android.content.Context;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;

import androidx.annotation.NonNull;

import com.android.wm.shell.R;

import java.io.PrintWriter;

/**
 * The util for handling A11y events.
 */
public final class OneHandedAccessibilityUtil {
    private static final String TAG = "OneHandedAccessibilityUtil";

    private final AccessibilityManager mAccessibilityManager;
    private final String mStartOneHandedDescription;
    private final String mStopOneHandedDescription;
    private final String mPackageName;

    private String mDescription;

    public OneHandedAccessibilityUtil(Context context) {
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mPackageName = context.getPackageName();
        mStartOneHandedDescription = context.getResources().getString(
                R.string.accessibility_action_start_one_handed);
        mStopOneHandedDescription = context.getResources().getString(
                R.string.accessibility_action_stop_one_handed);
    }

    /**
     * Gets One-Handed start description.
     * @return text of start description.
     */
    public String getOneHandedStartDescription() {
        return mStartOneHandedDescription;
    }

    /**
     * Gets One-Handed stop description.
     * @return text of stop description.
     */
    public String getOneHandedStopDescription() {
        return mStopOneHandedDescription;
    }

    /**
     * Announcement of A11y Events
     * @param description for accessibility announcement text
     */
    public void announcementForScreenReader(String description) {
        if (!mAccessibilityManager.isTouchExplorationEnabled()) {
            return;
        }
        mDescription = description;
        final AccessibilityEvent event = AccessibilityEvent.obtain();
        event.setPackageName(mPackageName);
        event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
        event.getText().add(mDescription);
        mAccessibilityManager.sendAccessibilityEvent(event);
    }

    public void dump(@NonNull PrintWriter pw) {
        final String innerPrefix = "  ";
        pw.println(TAG + "States: ");
        pw.print(innerPrefix + "mPackageName=");
        pw.println(mPackageName);
        pw.print(innerPrefix + "mDescription=");
        pw.println(mDescription);
    }
}
+19 −4
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
    private final AccessibilityManager mAccessibilityManager;
    private final DisplayController mDisplayController;
    private final OneHandedSettingsUtil mOneHandedSettingsUtil;
    private final OneHandedAccessibilityUtil mOneHandedAccessibilityUtil;
    private final OneHandedTimeoutHandler mTimeoutHandler;
    private final OneHandedTouchHandler mTouchHandler;
    private final OneHandedTutorialHandler mTutorialHandler;
@@ -193,6 +194,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
            return null;
        }

        OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
        OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context);
        OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
        OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context,
                windowManager, mainExecutor);
@@ -205,16 +208,16 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
        OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
                new OneHandedBackgroundPanelOrganizer(context, displayLayout, mainExecutor);
        OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
                context, displayLayout, animationController, tutorialHandler,
                context, displayLayout, settingsUtil, animationController, tutorialHandler,
                oneHandedBackgroundPanelOrganizer, mainExecutor);
        OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
        OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
        IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        return new OneHandedController(context, displayController,
                oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
                gestureHandler, settingsUtil, timeoutHandler, oneHandedUiEventsLogger,
                overlayManager, taskStackListener, mainExecutor, mainHandler);
                gestureHandler, settingsUtil, accessibilityUtil, timeoutHandler,
                oneHandedUiEventsLogger, overlayManager, taskStackListener, mainExecutor,
                mainHandler);
    }

    @VisibleForTesting
@@ -226,6 +229,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
            OneHandedTutorialHandler tutorialHandler,
            OneHandedGestureHandler gestureHandler,
            OneHandedSettingsUtil settingsUtil,
            OneHandedAccessibilityUtil oneHandedAccessibilityUtil,
            OneHandedTimeoutHandler timeoutHandler,
            OneHandedUiEventLogger uiEventsLogger,
            IOverlayManager overlayManager,
@@ -234,6 +238,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
            Handler mainHandler) {
        mContext = context;
        mOneHandedSettingsUtil = settingsUtil;
        mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
        mBackgroundPanelOrganizer = backgroundPanelOrganizer;
        mDisplayAreaOrganizer = displayAreaOrganizer;
        mDisplayController = displayController;
@@ -334,6 +339,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
        if (!mDisplayAreaOrganizer.isInOneHanded()) {
            final int yOffSet = Math.round(
                    mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
            mOneHandedAccessibilityUtil.announcementForScreenReader(
                    mOneHandedAccessibilityUtil.getOneHandedStartDescription());
            mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
            mTimeoutHandler.resetTimer();

@@ -345,6 +352,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
    @VisibleForTesting
    void stopOneHanded() {
        if (mDisplayAreaOrganizer.isInOneHanded()) {
            mOneHandedAccessibilityUtil.announcementForScreenReader(
                    mOneHandedAccessibilityUtil.getOneHandedStopDescription());
            mDisplayAreaOrganizer.scheduleOffset(0, 0);
            mTimeoutHandler.removeTimer();
        }
@@ -352,6 +361,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>

    private void stopOneHanded(int uiEvent) {
        if (mDisplayAreaOrganizer.isInOneHanded()) {
            mOneHandedAccessibilityUtil.announcementForScreenReader(
                    mOneHandedAccessibilityUtil.getOneHandedStopDescription());
            mDisplayAreaOrganizer.scheduleOffset(0, 0);
            mTimeoutHandler.removeTimer();
            mOneHandedUiEventLogger.writeEvent(uiEvent);
@@ -629,6 +640,10 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
            mTutorialHandler.dump(pw);
        }

        if (mOneHandedAccessibilityUtil != null) {
            mOneHandedAccessibilityUtil.dump(pw);
        }

        mOneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver(), mUserId);

        if (mOverlayManager != null) {
+10 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.onehanded;

import static android.os.UserHandle.myUserId;

import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;

@@ -61,6 +63,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {

    private final Rect mLastVisualDisplayBounds = new Rect();
    private final Rect mDefaultDisplayBounds = new Rect();
    private final OneHandedSettingsUtil mOneHandedSettingsUtil;

    private boolean mIsInOneHanded;
    private int mEnterExitAnimationDurationMs;
@@ -109,12 +112,14 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
     */
    public OneHandedDisplayAreaOrganizer(Context context,
            DisplayLayout displayLayout,
            OneHandedSettingsUtil oneHandedSettingsUtil,
            OneHandedAnimationController animationController,
            OneHandedTutorialHandler tutorialHandler,
            OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
            ShellExecutor mainExecutor) {
        super(mainExecutor);
        mDisplayLayout.set(displayLayout);
        mOneHandedSettingsUtil = oneHandedSettingsUtil;
        updateDisplayBounds();
        mAnimationController = animationController;
        final int animationDurationConfig = context.getResources().getInteger(
@@ -168,6 +173,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
        if (mDisplayLayout.rotation() == toRotation) {
            return;
        }

        if (!mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled(context.getContentResolver(),
                myUserId())) {
            return;
        }
        mDisplayLayout.rotateTo(context.getResources(), toRotation);
        resetWindowsOffset(wct);
        updateDisplayBounds();
+0 −23
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
@@ -51,7 +49,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
            "persist.debug.one_handed_offset_percentage";
    private static final int MAX_TUTORIAL_SHOW_COUNT = 2;
    private final WindowManager mWindowManager;
    private final AccessibilityManager mAccessibilityManager;
    private final String mPackageName;
    private final Rect mDisplaySize;

@@ -59,8 +56,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
    private View mTutorialView;
    private ContentResolver mContentResolver;
    private boolean mCanShowTutorial;
    private String mStartOneHandedDescription;
    private String mStopOneHandedDescription;
    private boolean mIsOneHandedMode;

    private enum ONE_HANDED_TRIGGER_STATE {
@@ -106,11 +101,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
        mDisplaySize = windowManager.getCurrentWindowMetrics().getBounds();
        mPackageName = context.getPackageName();
        mContentResolver = context.getContentResolver();
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mStartOneHandedDescription = context.getResources().getString(
                R.string.accessibility_action_start_one_handed);
        mStopOneHandedDescription = context.getResources().getString(
                R.string.accessibility_action_stop_one_handed);
        mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
                Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
                ? false : true;
@@ -131,14 +121,12 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
    public void onStartFinished(Rect bounds) {
        updateFinished(View.VISIBLE, 0f);
        updateTutorialCount();
        announcementForScreenReader(true);
        mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
    }

    @Override
    public void onStopFinished(Rect bounds) {
        updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
        announcementForScreenReader(false);
        removeTutorialFromWindowManager();
        mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
    }
@@ -170,17 +158,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
                Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, showCount);
    }

    private void announcementForScreenReader(boolean isStartOneHanded) {
        if (mAccessibilityManager.isTouchExplorationEnabled()) {
            final AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setPackageName(mPackageName);
            event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
            event.getText().add(isStartOneHanded
                    ? mStartOneHandedDescription : mStopOneHandedDescription);
            mAccessibilityManager.sendAccessibilityEvent(event);
        }
    }

    /**
     * Adds the tutorial target view to the WindowManager and update its layout, so it's ready
     * to be animated in.
+5 −2
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {

    Display mDisplay;
    DisplayLayout mDisplayLayout;
    OneHandedAccessibilityUtil mOneHandedAccessibilityUtil;
    OneHandedController mSpiedOneHandedController;
    OneHandedTimeoutHandler mSpiedTimeoutHandler;

@@ -116,6 +117,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
                new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height()));
        when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(mDisplayLayout);

        mOneHandedAccessibilityUtil = new OneHandedAccessibilityUtil(mContext);
        mSpiedOneHandedController = spy(new OneHandedController(
                mContext,
                mMockDisplayController,
@@ -125,6 +127,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
                mMockTutorialHandler,
                mMockGestureHandler,
                mMockSettingsUitl,
                mOneHandedAccessibilityUtil,
                mSpiedTimeoutHandler,
                mMockUiEventLogger,
                mMockOverlayManager,
@@ -139,8 +142,8 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        final OneHandedAnimationController animationController = new OneHandedAnimationController(
                mContext);
        OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
                mContext, mDisplayLayout, animationController, mMockTutorialHandler,
                mMockBackgroundOrganizer, mMockShellMainExecutor);
                mContext, mDisplayLayout, mMockSettingsUitl, animationController,
                mMockTutorialHandler, mMockBackgroundOrganizer, mMockShellMainExecutor);

        assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
    }
Loading