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

Commit bf0ab716 authored by jasonwshsu's avatar jasonwshsu
Browse files

Handle the phone get booted case to show accessibility floating menu

* AccessibilityManager might not ready when the phone just got booted.

Bug: 173940864
Test: atest AccessibilityFloatingMenuControllerTest
Change-Id: I0339597cd53ca5daade427fef257bfddb3b86bd8
parent 523514fd
Loading
Loading
Loading
Loading
+30 −2
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATIN


import android.content.Context;
import android.content.Context;
import android.text.TextUtils;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityManager;


import androidx.annotation.MainThread;
import androidx.annotation.MainThread;


@@ -36,9 +37,11 @@ import javax.inject.Inject;
@SysUISingleton
@SysUISingleton
public class AccessibilityFloatingMenuController implements
public class AccessibilityFloatingMenuController implements
        AccessibilityButtonModeObserver.ModeChangedListener,
        AccessibilityButtonModeObserver.ModeChangedListener,
        AccessibilityButtonTargetsObserver.TargetsChangedListener {
        AccessibilityButtonTargetsObserver.TargetsChangedListener,
        AccessibilityManager.AccessibilityStateChangeListener {


    private final Context mContext;
    private final Context mContext;
    private final AccessibilityManager mAccessibilityManager;
    private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
    private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
    private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
    private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;


@@ -54,13 +57,21 @@ public class AccessibilityFloatingMenuController implements
        mContext = context;
        mContext = context;
        mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
        mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
        mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
        mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);


        mAccessibilityButtonModeObserver.addListener(this);
        mAccessibilityButtonModeObserver.addListener(this);
        mAccessibilityButtonTargetsObserver.addListener(this);
        mAccessibilityButtonTargetsObserver.addListener(this);
        mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
        mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
        mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
        mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();


        // Accessibility floating menu widget needs accessibility service to work, but system
        // accessibility might be unavailable during the phone get booted, hence it needs to wait
        // for accessibility manager callback to work.
        mAccessibilityManager.addAccessibilityStateChangeListener(this);
        if (mAccessibilityManager.isEnabled()) {
            handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
            handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
            mAccessibilityManager.removeAccessibilityStateChangeListener(this);
        }
    }
    }


    /**
    /**
@@ -86,6 +97,23 @@ public class AccessibilityFloatingMenuController implements
        handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
        handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
    }
    }


    /**
     * Handles visibility of the accessibility floating menu when system accessibility state
     * changes.
     * If system accessibility become available onAccessibilityStateChanged(true), then we don't
     * need to listen to this listener anymore.
     *
     * @param enabled Whether accessibility is enabled.
     */
    @Override
    public void onAccessibilityStateChanged(boolean enabled) {
        if (enabled) {
            handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
        }

        mAccessibilityManager.removeAccessibilityStateChangeListener(this);
    }

    private void handleFloatingMenuVisibility(@AccessibilityButtonMode int mode, String targets) {
    private void handleFloatingMenuVisibility(@AccessibilityButtonMode int mode, String targets) {
        if (shouldShowFloatingMenu(mode, targets)) {
        if (shouldShowFloatingMenu(mode, targets)) {
            showFloatingMenu();
            showFloatingMenu();
+45 −1
Original line number Original line Diff line number Diff line
@@ -24,10 +24,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.provider.Settings;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper;
import android.view.accessibility.AccessibilityManager;


import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


@@ -36,8 +38,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;


import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;


/** Test for {@link AccessibilityFloatingMenuController}. */
/** Test for {@link AccessibilityFloatingMenuController}. */
@RunWith(AndroidTestingRunner.class)
@RunWith(AndroidTestingRunner.class)
@@ -47,9 +53,14 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {


    private static final String TEST_A11Y_BTN_TARGETS = "Magnification";
    private static final String TEST_A11Y_BTN_TARGETS = "Magnification";


    @Rule
    public MockitoRule mockito = MockitoJUnit.rule();

    private AccessibilityFloatingMenuController mController;
    private AccessibilityFloatingMenuController mController;
    private AccessibilityButtonTargetsObserver mTargetsObserver;
    private AccessibilityButtonTargetsObserver mTargetsObserver;
    private AccessibilityButtonModeObserver mModeObserver;
    private AccessibilityButtonModeObserver mModeObserver;
    @Mock
    private AccessibilityManager mMockA11yManager;


    @Test
    @Test
    public void initController_registerListeners() {
    public void initController_registerListeners() {
@@ -59,6 +70,37 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
                any(AccessibilityButtonTargetsObserver.TargetsChangedListener.class));
                any(AccessibilityButtonTargetsObserver.TargetsChangedListener.class));
        verify(mModeObserver).addListener(
        verify(mModeObserver).addListener(
                any(AccessibilityButtonModeObserver.ModeChangedListener.class));
                any(AccessibilityButtonModeObserver.ModeChangedListener.class));
        verify(mMockA11yManager).addAccessibilityStateChangeListener(any(
                AccessibilityManager.AccessibilityStateChangeListener.class));
    }

    @Test
    public void initController_accessibilityManagerEnabled_showWidget() {
        Settings.Secure.putInt(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
        Settings.Secure.putString(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS);
        when(mMockA11yManager.isEnabled()).thenReturn(true);

        mController = setUpController();

        assertThat(mController.mFloatingMenu).isNotNull();
        verify(mMockA11yManager).removeAccessibilityStateChangeListener(mController);
    }

    @Test
    public void initController_accessibilityManagerDisabledThenCallbackToEnabled_showWidget() {
        Settings.Secure.putInt(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
        Settings.Secure.putString(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS);
        when(mMockA11yManager.isEnabled()).thenReturn(false);

        mController = setUpController();
        mController.onAccessibilityStateChanged(true);

        assertThat(mController.mFloatingMenu).isNotNull();
        verify(mMockA11yManager).removeAccessibilityStateChangeListener(mController);
    }
    }


    @Test
    @Test
@@ -154,7 +196,9 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
    private AccessibilityFloatingMenuController setUpController() {
    private AccessibilityFloatingMenuController setUpController() {
        mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class));
        mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class));
        mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class));
        mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class));
        mContext.addMockSystemService(AccessibilityManager.class, mMockA11yManager);


        return new AccessibilityFloatingMenuController(mContext, mTargetsObserver, mModeObserver);
        return new AccessibilityFloatingMenuController(mContext, mTargetsObserver,
                mModeObserver);
    }
    }
}
}