refactor(A11yFeedback): Simply feedback logic into menu controller

Bug: 393980229
Test: atest FeedbackMenuControllerTest
Flag: com.android.server.accessibility.enable_low_vision_generic_feedback
Change-Id: I03af00957c2bcca1d1cc81970eccad6dd69bb4ac
This commit is contained in:
Menghan Li
2025-03-07 03:54:35 +00:00
parent 9066ecf68a
commit a389ff59ab
7 changed files with 276 additions and 218 deletions

View File

@@ -21,10 +21,7 @@ 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.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;
@@ -46,8 +43,6 @@ 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;
@@ -112,7 +107,6 @@ public class AccessibilitySettingsTest {
private static final String EMPTY_STRING = "";
private static final String DEFAULT_SUMMARY = "default summary";
private static final String DEFAULT_DESCRIPTION = "default description";
private static final String DEFAULT_CATEGORY = "default category";
private static final String DEFAULT_LABEL = "default label";
private static final Boolean SERVICE_ENABLED = true;
private static final Boolean SERVICE_DISABLED = false;
@@ -128,10 +122,6 @@ public class AccessibilitySettingsTest {
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private Menu mMenu;
@Mock
private MenuItem mMenuItem;
private ActivityController<SettingsActivity> mActivityController;
@@ -451,58 +441,6 @@ 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, DEFAULT_CATEGORY));
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu).add(anyInt(), anyInt(), anyInt(), anyInt());
}
@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, DEFAULT_CATEGORY));
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu, never()).add(anyInt(), anyInt(), anyInt(), anyInt());
}
@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, DEFAULT_CATEGORY));
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, DEFAULT_CATEGORY));
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(

View File

@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
@@ -82,6 +83,8 @@ public class ToggleColorInversionPreferenceFragmentTest {
private PreferenceManager mPreferenceManager;
@Mock
private FragmentActivity mActivity;
@Mock
private Resources mResources;
@Before
public void setUpTestFragment() {
@@ -93,6 +96,7 @@ public class ToggleColorInversionPreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(mContext);
when(mFragment.getActivity()).thenReturn(mActivity);
when(mActivity.getContentResolver()).thenReturn(mContext.getContentResolver());
when(mActivity.getResources()).thenReturn(mResources);
mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null));
when(mScreen.findPreference(mFragment.getUseServicePreferenceKey()))

View File

@@ -23,8 +23,6 @@ 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.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -38,16 +36,14 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.icu.text.CaseMap;
import android.net.Uri;
import android.os.Bundle;
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.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
@@ -107,19 +103,10 @@ public class ToggleFeaturePreferenceFragmentTest {
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
private static final String PLACEHOLDER_CATEGORY = "category";
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
private static final String DEFAULT_SUMMARY = "default summary";
private static final String DEFAULT_DESCRIPTION = "default description";
private static final String DEFAULT_TOP_INTRO = "default top intro";
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private TestToggleFeaturePreferenceFragment mFragment;
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@@ -135,9 +122,7 @@ public class ToggleFeaturePreferenceFragmentTest {
@Mock
private PackageManager mPackageManager;
@Mock
private Menu mMenu;
@Mock
private MenuItem mMenuItem;
private Resources mResources;
@Before
public void setUpTestFragment() {
@@ -150,6 +135,7 @@ public class ToggleFeaturePreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(mContext);
when(mFragment.getActivity()).thenReturn(mActivity);
when(mActivity.getContentResolver()).thenReturn(mContentResolver);
when(mActivity.getResources()).thenReturn(mResources);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
final PreferenceScreen screen = spy(new PreferenceScreen(mContext, null));
when(screen.getPreferenceManager()).thenReturn(mPreferenceManager);
@@ -186,61 +172,6 @@ public class ToggleFeaturePreferenceFragmentTest {
any(AccessibilitySettingsContentObserver.class));
}
@Test
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onCreateOptionsMenu_enableLowVisionGenericFeedback_shouldAddSendFeedbackMenu() {
mFragment.setFeedbackManager(
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu).add(anyInt(), eq(ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK),
anyInt(), eq(R.string.accessibility_send_feedback_title));
}
@Test
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onCreateOptionsMenu_disableLowVisionGenericFeedback_shouldNotAddSendFeedbackMenu() {
mFragment.setFeedbackManager(
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu, never()).add(anyInt(),
eq(ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK), anyInt(),
eq(R.string.accessibility_send_feedback_title));
}
@Test
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onOptionsItemSelected_enableLowVisionGenericFeedback_shouldStartSendFeedback() {
mFragment.setFeedbackManager(
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
when(mMenuItem.getItemId()).thenReturn(
ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK);
mFragment.onOptionsItemSelected(mMenuItem);
verify(mActivity).startActivityForResult(
argThat(intent -> intent != null
&& Intent.ACTION_BUG_REPORT.equals(intent.getAction())), anyInt());
}
@Test
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onOptionsItemSelected_disableLowVisionGenericFeedback_shouldNotStartSendFeedback() {
mFragment.setFeedbackManager(
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
when(mMenuItem.getItemId()).thenReturn(
ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK);
mFragment.onOptionsItemSelected(mMenuItem);
verify(mActivity, never()).startActivityForResult(
argThat(intent -> intent != null
&& Intent.ACTION_BUG_REPORT.equals(intent.getAction())), anyInt());
}
@Test
public void updateShortcutPreferenceData_assignDefaultValueToVariable() {
mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2025 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.settings.accessibility.actionbar;
import static com.android.settings.accessibility.actionbar.FeedbackMenuController.MENU_FEEDBACK;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.Menu;
import android.view.MenuItem;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.testing.EmptyFragmentActivity;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import com.android.settings.accessibility.FeedbackManager;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
/** Tests for {@link FeedbackMenuController} */
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
@RunWith(RobolectricTestRunner.class)
public class FeedbackMenuControllerTest {
private static final String PACKAGE_NAME = "com.android.test";
private static final String DEFAULT_CATEGORY = "default category";
@Rule
public final MockitoRule mMocks = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public ActivityScenarioRule<EmptyFragmentActivity> mActivityScenario =
new ActivityScenarioRule<>(EmptyFragmentActivity.class);
private FragmentActivity mActivity;
private InstrumentedPreferenceFragment mHost;
private FeedbackManager mFeedbackManager;
@Mock
private Lifecycle mLifecycle;
@Mock
private Menu mMenu;
@Mock
private MenuItem mMenuItem;
@Before
public void setUp() {
mActivityScenario.getScenario().onActivity(activity -> mActivity = activity);
mHost = spy(new InstrumentedPreferenceFragment() {
@Override
public int getMetricsCategory() {
return 0;
}
});
when(mHost.getActivity()).thenReturn(mActivity);
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
when(mMenuItem.getItemId()).thenReturn(MENU_FEEDBACK);
mFeedbackManager = new FeedbackManager(mActivity, PACKAGE_NAME, DEFAULT_CATEGORY);
}
@Test
public void init_withPageId_shouldAttachToLifecycle() {
when(mHost.getSettingsLifecycle()).thenReturn(mLifecycle);
FeedbackMenuController.init(mHost, SettingsEnums.ACCESSIBILITY);
verify(mLifecycle).addObserver(any(FeedbackMenuController.class));
}
@Test
public void init_withFeedbackManager_shouldAttachToLifecycle() {
when(mHost.getSettingsLifecycle()).thenReturn(mLifecycle);
FeedbackMenuController.init(mHost, mFeedbackManager);
verify(mLifecycle).addObserver(any(FeedbackMenuController.class));
}
@Test
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onCreateOptionsMenu_enableLowVisionGenericFeedback_shouldAddSendFeedbackMenu() {
FeedbackMenuController.init(mHost, mFeedbackManager);
mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu).add(anyInt(), anyInt(), anyInt(), anyInt());
}
@Test
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onCreateOptionsMenu_disableLowVisionGenericFeedback_shouldNotAddSendFeedbackMenu() {
FeedbackMenuController.init(mHost, mFeedbackManager);
mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, /* inflater= */ null);
verify(mMenu, never()).add(anyInt(), anyInt(), anyInt(), anyInt());
}
@Test
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onOptionsItemSelected_enableLowVisionGenericFeedback_shouldStartSendFeedback() {
FeedbackMenuController.init(mHost, mFeedbackManager);
mHost.getSettingsLifecycle().onOptionsItemSelected(mMenuItem);
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_BUG_REPORT);
}
@Test
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
public void onOptionsItemSelected_disableLowVisionGenericFeedback_shouldNotStartSendFeedback() {
FeedbackMenuController.init(mHost, mFeedbackManager);
mHost.getSettingsLifecycle().onOptionsItemSelected(mMenuItem);
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent).isNull();
}
}