diff --git a/res/values/strings.xml b/res/values/strings.xml
index 39e0dbdf4e8..c6ed89a22f9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5157,6 +5157,8 @@
Help improve by taking a survey
No surveys available
+
+ Send feedback
Downloaded apps
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index c0341cc5949..57eb4d5fba4 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -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 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.
*
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 91d7d91c833..13168658055 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -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 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(