Move Magnification Mode Settings to the main page

We move the mode settings because currently there is
only one item in the settings page. To fully test all logic,
we don't use fragament anymore in the controllerTest, and
test the interaction between the controller and the fragment
in the test of these two fragments.

Bug: 182992338
Test: atest ToggleScreenMagnificationPreferenceFragmentTest
      atest MagnificationModePreferenceControllerTest
      atest MagnificationSettingsFragmentTest
      manually test
Change-Id: Ia6b0ea4f116f3215407637d7aeaddb8d8196d8fb
This commit is contained in:
ryanlwlin
2021-04-27 20:03:21 +08:00
parent 95b5d0393d
commit 6269a92e16
9 changed files with 317 additions and 107 deletions

View File

@@ -715,8 +715,8 @@
parent="@*android:style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog"> parent="@*android:style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog">
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">56dp</item> <item name="android:layout_height">56dp</item>
<item name="android:paddingLeft">8dp</item> <item name="android:paddingEnd">8dp</item>
<item name="android:paddingRight">8dp</item> <item name="android:paddingStart">8dp</item>
<item name="android:background">?android:attr/selectableItemBackground</item> <item name="android:background">?android:attr/selectableItemBackground</item>
</style> </style>

View File

@@ -118,16 +118,16 @@ public class AccessibilityEditDialogUtils {
* Method to show the magnification edit shortcut dialog in Magnification. * Method to show the magnification edit shortcut dialog in Magnification.
* *
* @param context A valid context * @param context A valid context
* @param dialogTitle The title of magnify edit shortcut dialog
* @param positiveBtnListener The positive button listener * @param positiveBtnListener The positive button listener
* @return A magnification edit shortcut dialog in Magnification * @return A magnification edit shortcut dialog in Magnification
*/ */
public static Dialog createMagnificationSwitchShortcutDialog(Context context, public static Dialog createMagnificationSwitchShortcutDialog(Context context,
CharSequence dialogTitle, CustomButtonsClickListener positiveBtnListener) { CustomButtonsClickListener positiveBtnListener) {
final View contentView = createSwitchShortcutDialogContentView(context); final View contentView = createSwitchShortcutDialogContentView(context);
final AlertDialog alertDialog = new AlertDialog.Builder(context) final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setView(contentView) .setView(contentView)
.setTitle(dialogTitle) .setTitle(context.getString(
R.string.accessibility_magnification_switch_shortcut_title))
.create(); .create();
setCustomButtonsClickListener(alertDialog, contentView, setCustomButtonsClickListener(alertDialog, contentView,
positiveBtnListener, /* negativeBtnListener= */ null); positiveBtnListener, /* negativeBtnListener= */ null);

View File

@@ -47,6 +47,7 @@ import com.android.settings.accessibility.MagnificationCapabilities.Magnificatio
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate; 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 com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import java.util.ArrayList; 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. */ /** Controller that shows the magnification area mode summary and the preference click behavior. */
public class MagnificationModePreferenceController extends BasePreferenceController implements 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; private static final int DIALOG_ID_BASE = 10;
@VisibleForTesting @VisibleForTesting
static final int DIALOG_MAGNIFICATION_MODE = DIALOG_ID_BASE + 1; 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 String TAG = "MagnificationModePreferenceController";
private static final char COMPONENT_NAME_SEPARATOR = ':'; private static final char COMPONENT_NAME_SEPARATOR = ':';
private MagnificationSettingsFragment mParentFragment; private DialogHelper mDialogHelper;
// The magnification mode in the dialog. // The magnification mode in the dialog.
private int mMode = MagnificationMode.NONE; private int mMode = MagnificationMode.NONE;
private Preference mModePreference; private Preference mModePreference;
@@ -121,7 +123,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl
mModePreference = screen.findPreference(getPreferenceKey()); mModePreference = screen.findPreference(getPreferenceKey());
mModePreference.setOnPreferenceClickListener(preference -> { mModePreference.setOnPreferenceClickListener(preference -> {
mMode = MagnificationCapabilities.getCapabilities(mContext); mMode = MagnificationCapabilities.getCapabilities(mContext);
mParentFragment.showDialog(DIALOG_MAGNIFICATION_MODE); mDialogHelper.showDialog(DIALOG_MAGNIFICATION_MODE);
return true; return true;
}); });
} }
@@ -131,8 +133,12 @@ public class MagnificationModePreferenceController extends BasePreferenceControl
outState.putInt(EXTRA_MODE, mMode); 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 @Override
@@ -207,7 +213,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl
} }
mMode = modeInfo.mMagnificationMode; mMode = modeInfo.mMagnificationMode;
if (isTripleTapEnabled(mContext) && mMode != MagnificationMode.FULLSCREEN) { 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() { private Dialog createMagnificationShortCutConfirmDialog() {
final String title = mContext.getString( return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext,
R.string.accessibility_magnification_switch_shortcut_title);
return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, title,
this::onSwitchShortcutDialogButtonClicked); this::onSwitchShortcutDialogButtonClicked);
} }
@@ -267,6 +271,21 @@ public class MagnificationModePreferenceController extends BasePreferenceControl
joiner.toString()); 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 @VisibleForTesting
static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo { static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo {
@MagnificationMode @MagnificationMode

View File

@@ -20,6 +20,7 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
@@ -27,11 +28,13 @@ import com.android.settingslib.search.SearchIndexable;
/** Settings page for magnification. */ /** Settings page for magnification. */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) @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 static final String TAG = "MagnificationSettingsFragment";
private MagnificationModePreferenceController mMagnificationModePreferenceController; private DialogCreatable mDialogDelegate;
@Override @Override
public int getMetricsCategory() { public int getMetricsCategory() {
@@ -41,19 +44,23 @@ public class MagnificationSettingsFragment extends DashboardFragment {
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mMagnificationModePreferenceController = use(MagnificationModePreferenceController.class); use(MagnificationModePreferenceController.class).setDialogHelper(this);
mMagnificationModePreferenceController.setParentFragment(this);
} }
@Override @Override
protected void showDialog(int dialogId) { public void showDialog(int dialogId) {
super.showDialog(dialogId); super.showDialog(dialogId);
} }
@Override
public void setDialogDelegate(DialogCreatable delegate) {
mDialogDelegate = delegate;
}
@Override @Override
public int getDialogMetricsCategory(int dialogId) { public int getDialogMetricsCategory(int dialogId) {
if (mMagnificationModePreferenceController != null) { if (mDialogDelegate != null) {
return mMagnificationModePreferenceController.getDialogMetricsCategory(dialogId); return mDialogDelegate.getDialogMetricsCategory(dialogId);
} }
return 0; return 0;
} }
@@ -70,8 +77,8 @@ public class MagnificationSettingsFragment extends DashboardFragment {
@Override @Override
public Dialog onCreateDialog(int dialogId) { public Dialog onCreateDialog(int dialogId) {
if (mMagnificationModePreferenceController != null) { if (mDialogDelegate != null) {
final Dialog dialog = mMagnificationModePreferenceController.onCreateDialog(dialogId); final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId);
if (dialog != null) { if (dialog != null) {
return dialog; return dialog;
} }

View File

@@ -42,6 +42,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; 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. * and does not have toggle bar to turn on service to use.
*/ */
public class ToggleScreenMagnificationPreferenceFragment extends public class ToggleScreenMagnificationPreferenceFragment extends
ToggleFeaturePreferenceFragment { ToggleFeaturePreferenceFragment implements
MagnificationModePreferenceController.DialogHelper {
// TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util. // TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util.
private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
@@ -67,6 +69,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
private static final TextUtils.SimpleStringSplitter sStringColonSplitter = private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
private MagnificationModePreferenceController mModePreferenceController;
private DialogCreatable mDialogDelegate;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -108,6 +113,12 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override @Override
public Dialog onCreateDialog(int dialogId) { public Dialog onCreateDialog(int dialogId) {
if (mDialogDelegate != null) {
final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId);
if (dialog != null) {
return dialog;
}
}
final AlertDialog dialog; final AlertDialog dialog;
switch (dialogId) { switch (dialogId) {
case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: case DialogEnums.GESTURE_NAVIGATION_TUTORIAL:
@@ -128,20 +139,35 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override @Override
protected void initSettingsPreference() { protected void initSettingsPreference() {
// If the device doesn't support magnification area, it should hide the settings preference. // If the device doesn't support magnification area, it should hide the settings preference.
if (!getContext().getResources().getBoolean( if (!getContext().getResources().getBoolean(
com.android.internal.R.bool.config_magnification_area)) { com.android.internal.R.bool.config_magnification_area)) {
return; return;
} }
mSettingsPreference = new Preference(getPrefContext()); mSettingsPreference = new Preference(getPrefContext());
mSettingsPreference.setTitle(R.string.accessibility_menu_item_settings); mSettingsPreference.setTitle(R.string.accessibility_magnification_mode_title);
// TODO(b/177371954): "magnification area" should be brought up to the highest level of the mSettingsPreference.setKey(MagnificationModePreferenceController.PREF_KEY);
// settings UI so that it appears below "shortcut" to replace "settings.
mSettingsPreference.setFragment(MagnificationSettingsFragment.class.getName());
mSettingsPreference.setPersistent(false); mSettingsPreference.setPersistent(false);
final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY);
generalCategory.addPreference(mSettingsPreference); 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 @Override
@@ -278,6 +304,13 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override @Override
public int getDialogMetricsCategory(int dialogId) { public int getDialogMetricsCategory(int dialogId) {
if (mDialogDelegate != null) {
final int category = mDialogDelegate.getDialogMetricsCategory(dialogId);
if (category != 0) {
return category;
}
}
switch (dialogId) { switch (dialogId) {
case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: case DialogEnums.GESTURE_NAVIGATION_TUTORIAL:
return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION; return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION;

View File

@@ -16,8 +16,6 @@
package com.android.settings.accessibility; 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.AccessibilityEditDialogUtils.CustomButton;
import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode; import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo; 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 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.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ListView; import android.widget.ListView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.DialogCreatable;
import com.android.settings.R; 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.Before;
import org.junit.Rule; 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.Answers; import org.mockito.Spy;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
/** Tests for {@link MagnificationModePreferenceController}. */
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowDashboardFragment.class)
public class MagnificationModePreferenceControllerTest { public class MagnificationModePreferenceControllerTest {
private static final String PREF_KEY = "screen_magnification_mode"; private static final String PREF_KEY = "screen_magnification_mode";
private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL; private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL;
@@ -67,39 +59,38 @@ public class MagnificationModePreferenceControllerTest {
@Rule @Rule
public MockitoRule mocks = MockitoJUnit.rule(); public MockitoRule mocks = MockitoJUnit.rule();
@Mock
private PreferenceScreen mScreen; private PreferenceScreen mScreen;
private Context mContext; private Context mContext;
private TestMagnificationSettingsFragment mFragment;
private MagnificationModePreferenceController mController; private MagnificationModePreferenceController mController;
private Preference mModePreference; private Preference mModePreference;
@Spy
private TestDialogHelper mDialogHelper = new TestDialogHelper();
@Before @Before
public void setUp() { public void setUp() {
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mController = new MagnificationModePreferenceController(mContext, PREF_KEY); final PreferenceManager preferenceManager = new PreferenceManager(mContext);
mScreen = spy(new PreferenceScreen(mContext, null)); mScreen = preferenceManager.createPreferenceScreen(mContext);
mModePreference = new Preference(mContext); mModePreference = new Preference(mContext);
mFragment = spy(new TestMagnificationSettingsFragment(mController)); mModePreference.setKey(PREF_KEY);
mScreen.addPreference(mModePreference);
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);
MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT); MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT);
mController = new MagnificationModePreferenceController(mContext, PREF_KEY);
showPreferenceOnTheScreen(null); showPreferenceOnTheScreen(null);
mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
} }
@Test @Test
public void settingsModeIsDefault_checkedModeInDialogIsDefault() { public void clickPreference_settingsModeIsDefault_checkedModeInDialogIsDefault() {
mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
assertThat(getCheckedModeFromDialog()).isEqualTo( assertThat(getCheckedModeFromDialog()).isEqualTo(
MAGNIFICATION_MODE_DEFAULT); MAGNIFICATION_MODE_DEFAULT);
} }
@Test @Test
public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() { public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() {
mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
performItemClickWith(MagnificationMode.WINDOW); performItemClickWith(MagnificationMode.WINDOW);
assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW); assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW);
@@ -107,11 +98,11 @@ public class MagnificationModePreferenceControllerTest {
@Test @Test
public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() { public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() {
showPreferenceOnTheScreen(null); mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
performItemClickWith(MagnificationMode.WINDOW); performItemClickWith(MagnificationMode.WINDOW);
reshowPreferenceOnTheScreen(); reshowPreferenceOnTheScreen();
mFragment.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); mDialogHelper.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE);
assertThat(getCheckedModeFromDialog()).isEqualTo( assertThat(getCheckedModeFromDialog()).isEqualTo(
MagnificationMode.WINDOW); MagnificationMode.WINDOW);
@@ -120,24 +111,22 @@ public class MagnificationModePreferenceControllerTest {
@Test @Test
public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() { public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap(); enableTripleTap();
mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
performItemClickWith(MagnificationMode.WINDOW); performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment).showDialog( verify(mDialogHelper).showDialog(
MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
} }
@Test @Test
public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() { public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() {
enableTripleTap(); enableTripleTap();
MagnificationCapabilities.setCapabilities(mContext, mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE);
performItemClickWith(MagnificationMode.ALL); performItemClickWith(MagnificationMode.ALL);
verify(mFragment, never()).showDialog( verify(mDialogHelper, never()).showDialog(
MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
} }
@@ -206,48 +195,38 @@ public class MagnificationModePreferenceControllerTest {
private void reshowPreferenceOnTheScreen() { private void reshowPreferenceOnTheScreen() {
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
mFragment.onSaveInstanceState(bundle); mController.onSaveInstanceState(bundle);
mFragment.onDetach();
showPreferenceOnTheScreen(bundle); showPreferenceOnTheScreen(bundle);
} }
private void showPreferenceOnTheScreen(Bundle savedInstanceState) { private void showPreferenceOnTheScreen(Bundle savedInstanceState) {
mFragment.onAttach(mContext); mController.setDialogHelper(mDialogHelper);
mFragment.onCreate(savedInstanceState); mController.onCreate(savedInstanceState);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
} }
private static class TestMagnificationSettingsFragment extends MagnificationSettingsFragment { private static class TestDialogHelper implements DialogCreatable,
MagnificationModePreferenceController.DialogHelper {
TestMagnificationSettingsFragment(AbstractPreferenceController... controllers) { private DialogCreatable mDialogDelegate;
// 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]);
}
}
@Override @Override
public void onCreate(Bundle icicle) { public void showDialog(int dialogId) {
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.
onCreateDialog(dialogId); onCreateDialog(dialogId);
} }
@Override @Override
protected void addPreferenceController(AbstractPreferenceController controller) { public void setDialogDelegate(DialogCreatable delegate) {
super.addPreferenceController(controller); mDialogDelegate = delegate;
}
@Override
public Dialog onCreateDialog(int dialogId) {
return mDialogDelegate.onCreateDialog(dialogId);
}
@Override
public int getDialogMetricsCategory(int dialogId) {
return mDialogDelegate.getDialogMetricsCategory(dialogId);
} }
} }
} }

View File

@@ -18,23 +18,78 @@ package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat; 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 androidx.test.core.app.ApplicationProvider;
import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils; import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowDashboardFragment;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List; import java.util.List;
/** Tests for {@link MagnificationSettingsFragment} */ /** Tests for {@link MagnificationSettingsFragment} */
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowDashboardFragment.class)
public class MagnificationSettingsFragmentTest { public class MagnificationSettingsFragmentTest {
private final Context mContext = ApplicationProvider.getApplicationContext(); 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 @Test
public void getNonIndexableKeys_existInXmlLayout() { public void getNonIndexableKeys_existInXmlLayout() {
@@ -46,4 +101,10 @@ public class MagnificationSettingsFragmentTest {
R.xml.accessibility_magnification_service_settings); R.xml.accessibility_magnification_service_settings);
assertThat(keys).containsAtLeastElementsIn(niks); assertThat(keys).containsAtLeastElementsIn(niks);
} }
private void showPreferenceOnTheScreen(Bundle savedInstanceState) {
mFragment.onAttach(mContext);
mFragment.onCreate(savedInstanceState);
mFragment.onResume();
}
} }

View File

@@ -23,9 +23,13 @@ import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment
import static com.google.common.truth.Truth.assertThat; 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.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.ComponentName; import android.content.ComponentName;
@@ -34,6 +38,7 @@ import android.content.DialogInterface;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -41,21 +46,28 @@ import android.view.ViewGroup;
import androidx.annotation.XmlRes; import androidx.annotation.XmlRes;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowFragment; 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.Before;
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.Mockito;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowSettingsPreferenceFragment.class})
public class ToggleScreenMagnificationPreferenceFragmentTest { public class ToggleScreenMagnificationPreferenceFragmentTest {
private static final String PLACEHOLDER_PACKAGE_NAME = "com.mock.example"; private static final String PLACEHOLDER_PACKAGE_NAME = "com.mock.example";
@@ -79,9 +91,6 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
private Context mContext; private Context mContext;
private Resources mResources; private Resources mResources;
@Mock
private PreferenceManager mPreferenceManager;
@Mock
private FragmentActivity mActivity; private FragmentActivity mActivity;
@Before @Before
@@ -89,14 +98,11 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment()); mActivity = Robolectric.setupActivity(FragmentActivity.class);
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment(mContext));
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mContext);
mResources = spy(mContext.getResources()); mResources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(mResources); when(mContext.getResources()).thenReturn(mResources);
when(mFragment.getContext().getResources()).thenReturn(mResources); when(mFragment.getContext().getResources()).thenReturn(mResources);
doReturn(null).when(mFragment).getPreferenceScreen();
doReturn(mActivity).when(mFragment).getActivity(); doReturn(mActivity).when(mFragment).getActivity();
} }
@@ -257,15 +263,38 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
} }
@Test @Test
public void initSettingsPreference_notSupportsMagnificationArea_settingsPreferenceIsNull() { public void onCreateView_notSupportsMagnificationArea_settingsPreferenceIsNull() {
when(mResources.getBoolean( when(mResources.getBoolean(
com.android.internal.R.bool.config_magnification_area)) com.android.internal.R.bool.config_magnification_area))
.thenReturn(false); .thenReturn(false);
mFragment.initSettingsPreference();
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
assertThat(mFragment.mSettingsPreference).isNull(); 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) { private void putStringIntoSettings(String key, String componentName) {
Settings.Secure.putString(mContext.getContentResolver(), key, componentName); Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
} }
@@ -291,8 +320,25 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
private void callEmptyOnClicked(DialogInterface dialog, int which) {} private void callEmptyOnClicked(DialogInterface dialog, int which) {}
public static class TestToggleScreenMagnificationPreferenceFragment /**
* a test fragment that initializes PreferenceScreen for testing.
*/
static class TestToggleScreenMagnificationPreferenceFragment
extends ToggleScreenMagnificationPreferenceFragment { 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 @Override
protected void onPreferenceToggled(String preferenceKey, boolean enabled) { protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
} }
@@ -313,9 +359,21 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public PreferenceScreen getPreferenceScreen() {
Bundle savedInstanceState) { return mPreferenceManager.getPreferenceScreen();
return mock(View.class); }
@Override
public <T extends Preference> T findPreference(CharSequence key) {
if (TextUtils.isEmpty(key)) {
return null;
}
return getPreferenceScreen().findPreference(key);
}
@Override
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
} }
@Override @Override
@@ -337,5 +395,15 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
protected void updateShortcutPreference() { protected void updateShortcutPreference() {
// UI related function, do nothing in tests // UI related function, do nothing in tests
} }
@Override
public Lifecycle getSettingsLifecycle() {
return mSpyLifeyCycle;
}
@Override
public Context getContext() {
return mContext;
}
} }
} }

View File

@@ -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;
}
}