From 7aaff67c3c5d32ee85b23ecdef830c6d46dd39d7 Mon Sep 17 00:00:00 2001 From: danielwbhuang Date: Wed, 7 Jun 2023 16:40:37 +0800 Subject: [PATCH 1/2] Log metrics for PK settings topics 1. Log metrics for touchpad settings 2. Log metrics for modifier keys remapping 3. Log metrics for physical keyboard settings Bug: 271391879 Test: manual, atest Change-Id: I3f948927719ec6fc3dca78cdcb995c3037d8f97f --- .../ModifierKeysPickerDialogFragment.java | 27 +++++++++ .../ModifierKeysResetDialogFragment.java | 8 +++ .../NewKeyboardLayoutPickerContent.java | 50 +++------------- .../NewKeyboardLayoutPickerController.java | 57 +++++++++++++++---- .../NewKeyboardLayoutPickerTitle.java | 3 +- .../inputmethod/PhysicalKeyboardFragment.java | 12 +++- ...uchGesturesButtonPreferenceController.java | 6 ++ .../TrackpadBottomPreferenceController.java | 8 +++ .../TrackpadGoBackPreferenceController.java | 8 +++ .../TrackpadGoHomePreferenceController.java | 8 +++ ...kpadNotificationsPreferenceController.java | 8 +++ ...ckpadPointerSpeedPreferenceController.java | 7 +++ ...rackpadRecentAppsPreferenceController.java | 8 +++ ...dReverseScrollingPreferenceController.java | 8 +++ ...rackpadSwitchAppsPreferenceController.java | 8 +++ ...rackpadTapToClickPreferenceController.java | 8 +++ ...rackpadBottomPreferenceControllerTest.java | 21 +++++++ ...rackpadGoBackPreferenceControllerTest.java | 21 +++++++ ...rackpadGoHomePreferenceControllerTest.java | 21 +++++++ ...NotificationsPreferenceControllerTest.java | 21 +++++++ ...dPointerSpeedPreferenceControllerTest.java | 17 ++++++ ...padRecentAppsPreferenceControllerTest.java | 21 +++++++ ...erseScrollingPreferenceControllerTest.java | 22 ++++++- ...padSwitchAppsPreferenceControllerTest.java | 21 +++++++ ...padTapToClickPreferenceControllerTest.java | 21 +++++++ 25 files changed, 363 insertions(+), 57 deletions(-) diff --git a/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java index 076173ae48e..28ead8919af 100644 --- a/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java +++ b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.content.Context; import android.graphics.drawable.Drawable; import android.hardware.input.InputManager; @@ -47,6 +48,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.Utils; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.ArrayList; import java.util.Arrays; @@ -68,6 +70,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment { private TextView mLeftBracket; private TextView mRightBracket; private ImageView mActionKeyIcon; + private MetricsFeatureProvider mMetricsFeatureProvider; private List mRemappableKeyList = new ArrayList<>(Arrays.asList( @@ -91,6 +94,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment { super.onCreateDialog(savedInstanceState); mActivity = getActivity(); + mMetricsFeatureProvider = FeatureFactory.getFactory(mActivity).getMetricsFeatureProvider(); FeatureFactory featureFactory = FeatureFactory.getFactory(mActivity); mFeatureProvider = featureFactory.getKeyboardSettingsFeatureProvider(); InputManager inputManager = mActivity.getSystemService(InputManager.class); @@ -139,6 +143,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment { doneButton.setOnClickListener(v -> { String selectedItem = modifierKeys.get(adapter.getCurrentItem()); Spannable itemSummary; + logMetricsForRemapping(selectedItem); if (selectedItem.equals(mKeyDefaultName)) { itemSummary = new SpannableString( mActivity.getString(R.string.modifier_keys_default_summary)); @@ -189,6 +194,28 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment { return modifierKeyDialog; } + private void logMetricsForRemapping(String selectedItem) { + if (mKeyDefaultName.equals("Caps lock")) { + mMetricsFeatureProvider.action( + mActivity, SettingsEnums.ACTION_FROM_CAPS_LOCK_TO, selectedItem); + } + + if (mKeyDefaultName.equals("Ctrl")) { + mMetricsFeatureProvider.action( + mActivity, SettingsEnums.ACTION_FROM_CTRL_TO, selectedItem); + } + + if (mKeyDefaultName.equals("Action key")) { + mMetricsFeatureProvider.action( + mActivity, SettingsEnums.ACTION_FROM_ACTION_KEY_TO, selectedItem); + } + + if (mKeyDefaultName.equals("Alt")) { + mMetricsFeatureProvider.action( + mActivity, SettingsEnums.ACTION_FROM_ALT_TO, selectedItem); + } + } + private void setInitialFocusItem( List modifierKeys, ModifierKeyAdapter adapter) { if (modifierKeys.indexOf(mKeyFocus) == -1) { diff --git a/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java b/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java index 755e9dddedf..fea6e65e777 100644 --- a/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java +++ b/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.hardware.input.InputManager; import android.os.Bundle; import android.view.LayoutInflater; @@ -31,13 +32,18 @@ import android.widget.Button; import androidx.fragment.app.DialogFragment; import com.android.settings.R; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class ModifierKeysResetDialogFragment extends DialogFragment { + private static final String MODIFIER_KEYS_CAPS_LOCK = "modifier_keys_caps_lock"; private static final String MODIFIER_KEYS_CTRL = "modifier_keys_ctrl"; private static final String MODIFIER_KEYS_META = "modifier_keys_meta"; private static final String MODIFIER_KEYS_ALT = "modifier_keys_alt"; + private MetricsFeatureProvider mMetricsFeatureProvider; + private String[] mKeys = { MODIFIER_KEYS_CAPS_LOCK, MODIFIER_KEYS_CTRL, @@ -51,6 +57,7 @@ public class ModifierKeysResetDialogFragment extends DialogFragment { super.onCreateDialog(savedInstanceState); Activity activity = getActivity(); + mMetricsFeatureProvider = FeatureFactory.getFactory(activity).getMetricsFeatureProvider(); InputManager inputManager = activity.getSystemService(InputManager.class); View dialoglayout = LayoutInflater.from(activity).inflate(R.layout.modifier_key_reset_dialog, null); @@ -60,6 +67,7 @@ public class ModifierKeysResetDialogFragment extends DialogFragment { Button restoreButton = dialoglayout.findViewById(R.id.modifier_key_reset_restore_button); restoreButton.setOnClickListener(v -> { + mMetricsFeatureProvider.action(activity, SettingsEnums.ACTION_CLEAR_REMAPPINGS); inputManager.clearAllModifierKeyRemappings(); dismiss(); activity.recreate(); diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java index 1af001bda31..11740ec8201 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java @@ -20,10 +20,6 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; -import android.hardware.input.KeyboardLayout; -import android.os.Bundle; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -32,55 +28,23 @@ public class NewKeyboardLayoutPickerContent extends DashboardFragment { private static final String TAG = "KeyboardLayoutPicker"; - private InputManager mIm; - private int mUserId; - private InputDeviceIdentifier mIdentifier; - private InputMethodInfo mInputMethodInfo; - private InputMethodSubtype mInputMethodSubtype; - @Override public void onAttach(Context context) { super.onAttach(context); - mIm = getContext().getSystemService(InputManager.class); - Bundle arguments = getArguments(); - final CharSequence title = arguments.getCharSequence(NewKeyboardSettingsUtils.EXTRA_TITLE); - mUserId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID); - mIdentifier = - arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER); - mInputMethodInfo = - arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO); - mInputMethodSubtype = - arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE); - if (mIdentifier == null - || NewKeyboardSettingsUtils.getInputDevice(mIm, mIdentifier) == null) { + InputManager im = getContext().getSystemService(InputManager.class); + InputDeviceIdentifier identifier = + getArguments().getParcelable( + NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER); + if (identifier == null + || NewKeyboardSettingsUtils.getInputDevice(im, identifier) == null) { getActivity().finish(); return; } - getActivity().setTitle(title); - use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/, mUserId, - mIdentifier, mInputMethodInfo, mInputMethodSubtype, getSelectedLayoutLabel()); - } - - private String getSelectedLayoutLabel() { - String label = getContext().getString(R.string.keyboard_default_layout); - String layout = NewKeyboardSettingsUtils.getKeyboardLayout( - mIm, mUserId, mIdentifier, mInputMethodInfo, mInputMethodSubtype); - KeyboardLayout[] keyboardLayouts = NewKeyboardSettingsUtils.getKeyboardLayouts( - mIm, mUserId, mIdentifier, mInputMethodInfo, mInputMethodSubtype); - if (layout != null) { - for (int i = 0; i < keyboardLayouts.length; i++) { - if (keyboardLayouts[i].getDescriptor().equals(layout)) { - label = keyboardLayouts[i].getLabel(); - break; - } - } - } - return label; + use(NewKeyboardLayoutPickerController.class).initialize(this); } @Override public int getMetricsCategory() { - // TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_CONTENT return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER; } diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java index 8278be88d98..65b1c62040b 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java @@ -16,10 +16,12 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.hardware.input.KeyboardLayout; +import android.os.Bundle; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; @@ -27,8 +29,11 @@ import androidx.fragment.app.Fragment; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.TickButtonPreference; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; @@ -38,38 +43,47 @@ import java.util.Map; public class NewKeyboardLayoutPickerController extends BasePreferenceController implements InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop { + private final InputManager mIm; private final Map mPreferenceMap; - private Fragment mParent; + private CharSequence mTitle; private int mInputDeviceId; private int mUserId; private InputDeviceIdentifier mInputDeviceIdentifier; private InputMethodInfo mInputMethodInfo; private InputMethodSubtype mInputMethodSubtype; - private KeyboardLayout[] mKeyboardLayouts; private PreferenceScreen mScreen; private String mPreviousSelection; + private String mFinalSelectedLayout; private String mLayout; + private MetricsFeatureProvider mMetricsFeatureProvider; public NewKeyboardLayoutPickerController(Context context, String key) { super(context, key); mIm = context.getSystemService(InputManager.class); mInputDeviceId = -1; mPreferenceMap = new HashMap<>(); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } - public void initialize(Fragment parent, int userId, InputDeviceIdentifier inputDeviceIdentifier, - InputMethodInfo imeInfo, InputMethodSubtype imeSubtype, String layout) { + public void initialize(Fragment parent) { mParent = parent; - mUserId = userId; - mInputDeviceIdentifier = inputDeviceIdentifier; - mInputMethodInfo = imeInfo; - mInputMethodSubtype = imeSubtype; - mLayout = layout; + Bundle arguments = parent.getArguments(); + mTitle = arguments.getCharSequence(NewKeyboardSettingsUtils.EXTRA_TITLE); + mUserId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID); + mInputDeviceIdentifier = + arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER); + mInputMethodInfo = + arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO); + mInputMethodSubtype = + arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE); + mLayout = getSelectedLayoutLabel(); + mFinalSelectedLayout = mLayout; mKeyboardLayouts = mIm.getKeyboardLayoutListForInputDevice( - inputDeviceIdentifier, userId, imeInfo, imeSubtype); + mInputDeviceIdentifier, mUserId, mInputMethodInfo, mInputMethodSubtype); + parent.getActivity().setTitle(mTitle); } @Override @@ -85,6 +99,11 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController @Override public void onStop() { + if (!mLayout.equals(mFinalSelectedLayout)) { + String change = "From:" + mLayout + ", to:" + mFinalSelectedLayout; + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_PK_LAYOUT_CHANGED, change); + } mIm.unregisterInputDeviceListener(this); mInputDeviceId = -1; } @@ -115,6 +134,7 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController } setLayout(pref); mPreviousSelection = preference.getKey(); + mFinalSelectedLayout = pref.getTitle().toString(); return true; } @@ -162,4 +182,21 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController mInputMethodSubtype, mPreferenceMap.get(preference).getDescriptor()); } + + private String getSelectedLayoutLabel() { + String label = mContext.getString(R.string.keyboard_default_layout); + String layout = NewKeyboardSettingsUtils.getKeyboardLayout( + mIm, mUserId, mInputDeviceIdentifier, mInputMethodInfo, mInputMethodSubtype); + KeyboardLayout[] keyboardLayouts = NewKeyboardSettingsUtils.getKeyboardLayouts( + mIm, mUserId, mInputDeviceIdentifier, mInputMethodInfo, mInputMethodSubtype); + if (layout != null) { + for (KeyboardLayout keyboardLayout : keyboardLayouts) { + if (keyboardLayout.getDescriptor().equals(layout)) { + label = keyboardLayout.getLabel(); + break; + } + } + } + return label; + } } diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java index abcad277e8e..7f8782697bb 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java @@ -34,8 +34,7 @@ public class NewKeyboardLayoutPickerTitle extends SettingsPreferenceFragment { @Override public int getMetricsCategory() { - // TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_TITLE - return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER; + return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER_TITLE; } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java index f504fbaaf3f..9f5d67a8e9a 100644 --- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java +++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java @@ -108,6 +108,7 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment SHOW_VIRTUAL_KEYBOARD_SWITCH)); FeatureFactory featureFactory = FeatureFactory.getFactory(getContext()); + mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); mFeatureProvider = featureFactory.getKeyboardSettingsFeatureProvider(); mSupportsFirmwareUpdate = mFeatureProvider.supportsFirmwareUpdate(); if (mSupportsFirmwareUpdate) { @@ -122,7 +123,12 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment } InputDeviceIdentifier inputDeviceIdentifier = activity.getIntent().getParcelableExtra( KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER); - // TODO (b/271391879): The EXTRA_INTENT_FROM is used for the future metrics. + String intentFromWhere = + activity.getIntent().getStringExtra(NewKeyboardSettingsUtils.EXTRA_INTENT_FROM); + if (intentFromWhere != null) { + mMetricsFeatureProvider.action( + getContext(), SettingsEnums.ACTION_OPEN_PK_SETTINGS_FROM, intentFromWhere); + } if (inputDeviceIdentifier != null) { mAutoInputDeviceIdentifier = inputDeviceIdentifier; } @@ -253,6 +259,10 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment }); } category.addPreference(pref); + mMetricsFeatureProvider.action( + getContext(), + SettingsEnums.ACTION_USE_SPECIFIC_KEYBOARD, + hardKeyboardDeviceInfo.mDeviceName); } mKeyboardAssistanceCategory.setOrder(1); preferenceScreen.addPreference(mKeyboardAssistanceCategory); diff --git a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java index bbe65c11fb8..f0ee1fd252f 100644 --- a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java +++ b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.util.FeatureFlagUtils; @@ -23,6 +24,8 @@ import androidx.fragment.app.Fragment; import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.widget.ButtonPreference; public class TouchGesturesButtonPreferenceController extends BasePreferenceController { @@ -33,9 +36,11 @@ public class TouchGesturesButtonPreferenceController extends BasePreferenceContr private static final String GESTURE_DIALOG_TAG = "GESTURE_DIALOG_TAG"; private Fragment mParent; + private MetricsFeatureProvider mMetricsFeatureProvider; public TouchGesturesButtonPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } public void setFragment(Fragment parent) { @@ -67,6 +72,7 @@ public class TouchGesturesButtonPreferenceController extends BasePreferenceContr } private void showTouchpadGestureEducation() { + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_LEARN_TOUCHPAD_GESTURE_CLICK); TrackpadGestureDialogFragment fragment = new TrackpadGestureDialogFragment(); fragment.setTargetFragment(mParent, 0); fragment.show(mParent.getActivity().getSupportFragmentManager(), GESTURE_DIALOG_TAG); diff --git a/src/com/android/settings/inputmethod/TrackpadBottomPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadBottomPreferenceController.java index 5133d0438d3..1cf1f6f9e75 100644 --- a/src/com/android/settings/inputmethod/TrackpadBottomPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadBottomPreferenceController.java @@ -16,16 +16,22 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputSettings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadBottomPreferenceController extends TogglePreferenceController { + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadBottomPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -36,6 +42,8 @@ public class TrackpadBottomPreferenceController extends TogglePreferenceControll @Override public boolean setChecked(boolean isChecked) { InputSettings.setTouchpadRightClickZone(mContext, isChecked); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_BOTTOM_RIGHT_TAP_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceController.java index 017689d6987..11d7cf3db07 100644 --- a/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceController.java @@ -16,18 +16,24 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadGoBackPreferenceController extends TogglePreferenceController { private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_BACK_ENABLED; + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadGoBackPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -38,6 +44,8 @@ public class TrackpadGoBackPreferenceController extends TogglePreferenceControll @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY, isChecked ? 1 : 0); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_GO_BACK_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceController.java b/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceController.java index 18699e3e3a1..5027e2f678d 100644 --- a/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceController.java @@ -16,18 +16,24 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadGoHomePreferenceController extends TogglePreferenceController { private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_HOME_ENABLED; + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadGoHomePreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -38,6 +44,8 @@ public class TrackpadGoHomePreferenceController extends TogglePreferenceControll @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY, isChecked ? 1 : 0); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_GO_HOME_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceController.java index 21f04a37f94..0fb28d72cd9 100644 --- a/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceController.java @@ -16,18 +16,24 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadNotificationsPreferenceController extends TogglePreferenceController { private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_NOTIFICATION_ENABLED; + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadNotificationsPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -38,6 +44,8 @@ public class TrackpadNotificationsPreferenceController extends TogglePreferenceC @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY, isChecked ? 1 : 0); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_NOTIFICATION_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceController.java index 71b4119a7bc..58b477244de 100644 --- a/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceController.java @@ -16,20 +16,25 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputSettings; import androidx.preference.PreferenceScreen; import com.android.settings.core.SliderPreferenceController; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.SeekBarPreference; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadPointerSpeedPreferenceController extends SliderPreferenceController { private SeekBarPreference mPreference; + private MetricsFeatureProvider mMetricsFeatureProvider; public TrackpadPointerSpeedPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -53,6 +58,8 @@ public class TrackpadPointerSpeedPreferenceController extends SliderPreferenceCo return false; } InputSettings.setTouchpadPointerSpeed(mContext, position); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_POINTER_SPEED_CHANGED, position); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceController.java index eab2b330968..878cbe3fc4e 100644 --- a/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceController.java @@ -16,18 +16,24 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadRecentAppsPreferenceController extends TogglePreferenceController { private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_OVERVIEW_ENABLED; + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadRecentAppsPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -38,6 +44,8 @@ public class TrackpadRecentAppsPreferenceController extends TogglePreferenceCont @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY, isChecked ? 1 : 0); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_RECENT_APPS_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceController.java index 10d30139b6c..2b74c74686a 100644 --- a/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceController.java @@ -16,16 +16,22 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputSettings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadReverseScrollingPreferenceController extends TogglePreferenceController { + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadReverseScrollingPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -36,6 +42,8 @@ public class TrackpadReverseScrollingPreferenceController extends TogglePreferen @Override public boolean setChecked(boolean isChecked) { InputSettings.setTouchpadNaturalScrolling(mContext, !isChecked); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_REVERSE_SCROLLING_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceController.java index 84de64e9494..cfca856b894 100644 --- a/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceController.java @@ -16,18 +16,24 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadSwitchAppsPreferenceController extends TogglePreferenceController { private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_QUICK_SWITCH_ENABLED; + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadSwitchAppsPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -38,6 +44,8 @@ public class TrackpadSwitchAppsPreferenceController extends TogglePreferenceCont @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY, isChecked ? 1 : 0); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_SWITCH_APPS_CHANGED, isChecked); return true; } diff --git a/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceController.java index 86553070a55..9ee446ba304 100644 --- a/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceController.java +++ b/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceController.java @@ -16,16 +16,22 @@ package com.android.settings.inputmethod; +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputSettings; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class TrackpadTapToClickPreferenceController extends TogglePreferenceController { + private MetricsFeatureProvider mMetricsFeatureProvider; + public TrackpadTapToClickPreferenceController(Context context, String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -36,6 +42,8 @@ public class TrackpadTapToClickPreferenceController extends TogglePreferenceCont @Override public boolean setChecked(boolean isChecked) { InputSettings.setTouchpadTapToClick(mContext, isChecked); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_GESTURE_TAP_TO_CLICK_CHANGED, isChecked); return true; } diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadBottomPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadBottomPreferenceControllerTest.java index 1b061ec8d74..3c51cf342a2 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadBottomPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadBottomPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; @@ -26,25 +31,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadBottomPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadBottomPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "trackpad_bottom_right_tap"; private static final String SETTING_KEY = Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE; private Context mContext; private TrackpadBottomPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadBottomPreferenceController(mContext, PREFERENCE_KEY); } @@ -70,6 +83,10 @@ public class TrackpadBottomPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_BOTTOM_RIGHT_TAP_CHANGED), + eq(true)); } @Test @@ -83,6 +100,10 @@ public class TrackpadBottomPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_BOTTOM_RIGHT_TAP_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceControllerTest.java index 0e1705e6d00..85d56ef834b 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoBackPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; @@ -25,25 +30,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadGoBackPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadGoBackPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "gesture_go_back"; private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_BACK_ENABLED; private Context mContext; private TrackpadGoBackPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadGoBackPreferenceController(mContext, PREFERENCE_KEY); } @@ -65,6 +78,10 @@ public class TrackpadGoBackPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_GO_BACK_CHANGED), + eq(true)); } @Test @@ -74,6 +91,10 @@ public class TrackpadGoBackPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_GO_BACK_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceControllerTest.java index 3289bccbd52..6b3b3f5a86d 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadGoHomePreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; @@ -25,25 +30,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadGoHomePreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadGoHomePreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "gesture_go_home"; private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_HOME_ENABLED; private Context mContext; private TrackpadGoHomePreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadGoHomePreferenceController(mContext, PREFERENCE_KEY); } @@ -65,6 +78,10 @@ public class TrackpadGoHomePreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_GO_HOME_CHANGED), + eq(true)); } @Test @@ -74,6 +91,10 @@ public class TrackpadGoHomePreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_GO_HOME_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceControllerTest.java index 3df16272655..005bc9fcf23 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadNotificationsPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; @@ -25,25 +30,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadNotificationsPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadNotificationsPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "gesture_notifications"; private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_NOTIFICATION_ENABLED; private Context mContext; private TrackpadNotificationsPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadNotificationsPreferenceController(mContext, PREFERENCE_KEY); } @@ -65,6 +78,10 @@ public class TrackpadNotificationsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_NOTIFICATION_CHANGED), + eq(true)); } @Test @@ -74,6 +91,10 @@ public class TrackpadNotificationsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_NOTIFICATION_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceControllerTest.java index daf17737ffa..1cfda128908 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadPointerSpeedPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.hardware.input.InputSettings; import android.os.UserHandle; @@ -26,15 +31,21 @@ import android.provider.Settings; import androidx.test.core.app.ApplicationProvider; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadPointerSpeedPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadPointerSpeedPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "trackpad_pointer_speed"; private static final String SETTING_KEY = Settings.System.TOUCHPAD_POINTER_SPEED; @@ -42,10 +53,12 @@ public class TrackpadPointerSpeedPreferenceControllerTest { private Context mContext; private TrackpadPointerSpeedPreferenceController mController; private int mDefaultSpeed; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadPointerSpeedPreferenceController(mContext, PREFERENCE_KEY); mDefaultSpeed = Settings.System.getIntForUser( mContext.getContentResolver(), @@ -85,6 +98,10 @@ public class TrackpadPointerSpeedPreferenceControllerTest { assertThat(result).isTrue(); assertThat(mController.getSliderPosition()).isEqualTo(inputSpeed); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_POINTER_SPEED_CHANGED), + eq(1)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceControllerTest.java index dbed5421a00..2ef53a67aeb 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadRecentAppsPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; @@ -25,25 +30,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadRecentAppsPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadRecentAppsPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "gesture_recent_apps"; private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_OVERVIEW_ENABLED; private Context mContext; private TrackpadRecentAppsPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadRecentAppsPreferenceController(mContext, PREFERENCE_KEY); } @@ -65,6 +78,10 @@ public class TrackpadRecentAppsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_RECENT_APPS_CHANGED), + eq(true)); } @Test @@ -74,6 +91,10 @@ public class TrackpadRecentAppsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_RECENT_APPS_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceControllerTest.java index a99abb8d38f..e74261e3472 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadReverseScrollingPreferenceControllerTest.java @@ -16,9 +16,13 @@ package com.android.settings.inputmethod; - import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; @@ -27,25 +31,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadReverseScrollingPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadReverseScrollingPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "trackpad_reverse_scrolling"; private static final String SETTING_KEY = Settings.System.TOUCHPAD_NATURAL_SCROLLING; private Context mContext; private TrackpadReverseScrollingPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadReverseScrollingPreferenceController(mContext, PREFERENCE_KEY); } @@ -71,6 +83,10 @@ public class TrackpadReverseScrollingPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_REVERSE_SCROLLING_CHANGED), + eq(true)); } @Test @@ -84,6 +100,10 @@ public class TrackpadReverseScrollingPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_REVERSE_SCROLLING_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceControllerTest.java index 3f160258e29..5e354d2ca18 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadSwitchAppsPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.provider.Settings; @@ -25,25 +30,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadSwitchAppsPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadSwitchAppsPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "gesture_switch_apps"; private static final String SETTING_KEY = Settings.Secure.TRACKPAD_GESTURE_QUICK_SWITCH_ENABLED; private Context mContext; private TrackpadSwitchAppsPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadSwitchAppsPreferenceController(mContext, PREFERENCE_KEY); } @@ -65,6 +78,10 @@ public class TrackpadSwitchAppsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_SWITCH_APPS_CHANGED), + eq(true)); } @Test @@ -74,6 +91,10 @@ public class TrackpadSwitchAppsPreferenceControllerTest { int result = Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 1); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_SWITCH_APPS_CHANGED), + eq(false)); } @Test diff --git a/tests/robotests/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceControllerTest.java index b4b8921a050..3784cc73935 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/TrackpadTapToClickPreferenceControllerTest.java @@ -18,6 +18,11 @@ package com.android.settings.inputmethod; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; @@ -26,25 +31,33 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link TrackpadTapToClickPreferenceController} */ @RunWith(RobolectricTestRunner.class) public class TrackpadTapToClickPreferenceControllerTest { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); private static final String PREFERENCE_KEY = "trackpad_tap_to_click"; private static final String SETTING_KEY = Settings.System.TOUCHPAD_TAP_TO_CLICK; private Context mContext; private TrackpadTapToClickPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new TrackpadTapToClickPreferenceController(mContext, PREFERENCE_KEY); } @@ -70,6 +83,10 @@ public class TrackpadTapToClickPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(1); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_TAP_TO_CLICK_CHANGED), + eq(true)); } @Test @@ -83,6 +100,10 @@ public class TrackpadTapToClickPreferenceControllerTest { UserHandle.USER_CURRENT); assertThat(result).isEqualTo(0); + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), + eq(SettingsEnums.ACTION_GESTURE_TAP_TO_CLICK_CHANGED), + eq(false)); } @Test From d42cc8e5e2bf8517a220d222b3c8308bf5db5b36 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Tue, 4 Jul 2023 00:12:42 +0800 Subject: [PATCH 2/2] Fix DataUsagePreferenceController ANR Offload calculation work from main thread to fix. Fix: 286082055 Test: manual - on Mobile Settings page Test: unit test Change-Id: I7865823d6af2c812afa35d047bd79b60ae4b0fb7 --- .../DataUsagePreferenceController.java | 151 --------------- .../DataUsagePreferenceController.kt | 126 +++++++++++++ .../telephony/MobileNetworkSettings.java | 9 + .../DataUsagePreferenceControllerTest.java | 139 -------------- .../DataUsagePreferenceControllerTest.kt | 172 ++++++++++++++++++ 5 files changed, 307 insertions(+), 290 deletions(-) delete mode 100644 src/com/android/settings/network/telephony/DataUsagePreferenceController.java create mode 100644 src/com/android/settings/network/telephony/DataUsagePreferenceController.kt delete mode 100644 tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java create mode 100644 tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java deleted file mode 100644 index a536c1da96b..00000000000 --- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2018 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.network.telephony; - -import android.content.Context; -import android.content.Intent; -import android.net.NetworkTemplate; -import android.provider.Settings; -import android.telephony.SubscriptionManager; -import android.text.TextUtils; -import android.util.Log; - -import androidx.preference.Preference; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.settings.R; -import com.android.settings.datausage.DataUsageUtils; -import com.android.settings.datausage.lib.DataUsageLib; -import com.android.settingslib.net.DataUsageController; -import com.android.settingslib.utils.ThreadUtils; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Preference controller for "Data usage" - */ -public class DataUsagePreferenceController extends TelephonyBasePreferenceController { - - private static final String LOG_TAG = "DataUsagePreferCtrl"; - - private Future mTemplateFuture; - private AtomicReference mTemplate; - private Future mHistoricalUsageLevel; - - public DataUsagePreferenceController(Context context, String key) { - super(context, key); - mTemplate = new AtomicReference(); - } - - @Override - public int getAvailabilityStatus(int subId) { - return (SubscriptionManager.isValidSubscriptionId(subId)) - && DataUsageUtils.hasMobileData(mContext) - ? AVAILABLE - : AVAILABLE_UNSEARCHABLE; - } - - @Override - public boolean handlePreferenceTreeClick(Preference preference) { - if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { - return false; - } - final Intent intent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE); - intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, getNetworkTemplate()); - intent.putExtra(Settings.EXTRA_SUB_ID, mSubId); - - mContext.startActivity(intent); - return true; - } - - @Override - public void updateState(Preference preference) { - super.updateState(preference); - if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { - preference.setEnabled(false); - return; - } - final CharSequence summary = getDataUsageSummary(mContext, mSubId); - if (summary == null) { - preference.setEnabled(false); - } else { - preference.setEnabled(true); - preference.setSummary(summary); - } - } - - public void init(int subId) { - mSubId = subId; - mTemplate.set(null); - mTemplateFuture = ThreadUtils.postOnBackgroundThread(() - -> fetchMobileTemplate(mContext, mSubId)); - } - - private NetworkTemplate fetchMobileTemplate(Context context, int subId) { - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return null; - } - return DataUsageLib.getMobileTemplate(context, subId); - } - - private NetworkTemplate getNetworkTemplate() { - if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { - return null; - } - NetworkTemplate template = mTemplate.get(); - if (template != null) { - return template; - } - try { - template = mTemplateFuture.get(); - mTemplate.set(template); - } catch (ExecutionException | InterruptedException | NullPointerException exception) { - Log.e(LOG_TAG, "Fail to get data usage template", exception); - } - return template; - } - - @VisibleForTesting - DataUsageController.DataUsageInfo getDataUsageInfo(DataUsageController controller) { - return controller.getDataUsageInfo(getNetworkTemplate()); - } - - private CharSequence getDataUsageSummary(Context context, int subId) { - final DataUsageController controller = new DataUsageController(context); - controller.setSubscriptionId(subId); - - mHistoricalUsageLevel = ThreadUtils.postOnBackgroundThread(() -> - controller.getHistoricalUsageLevel(getNetworkTemplate())); - - final DataUsageController.DataUsageInfo usageInfo = getDataUsageInfo(controller); - - long usageLevel = usageInfo.usageLevel; - if (usageLevel <= 0L) { - try { - usageLevel = mHistoricalUsageLevel.get(); - } catch (Exception exception) { - } - } - if (usageLevel <= 0L) { - return null; - } - return context.getString(R.string.data_usage_template, - DataUsageUtils.formatDataUsage(context, usageLevel), usageInfo.period); - } -} diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt new file mode 100644 index 00000000000..14adf6f1918 --- /dev/null +++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2023 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.network.telephony + +import android.content.Context +import android.content.Intent +import android.net.NetworkTemplate +import android.provider.Settings +import android.telephony.SubscriptionManager +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import androidx.preference.Preference +import androidx.preference.PreferenceScreen +import com.android.settings.R +import com.android.settings.datausage.DataUsageUtils +import com.android.settingslib.net.DataUsageController +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * Preference controller for "Data usage" + */ +class DataUsagePreferenceController(context: Context, key: String) : + TelephonyBasePreferenceController(context, key) { + + private lateinit var preference: Preference + private var networkTemplate: NetworkTemplate? = null + + @VisibleForTesting + var dataUsageControllerFactory: (Context) -> DataUsageController = { DataUsageController(it) } + + fun init(subId: Int) { + mSubId = subId + } + + override fun getAvailabilityStatus(subId: Int): Int = when { + SubscriptionManager.isValidSubscriptionId(subId) && + DataUsageUtils.hasMobileData(mContext) -> AVAILABLE + + else -> AVAILABLE_UNSEARCHABLE + } + + override fun displayPreference(screen: PreferenceScreen) { + super.displayPreference(screen) + preference = screen.findPreference(preferenceKey)!! + } + + fun whenViewCreated(viewLifecycleOwner: LifecycleOwner) { + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + update() + } + } + } + + override fun handlePreferenceTreeClick(preference: Preference): Boolean { + if (preference.key != preferenceKey || networkTemplate == null) return false + val intent = Intent(Settings.ACTION_MOBILE_DATA_USAGE).apply { + putExtra(Settings.EXTRA_NETWORK_TEMPLATE, networkTemplate) + putExtra(Settings.EXTRA_SUB_ID, mSubId) + } + mContext.startActivity(intent) + return true + } + + private suspend fun update() { + val summary = withContext(Dispatchers.Default) { + networkTemplate = getNetworkTemplate() + getDataUsageSummary() + } + if (summary == null) { + preference.isEnabled = false + } else { + preference.isEnabled = true + preference.summary = summary + } + } + + private fun getNetworkTemplate(): NetworkTemplate? = when { + SubscriptionManager.isValidSubscriptionId(mSubId) -> { + DataUsageUtils.getMobileTemplate(mContext, mSubId) + } + + else -> null + } + + private fun getDataUsageSummary(): String? { + val networkTemplate = networkTemplate ?: return null + val controller = dataUsageControllerFactory(mContext).apply { + setSubscriptionId(mSubId) + } + val usageInfo = controller.getDataUsageInfo(networkTemplate) + if (usageInfo != null && usageInfo.usageLevel > 0) { + return mContext.getString( + R.string.data_usage_template, + DataUsageUtils.formatDataUsage(mContext, usageInfo.usageLevel), + usageInfo.period, + ) + } + + return controller.getHistoricalUsageLevel(networkTemplate).takeIf { it > 0 }?.let { + mContext.getString( + R.string.data_used_template, + DataUsageUtils.formatDataUsage(mContext, it), + ) + } + } +} diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index 1d862f3385f..5b57ede430a 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -31,7 +31,10 @@ import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; @@ -327,6 +330,12 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme onRestoreInstance(icicle); } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + use(DataUsagePreferenceController.class).whenViewCreated(getViewLifecycleOwner()); + } + @Override public void onResume() { super.onResume(); diff --git a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java deleted file mode 100644 index a3be60d2574..00000000000 --- a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2018 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.network.telephony; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import android.app.usage.NetworkStatsManager; -import android.content.Context; -import android.content.Intent; -import android.provider.Settings; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.DataUnit; - -import androidx.preference.SwitchPreference; - -import com.android.settings.core.BasePreferenceController; -import com.android.settingslib.net.DataUsageController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; -import org.robolectric.shadows.ShadowTelephonyManager; - -@RunWith(RobolectricTestRunner.class) -public class DataUsagePreferenceControllerTest { - private static final int SUB_ID = 2; - - @Mock - private NetworkStatsManager mNetworkStatsManager; - private DataUsagePreferenceController mController; - private SwitchPreference mPreference; - private Context mContext; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mContext = spy(RuntimeEnvironment.application); - - final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); - final ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf(telephonyManager); - shadowTelephonyManager.setTelephonyManagerForSubscriptionId(SUB_ID, telephonyManager); - shadowTelephonyManager.setTelephonyManagerForSubscriptionId( - SubscriptionManager.INVALID_SUBSCRIPTION_ID, telephonyManager); - - doReturn(mNetworkStatsManager).when(mContext).getSystemService(NetworkStatsManager.class); - - mPreference = new SwitchPreference(mContext); - mController = spy(new DataUsagePreferenceController(mContext, "data_usage")); - mController.init(SUB_ID); - mPreference.setKey(mController.getPreferenceKey()); - } - - @Test - public void getAvailabilityStatus_validSubId_returnAvailable() { - assertThat(mController.getAvailabilityStatus()).isEqualTo( - BasePreferenceController.AVAILABLE); - } - - @Test - public void getAvailabilityStatus_invalidSubId_returnUnsearchable() { - mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID); - - assertThat(mController.getAvailabilityStatus()).isEqualTo( - BasePreferenceController.AVAILABLE_UNSEARCHABLE); - } - - @Test - public void handlePreferenceTreeClick_needDialog_showDialog() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); - doNothing().when(mContext).startActivity(captor.capture()); - - mController.handlePreferenceTreeClick(mPreference); - - final Intent intent = captor.getValue(); - - assertThat(intent.getAction()).isEqualTo(Settings.ACTION_MOBILE_DATA_USAGE); - assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID, 0)).isEqualTo(SUB_ID); - } - - @Test - public void updateState_invalidSubId_disabled() { - mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID); - - mController.updateState(mPreference); - - assertThat(mPreference.isEnabled()).isFalse(); - } - - @Test - public void updateState_noUsageData_shouldDisablePreference() { - final DataUsageController.DataUsageInfo usageInfo = - new DataUsageController.DataUsageInfo(); - doReturn(usageInfo).when(mController).getDataUsageInfo(any()); - - mController.updateState(mPreference); - - assertThat(mPreference.isEnabled()).isFalse(); - } - - @Test - public void updateState_shouldUseIECUnit() { - final DataUsageController.DataUsageInfo usageInfo = - new DataUsageController.DataUsageInfo(); - usageInfo.usageLevel = DataUnit.MEBIBYTES.toBytes(1); - doReturn(usageInfo).when(mController).getDataUsageInfo(any()); - - mController.updateState(mPreference); - - assertThat(mPreference.getSummary().toString()) - .contains("1.00 MB"); - } -} diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt new file mode 100644 index 00000000000..a9d343fa0b5 --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2023 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.network.telephony + +import android.content.Context +import android.content.Intent +import android.net.NetworkTemplate +import android.provider.Settings +import android.telephony.SubscriptionManager +import android.util.DataUnit +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.testing.TestLifecycleOwner +import androidx.preference.Preference +import androidx.preference.PreferenceScreen +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.dx.mockito.inline.extended.ExtendedMockito +import com.android.settings.core.BasePreferenceController.AVAILABLE +import com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE +import com.android.settings.datausage.DataUsageUtils +import com.android.settingslib.net.DataUsageController +import com.android.settingslib.net.DataUsageController.DataUsageInfo +import com.android.settingslib.spa.testutils.waitUntil +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.verify +import org.mockito.MockitoSession +import org.mockito.Spy +import org.mockito.quality.Strictness +import org.mockito.Mockito.`when` as whenever + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +class DataUsagePreferenceControllerTest { + + private lateinit var mockSession: MockitoSession + + @Spy + private val context: Context = ApplicationProvider.getApplicationContext() + + private lateinit var controller: DataUsagePreferenceController + + private val preference = Preference(context) + + @Mock + private lateinit var networkTemplate: NetworkTemplate + + @Mock + private lateinit var dataUsageController: DataUsageController + + @Mock + private lateinit var preferenceScreen: PreferenceScreen + + @Before + fun setUp() { + mockSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .mockStatic(SubscriptionManager::class.java) + .spyStatic(DataUsageUtils::class.java) + .strictness(Strictness.LENIENT) + .startMocking() + + whenever(SubscriptionManager.isValidSubscriptionId(SUB_ID)).thenReturn(true) + ExtendedMockito.doReturn(true).`when` { DataUsageUtils.hasMobileData(context) } + ExtendedMockito.doReturn(networkTemplate) + .`when` { DataUsageUtils.getMobileTemplate(context, SUB_ID) } + preference.key = TEST_KEY + whenever(preferenceScreen.findPreference(TEST_KEY)).thenReturn(preference) + + controller = + DataUsagePreferenceController(context, TEST_KEY).apply { + init(SUB_ID) + displayPreference(preferenceScreen) + dataUsageControllerFactory = { dataUsageController } + } + } + + @After + fun tearDown() { + mockSession.finishMocking() + } + + @Test + fun getAvailabilityStatus_validSubId_returnAvailable() { + assertThat(controller.availabilityStatus).isEqualTo(AVAILABLE) + } + + @Test + fun getAvailabilityStatus_invalidSubId_returnUnsearchable() { + controller.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID) + + assertThat(controller.availabilityStatus).isEqualTo(AVAILABLE_UNSEARCHABLE) + } + + @Test + fun handlePreferenceTreeClick_startActivity() = runTest { + val usageInfo = DataUsageInfo().apply { + usageLevel = DataUnit.MEBIBYTES.toBytes(1) + } + whenever(dataUsageController.getDataUsageInfo(networkTemplate)).thenReturn(usageInfo) + doNothing().`when`(context).startActivity(any()) + controller.whenViewCreated(TestLifecycleOwner(initialState = Lifecycle.State.STARTED)) + waitUntil { preference.summary != null } + + controller.handlePreferenceTreeClick(preference) + + val captor = ArgumentCaptor.forClass(Intent::class.java) + verify(context).startActivity(captor.capture()) + val intent = captor.value + assertThat(intent.action).isEqualTo(Settings.ACTION_MOBILE_DATA_USAGE) + assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID, 0)).isEqualTo(SUB_ID) + } + + @Test + fun updateState_invalidSubId_disabled() = runTest { + controller.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID) + + controller.whenViewCreated(TestLifecycleOwner(initialState = Lifecycle.State.STARTED)) + + waitUntil { !preference.isEnabled } + } + + @Test + fun updateState_noUsageData_shouldDisablePreference() = runTest { + val usageInfo = DataUsageInfo() + whenever(dataUsageController.getDataUsageInfo(networkTemplate)).thenReturn(usageInfo) + + controller.whenViewCreated(TestLifecycleOwner(initialState = Lifecycle.State.STARTED)) + + waitUntil { !preference.isEnabled } + } + + @Test + fun updateState_shouldUseIecUnit() = runTest { + val usageInfo = DataUsageInfo().apply { + usageLevel = DataUnit.MEBIBYTES.toBytes(1) + } + whenever(dataUsageController.getDataUsageInfo(networkTemplate)).thenReturn(usageInfo) + + controller.whenViewCreated(TestLifecycleOwner(initialState = Lifecycle.State.STARTED)) + + waitUntil { preference.summary?.contains("1.00 MB") == true } + } + + private companion object { + const val TEST_KEY = "test_key" + const val SUB_ID = 2 + } +}