diff --git a/res/values/styles.xml b/res/values/styles.xml index b27cc5de530..783a1487d17 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -715,8 +715,8 @@ parent="@*android:style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog"> match_parent 56dp - 8dp - 8dp + 8dp + 8dp ?android:attr/selectableItemBackground diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java index 26c23137729..803550b8cc4 100644 --- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java +++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java @@ -118,16 +118,16 @@ public class AccessibilityEditDialogUtils { * Method to show the magnification edit shortcut dialog in Magnification. * * @param context A valid context - * @param dialogTitle The title of magnify edit shortcut dialog * @param positiveBtnListener The positive button listener * @return A magnification edit shortcut dialog in Magnification */ public static Dialog createMagnificationSwitchShortcutDialog(Context context, - CharSequence dialogTitle, CustomButtonsClickListener positiveBtnListener) { + CustomButtonsClickListener positiveBtnListener) { final View contentView = createSwitchShortcutDialogContentView(context); final AlertDialog alertDialog = new AlertDialog.Builder(context) .setView(contentView) - .setTitle(dialogTitle) + .setTitle(context.getString( + R.string.accessibility_magnification_switch_shortcut_title)) .create(); setCustomButtonsClickListener(alertDialog, contentView, positiveBtnListener, /* negativeBtnListener= */ null); diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java index 67b68ccb93d..ef858345cea 100644 --- a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java @@ -47,6 +47,7 @@ import com.android.settings.accessibility.MagnificationCapabilities.Magnificatio import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnCreate; +import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; import java.util.ArrayList; @@ -55,8 +56,9 @@ import java.util.StringJoiner; /** Controller that shows the magnification area mode summary and the preference click behavior. */ public class MagnificationModePreferenceController extends BasePreferenceController implements - DialogCreatable, LifecycleObserver, OnCreate, OnSaveInstanceState { + DialogCreatable, LifecycleObserver, OnCreate, OnResume, OnSaveInstanceState { + static final String PREF_KEY = "screen_magnification_mode"; private static final int DIALOG_ID_BASE = 10; @VisibleForTesting static final int DIALOG_MAGNIFICATION_MODE = DIALOG_ID_BASE + 1; @@ -68,7 +70,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl private static final String TAG = "MagnificationModePreferenceController"; private static final char COMPONENT_NAME_SEPARATOR = ':'; - private MagnificationSettingsFragment mParentFragment; + private DialogHelper mDialogHelper; // The magnification mode in the dialog. private int mMode = MagnificationMode.NONE; private Preference mModePreference; @@ -121,7 +123,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl mModePreference = screen.findPreference(getPreferenceKey()); mModePreference.setOnPreferenceClickListener(preference -> { mMode = MagnificationCapabilities.getCapabilities(mContext); - mParentFragment.showDialog(DIALOG_MAGNIFICATION_MODE); + mDialogHelper.showDialog(DIALOG_MAGNIFICATION_MODE); return true; }); } @@ -131,8 +133,12 @@ public class MagnificationModePreferenceController extends BasePreferenceControl outState.putInt(EXTRA_MODE, mMode); } - public void setParentFragment(MagnificationSettingsFragment parentFragment) { - mParentFragment = parentFragment; + /** + * Sets {@link DialogHelper} used to show the dialog. + */ + public void setDialogHelper(DialogHelper dialogHelper) { + mDialogHelper = dialogHelper; + mDialogHelper.setDialogDelegate(this); } @Override @@ -207,7 +213,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl } mMode = modeInfo.mMagnificationMode; if (isTripleTapEnabled(mContext) && mMode != MagnificationMode.FULLSCREEN) { - mParentFragment.showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); + mDialogHelper.showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } } @@ -229,9 +235,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl } private Dialog createMagnificationShortCutConfirmDialog() { - final String title = mContext.getString( - R.string.accessibility_magnification_switch_shortcut_title); - return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, title, + return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, this::onSwitchShortcutDialogButtonClicked); } @@ -267,6 +271,21 @@ public class MagnificationModePreferenceController extends BasePreferenceControl joiner.toString()); } + // TODO(b/186731461): Remove it when this controller is used in DashBoardFragment only. + @Override + public void onResume() { + updateState(mModePreference); + } + + + /** + * An interface to help the delegate to show the dialog. It will be injected to the delegate. + */ + interface DialogHelper extends DialogCreatable { + void showDialog(int dialogId); + void setDialogDelegate(DialogCreatable delegate); + } + @VisibleForTesting static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo { @MagnificationMode diff --git a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java index 0af40fdca45..a898076033c 100644 --- a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java +++ b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java @@ -20,6 +20,7 @@ import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.Context; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -27,11 +28,13 @@ import com.android.settingslib.search.SearchIndexable; /** Settings page for magnification. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class MagnificationSettingsFragment extends DashboardFragment { +public class MagnificationSettingsFragment extends DashboardFragment implements + MagnificationModePreferenceController.DialogHelper { private static final String TAG = "MagnificationSettingsFragment"; - private MagnificationModePreferenceController mMagnificationModePreferenceController; + private DialogCreatable mDialogDelegate; + @Override public int getMetricsCategory() { @@ -41,19 +44,23 @@ public class MagnificationSettingsFragment extends DashboardFragment { @Override public void onAttach(Context context) { super.onAttach(context); - mMagnificationModePreferenceController = use(MagnificationModePreferenceController.class); - mMagnificationModePreferenceController.setParentFragment(this); + use(MagnificationModePreferenceController.class).setDialogHelper(this); } @Override - protected void showDialog(int dialogId) { + public void showDialog(int dialogId) { super.showDialog(dialogId); } + @Override + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; + } + @Override public int getDialogMetricsCategory(int dialogId) { - if (mMagnificationModePreferenceController != null) { - return mMagnificationModePreferenceController.getDialogMetricsCategory(dialogId); + if (mDialogDelegate != null) { + return mDialogDelegate.getDialogMetricsCategory(dialogId); } return 0; } @@ -70,8 +77,8 @@ public class MagnificationSettingsFragment extends DashboardFragment { @Override public Dialog onCreateDialog(int dialogId) { - if (mMagnificationModePreferenceController != null) { - final Dialog dialog = mMagnificationModePreferenceController.onCreateDialog(dialogId); + if (mDialogDelegate != null) { + final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId); if (dialog != null) { return dialog; } diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 738d284bda0..7c03ba9e9a8 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -42,6 +42,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; @@ -55,7 +56,8 @@ import java.util.StringJoiner; * and does not have toggle bar to turn on service to use. */ public class ToggleScreenMagnificationPreferenceFragment extends - ToggleFeaturePreferenceFragment { + ToggleFeaturePreferenceFragment implements + MagnificationModePreferenceController.DialogHelper { // TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util. private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; @@ -67,6 +69,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends private static final TextUtils.SimpleStringSplitter sStringColonSplitter = new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); + private MagnificationModePreferenceController mModePreferenceController; + private DialogCreatable mDialogDelegate; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -108,6 +113,12 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override public Dialog onCreateDialog(int dialogId) { + if (mDialogDelegate != null) { + final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId); + if (dialog != null) { + return dialog; + } + } final AlertDialog dialog; switch (dialogId) { case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: @@ -128,20 +139,35 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override protected void initSettingsPreference() { + // If the device doesn't support magnification area, it should hide the settings preference. if (!getContext().getResources().getBoolean( com.android.internal.R.bool.config_magnification_area)) { return; } mSettingsPreference = new Preference(getPrefContext()); - mSettingsPreference.setTitle(R.string.accessibility_menu_item_settings); - // TODO(b/177371954): "magnification area" should be brought up to the highest level of the - // settings UI so that it appears below "shortcut" to replace "settings. - mSettingsPreference.setFragment(MagnificationSettingsFragment.class.getName()); + mSettingsPreference.setTitle(R.string.accessibility_magnification_mode_title); + mSettingsPreference.setKey(MagnificationModePreferenceController.PREF_KEY); mSettingsPreference.setPersistent(false); final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); generalCategory.addPreference(mSettingsPreference); + + mModePreferenceController = new MagnificationModePreferenceController(getContext(), + MagnificationModePreferenceController.PREF_KEY); + mModePreferenceController.setDialogHelper(this); + getSettingsLifecycle().addObserver(mModePreferenceController); + mModePreferenceController.displayPreference(getPreferenceScreen()); + } + + @Override + public void showDialog(int dialogId) { + super.showDialog(dialogId); + } + + @Override + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; } @Override @@ -278,6 +304,13 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override public int getDialogMetricsCategory(int dialogId) { + if (mDialogDelegate != null) { + final int category = mDialogDelegate.getDialogMetricsCategory(dialogId); + if (category != 0) { + return category; + } + } + switch (dialogId) { case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION; diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java index 4b053ab457b..d4b7ea038fe 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java @@ -16,8 +16,6 @@ package com.android.settings.accessibility; -import static androidx.lifecycle.Lifecycle.Event.ON_CREATE; - import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton; import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode; import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo; @@ -25,41 +23,35 @@ import static com.android.settings.accessibility.MagnificationPreferenceFragment import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.provider.Settings; import android.widget.AdapterView; import android.widget.ListView; -import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import com.android.settings.DialogCreatable; import com.android.settings.R; -import com.android.settings.testutils.shadow.ShadowDashboardFragment; -import com.android.settingslib.core.AbstractPreferenceController; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - +/** Tests for {@link MagnificationModePreferenceController}. */ @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowDashboardFragment.class) public class MagnificationModePreferenceControllerTest { private static final String PREF_KEY = "screen_magnification_mode"; private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL; @@ -67,39 +59,38 @@ public class MagnificationModePreferenceControllerTest { @Rule public MockitoRule mocks = MockitoJUnit.rule(); - @Mock private PreferenceScreen mScreen; private Context mContext; - private TestMagnificationSettingsFragment mFragment; private MagnificationModePreferenceController mController; private Preference mModePreference; + @Spy + private TestDialogHelper mDialogHelper = new TestDialogHelper(); @Before public void setUp() { mContext = RuntimeEnvironment.application; - mController = new MagnificationModePreferenceController(mContext, PREF_KEY); - mScreen = spy(new PreferenceScreen(mContext, null)); + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); mModePreference = new Preference(mContext); - mFragment = spy(new TestMagnificationSettingsFragment(mController)); - - doReturn(mScreen).when(mFragment).getPreferenceScreen(); - doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when( - mFragment).getChildFragmentManager(); - mContext.setTheme(R.style.Theme_AppCompat); - doReturn(mModePreference).when(mScreen).findPreference(PREF_KEY); + mModePreference.setKey(PREF_KEY); + mScreen.addPreference(mModePreference); MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT); + mController = new MagnificationModePreferenceController(mContext, PREF_KEY); showPreferenceOnTheScreen(null); - mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); } @Test - public void settingsModeIsDefault_checkedModeInDialogIsDefault() { + public void clickPreference_settingsModeIsDefault_checkedModeInDialogIsDefault() { + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); + assertThat(getCheckedModeFromDialog()).isEqualTo( MAGNIFICATION_MODE_DEFAULT); } @Test public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() { + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); + performItemClickWith(MagnificationMode.WINDOW); assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW); @@ -107,11 +98,11 @@ public class MagnificationModePreferenceControllerTest { @Test public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() { - showPreferenceOnTheScreen(null); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.WINDOW); reshowPreferenceOnTheScreen(); - mFragment.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); + mDialogHelper.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); assertThat(getCheckedModeFromDialog()).isEqualTo( MagnificationMode.WINDOW); @@ -120,24 +111,22 @@ public class MagnificationModePreferenceControllerTest { @Test public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() { enableTripleTap(); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.WINDOW); - verify(mFragment).showDialog( + verify(mDialogHelper).showDialog( MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } @Test public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() { enableTripleTap(); - MagnificationCapabilities.setCapabilities(mContext, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); - mFragment.onCreate(Bundle.EMPTY); - mFragment.onCreateDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.ALL); - verify(mFragment, never()).showDialog( + verify(mDialogHelper, never()).showDialog( MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } @@ -206,48 +195,38 @@ public class MagnificationModePreferenceControllerTest { private void reshowPreferenceOnTheScreen() { final Bundle bundle = new Bundle(); - mFragment.onSaveInstanceState(bundle); - mFragment.onDetach(); + mController.onSaveInstanceState(bundle); showPreferenceOnTheScreen(bundle); - } private void showPreferenceOnTheScreen(Bundle savedInstanceState) { - mFragment.onAttach(mContext); - mFragment.onCreate(savedInstanceState); + mController.setDialogHelper(mDialogHelper); + mController.onCreate(savedInstanceState); mController.displayPreference(mScreen); } - private static class TestMagnificationSettingsFragment extends MagnificationSettingsFragment { - - TestMagnificationSettingsFragment(AbstractPreferenceController... controllers) { - // Add given controllers for injection. Although controllers will be added in - // onAttach(). use(AbstractPreferenceController.class) returns the first added one. - for (int i = 0; i < controllers.length; i++) { - addPreferenceController(controllers[i]); - } - } + private static class TestDialogHelper implements DialogCreatable, + MagnificationModePreferenceController.DialogHelper { + private DialogCreatable mDialogDelegate; @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - // Simulate the observable behaviour because ShadowDashFragment doesn't call - // super.create. - - getSettingsLifecycle().onCreate(icicle); - getSettingsLifecycle().handleLifecycleEvent(ON_CREATE); - } - - @Override - protected void showDialog(int dialogId) { - super.showDialog(dialogId); - // In current fragment architecture, we could assume onCreateDialog is called directly. + public void showDialog(int dialogId) { onCreateDialog(dialogId); } @Override - protected void addPreferenceController(AbstractPreferenceController controller) { - super.addPreferenceController(controller); + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; + } + + @Override + public Dialog onCreateDialog(int dialogId) { + return mDialogDelegate.onCreateDialog(dialogId); + } + + @Override + public int getDialogMetricsCategory(int dialogId) { + return mDialogDelegate.getDialogMetricsCategory(dialogId); } } } diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java index 789362b6de4..73d29cf4ef4 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java @@ -18,23 +18,78 @@ package com.android.settings.accessibility; import static com.google.common.truth.Truth.assertThat; -import android.content.Context; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.content.Context; +import android.os.Bundle; + +import androidx.fragment.app.FragmentManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.testutils.XmlTestUtils; +import com.android.settings.testutils.shadow.ShadowDashboardFragment; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; import java.util.List; /** Tests for {@link MagnificationSettingsFragment} */ @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowDashboardFragment.class) public class MagnificationSettingsFragmentTest { + private final Context mContext = ApplicationProvider.getApplicationContext(); + private MagnificationSettingsFragment mFragment; + private PreferenceScreen mScreen; + + @Before + public void setup() { + mContext.setTheme(R.style.Theme_AppCompat); + mFragment = spy(new MagnificationSettingsFragment()); + mScreen = new PreferenceScreen(mContext, null); + + doReturn(mContext).when(mFragment).getContext(); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); + doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when( + mFragment).getChildFragmentManager(); + + } + + @Test + public void showPreferenceOnTheScreen_setDialogHelper() { + showPreferenceOnTheScreen(null); + + verify(mFragment).setDialogDelegate(any(MagnificationModePreferenceController.class)); + } + + @Test + public void onCreateDialog_setDialogDelegate_invokeDialogDelegate() { + final DialogCreatable dialogDelegate = mock(DialogCreatable.class, RETURNS_DEEP_STUBS); + when(dialogDelegate.getDialogMetricsCategory(anyInt())).thenReturn(1); + + mFragment.setDialogDelegate(dialogDelegate); + + mFragment.onCreateDialog(1); + mFragment.getDialogMetricsCategory(1); + + verify(dialogDelegate).onCreateDialog(1); + verify(dialogDelegate).getDialogMetricsCategory(1); + } @Test public void getNonIndexableKeys_existInXmlLayout() { @@ -46,4 +101,10 @@ public class MagnificationSettingsFragmentTest { R.xml.accessibility_magnification_service_settings); assertThat(keys).containsAtLeastElementsIn(niks); } + + private void showPreferenceOnTheScreen(Bundle savedInstanceState) { + mFragment.onAttach(mContext); + mFragment.onCreate(savedInstanceState); + mFragment.onResume(); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java index 0ed6747e517..c8ad94faecb 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java @@ -23,9 +23,13 @@ import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment 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.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; @@ -34,6 +38,7 @@ import android.content.DialogInterface; import android.content.res.Resources; import android.os.Bundle; import android.provider.Settings; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -41,21 +46,28 @@ import android.view.ViewGroup; import androidx.annotation.XmlRes; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; +import androidx.preference.Preference; import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowFragment; +import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment; +import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSettingsPreferenceFragment.class}) public class ToggleScreenMagnificationPreferenceFragmentTest { private static final String PLACEHOLDER_PACKAGE_NAME = "com.mock.example"; @@ -79,9 +91,6 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { private Context mContext; private Resources mResources; - @Mock - private PreferenceManager mPreferenceManager; - @Mock private FragmentActivity mActivity; @Before @@ -89,14 +98,11 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment()); - when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); - when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); - when(mFragment.getContext()).thenReturn(mContext); + mActivity = Robolectric.setupActivity(FragmentActivity.class); + mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment(mContext)); mResources = spy(mContext.getResources()); when(mContext.getResources()).thenReturn(mResources); when(mFragment.getContext().getResources()).thenReturn(mResources); - doReturn(null).when(mFragment).getPreferenceScreen(); doReturn(mActivity).when(mFragment).getActivity(); } @@ -257,15 +263,38 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { } @Test - public void initSettingsPreference_notSupportsMagnificationArea_settingsPreferenceIsNull() { + public void onCreateView_notSupportsMagnificationArea_settingsPreferenceIsNull() { when(mResources.getBoolean( com.android.internal.R.bool.config_magnification_area)) .thenReturn(false); - mFragment.initSettingsPreference(); + + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); assertThat(mFragment.mSettingsPreference).isNull(); } + @Test + public void onCreateView_setDialogDelegateAndAddTheControllerToLifeCycleObserver() { + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); + + verify(mFragment).setDialogDelegate(any(MagnificationModePreferenceController.class)); + verify(mFragment.mSpyLifeyCycle).addObserver( + any(MagnificationModePreferenceController.class)); + } + + @Test + public void onCreateDialog_setDialogDelegate_invokeDialogDelegate() { + final DialogCreatable dialogDelegate = mock(DialogCreatable.class, RETURNS_DEEP_STUBS); + when(dialogDelegate.getDialogMetricsCategory(anyInt())).thenReturn(1); + mFragment.setDialogDelegate(dialogDelegate); + + mFragment.onCreateDialog(1); + mFragment.getDialogMetricsCategory(1); + + verify(dialogDelegate).onCreateDialog(1); + verify(dialogDelegate).getDialogMetricsCategory(1); + } + private void putStringIntoSettings(String key, String componentName) { Settings.Secure.putString(mContext.getContentResolver(), key, componentName); } @@ -291,8 +320,25 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { private void callEmptyOnClicked(DialogInterface dialog, int which) {} - public static class TestToggleScreenMagnificationPreferenceFragment + /** + * a test fragment that initializes PreferenceScreen for testing. + */ + static class TestToggleScreenMagnificationPreferenceFragment extends ToggleScreenMagnificationPreferenceFragment { + + private final Lifecycle mSpyLifeyCycle = Mockito.mock(Lifecycle.class); + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestToggleScreenMagnificationPreferenceFragment(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + setArguments(new Bundle()); + } + @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { } @@ -313,9 +359,21 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return mock(View.class); + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public T findPreference(CharSequence key) { + if (TextUtils.isEmpty(key)) { + return null; + } + return getPreferenceScreen().findPreference(key); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; } @Override @@ -337,5 +395,15 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { protected void updateShortcutPreference() { // UI related function, do nothing in tests } + + @Override + public Lifecycle getSettingsLifecycle() { + return mSpyLifeyCycle; + } + + @Override + public Context getContext() { + return mContext; + } } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java new file mode 100644 index 00000000000..27fca621930 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java @@ -0,0 +1,43 @@ +/* + * 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.settings.testutils.shadow; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.android.settings.SettingsPreferenceFragment; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +/** + * Shadow of {@link SettingsPreferenceFragment}. + * + * Override the {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}} to skip inflating + * a View from a xml. + */ +@Implements(SettingsPreferenceFragment.class) +public class ShadowSettingsPreferenceFragment extends ShadowFragment { + + @Implementation + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return container; + } +}