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

Commit c86e2f34 authored by Menghan Li's avatar Menghan Li
Browse files

feat(A11yFeedback): Add feedback entry for Accessibility page

This entry point allows users to access in the action bar.
Visibility is controlled by the aconfig and FeedbackManager#isAvailable

Bug: 393981463
Test: atest AccessibilitySettingsTest
Flag: com.android.server.accessibility.enable_low_vision_generic_feedback
Change-Id: I8c219b8220b5839121d14959fe526e6200afeecb
parent 267251aa
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -5157,6 +5157,8 @@
    <string name="accessibility_feedback_summary">Help improve by taking a survey</string>
    <!-- Summary for the accessibility feedback preference is disabled. [CHAR LIMIT=100] -->
    <string name="accessibility_feedback_disabled_summary">No surveys available</string>
    <!-- The menu item to start the feedback process for the accessibility [CHAR LIMIT=30] -->
    <string name="accessibility_send_feedback_title">Send feedback</string>
    <!-- Title for the accessibility preference category of services downloaded by the user. [CHAR LIMIT=50] -->
    <string name="user_installed_services_category_title">Downloaded apps</string>
    <!-- Title for the accessibility preference category of settings considered to be experimental, meaning they might be changed or removed in the future. [CHAR LIMIT=50] -->
+38 −2
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.accessibility.AccessibilityManager;

import androidx.annotation.NonNull;
@@ -101,6 +104,8 @@ public class AccessibilitySettings extends DashboardFragment implements
    // presentation.
    private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;

    static final int MENU_ID_SEND_FEEDBACK = 0;

    private final Handler mHandler = new Handler();

    private final Runnable mUpdateRunnable = new Runnable() {
@@ -143,8 +148,9 @@ public class AccessibilitySettings extends DashboardFragment implements
        }
    };

    @VisibleForTesting
    AccessibilitySettingsContentObserver mSettingsContentObserver;
    private AccessibilitySettingsContentObserver mSettingsContentObserver;

    private FeedbackManager mFeedbackManager;

    private final Map<String, PreferenceCategory> mCategoryToPrefCategoryMap =
            new ArrayMap<>();
@@ -245,6 +251,24 @@ public class AccessibilitySettings extends DashboardFragment implements
        super.onDestroy();
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        if (getFeedbackManager().isAvailable()) {
            menu.add(Menu.NONE, MENU_ID_SEND_FEEDBACK, Menu.NONE,
                    getPrefContext().getText(R.string.accessibility_send_feedback_title));
        }
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == MENU_ID_SEND_FEEDBACK) {
            getFeedbackManager().sendFeedback();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.accessibility_settings;
@@ -255,6 +279,18 @@ public class AccessibilitySettings extends DashboardFragment implements
        return TAG;
    }

    @VisibleForTesting
    void setFeedbackManager(FeedbackManager feedbackManager) {
        this.mFeedbackManager = feedbackManager;
    }

    private FeedbackManager getFeedbackManager() {
        if (mFeedbackManager == null) {
            mFeedbackManager = new FeedbackManager(getActivity());
        }
        return mFeedbackManager;
    }

    /**
     * Returns the summary for the current state of this accessibilityService.
     *
+70 −1
Original line number Diff line number Diff line
@@ -21,7 +21,11 @@ import static com.android.internal.accessibility.common.ShortcutConstants.UserSh
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

@@ -43,6 +47,8 @@ import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
import android.view.accessibility.AccessibilityManager;

import androidx.fragment.app.Fragment;
@@ -113,7 +119,8 @@ public class AccessibilitySettingsTest {

    @Rule
    public final MockitoRule mocks = MockitoJUnit.rule();
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    private final Context mContext = ApplicationProvider.getApplicationContext();
    @Spy
    private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
@@ -121,7 +128,13 @@ public class AccessibilitySettingsTest {
    private ShadowAccessibilityManager mShadowAccessibilityManager;
    @Mock
    private LocalBluetoothManager mLocalBluetoothManager;
    @Mock
    private Menu mMenu;
    @Mock
    private MenuItem mMenuItem;

    private ActivityController<SettingsActivity> mActivityController;

    private AccessibilitySettings mFragment;

    @Before
@@ -438,6 +451,62 @@ public class AccessibilitySettingsTest {

    }

    @Test
    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
    public void onCreateOptionsMenu_enableLowVisionGenericFeedback_shouldAddSendFeedbackMenu() {
        setupFragment();
        mFragment.setFeedbackManager(new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME));
        when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);

        mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);

        verify(mMenu).add(anyInt(), eq(AccessibilitySettings.MENU_ID_SEND_FEEDBACK),
                anyInt(), eq(mContext.getText(R.string.accessibility_send_feedback_title)));
    }

    @Test
    @DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
    public void onCreateOptionsMenu_disableLowVisionGenericFeedback_shouldNotAddSendFeedbackMenu() {
        setupFragment();
        mFragment.setFeedbackManager(new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME));
        when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);

        mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);

        verify(mMenu, never()).add(anyInt(), eq(AccessibilitySettings.MENU_ID_SEND_FEEDBACK),
                anyInt(), eq(mContext.getText(R.string.accessibility_send_feedback_title)));
    }

    @Test
    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
    public void onOptionsItemSelected_enableLowVisionGenericFeedback_shouldStartSendFeedback() {
        setupFragment();
        mFragment.setFeedbackManager(new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME));
        when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
        mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
        when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);

        mFragment.onOptionsItemSelected(mMenuItem);

        Intent startedIntent = shadowOf(mFragment.getActivity()).getNextStartedActivity();
        assertThat(startedIntent).isNotNull();
    }

    @Test
    @DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
    public void onOptionsItemSelected_disableLowVisionGenericFeedback_shouldNotStartSendFeedback() {
        setupFragment();
        mFragment.setFeedbackManager(new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME));
        when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
        mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
        when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);

        mFragment.onOptionsItemSelected(mMenuItem);

        Intent startedIntent = shadowOf(mFragment.getActivity()).getNextStartedActivity();
        assertThat(startedIntent).isNull();
    }

    @Test
    public void testAccessibilityMenuInSystem_IncludedInInteractionControl() {
        mShadowAccessibilityManager.setInstalledAccessibilityServiceList(