diff --git a/res/layout/data_usage_spinner_item.xml b/res/layout/data_usage_spinner_item.xml new file mode 100644 index 00000000000..1706edfc508 --- /dev/null +++ b/res/layout/data_usage_spinner_item.xml @@ -0,0 +1,29 @@ + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index f68323a6763..567f255c2ae 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7998,7 +7998,7 @@ App modify system settings permission - Allow modify system settings + Allow modifying system settings This permission allows an app to modify system settings. diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java index 9c61873cb99..d4397dc1c13 100644 --- a/src/com/android/settings/dashboard/DashboardAdapter.java +++ b/src/com/android/settings/dashboard/DashboardAdapter.java @@ -31,7 +31,6 @@ import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -47,11 +46,9 @@ import com.android.settings.dashboard.DashboardData.SuggestionConditionHeaderDat import com.android.settings.dashboard.conditional.Condition; import com.android.settings.dashboard.conditional.ConditionAdapter; import com.android.settings.dashboard.suggestions.SuggestionAdapter; -import com.android.settings.dashboard.suggestions.SuggestionController; import com.android.settings.dashboard.suggestions.SuggestionControllerMixin; import com.android.settings.dashboard.suggestions.SuggestionDismissController; import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; -import com.android.settings.dashboard.suggestions.SuggestionLogHelper; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.Utils; import com.android.settingslib.drawer.DashboardCategory; @@ -164,24 +161,6 @@ public class DashboardAdapter extends RecyclerView.Adapter shownSuggestions = null; - final int mode = mDashboardData.getSuggestionConditionMode(); - if (mode == DashboardData.HEADER_MODE_DEFAULT) { - shownSuggestions = suggestions.subList(0, - Math.min(suggestions.size(), DashboardData.DEFAULT_SUGGESTION_COUNT)); - } else if (mode != DashboardData.HEADER_MODE_COLLAPSED) { - shownSuggestions = suggestions; - } - if (shownSuggestions != null) { - for (Tile suggestion : shownSuggestions) { - final String identifier = mSuggestionFeatureProvider.getSuggestionIdentifier( - mContext, suggestion); - mMetricsFeatureProvider.action( - mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, identifier, - getSuggestionTaggedData()); - mSuggestionsShownLogged.add(identifier); - } - } } public void setSuggestionsV2(List data) { @@ -191,7 +170,6 @@ public class DashboardAdapter extends RecyclerView.Adapter suggestions = mDashboardData.getSuggestions(); - if (suggestions == null) { - return; - } - for (Tile suggestion : suggestions) { - final String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier( - mContext, suggestion); - if (!mSuggestionsShownLogged.contains(suggestionId)) { - mMetricsFeatureProvider.action( - mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, suggestionId, - getSuggestionTaggedData()); - mSuggestionsShownLogged.add(suggestionId); - } - } - } - @VisibleForTesting void onBindSuggestionConditionHeader(final SuggestionAndConditionHeaderHolder holder, SuggestionConditionHeaderData data) { @@ -460,9 +405,7 @@ public class DashboardAdapter extends RecyclerView.Adapter { - if (moreSuggestions) { - logSuggestions(); - } else if (hasConditions) { + if (hasConditions) { mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true); } @@ -587,11 +530,6 @@ public class DashboardAdapter extends RecyclerView.Adapter[] getSuggestionTaggedData() { - return SuggestionLogHelper.getSuggestionTaggedData( - mSuggestionFeatureProvider.isSmartSuggestionEnabled(mContext)); - } - public static class IconCache { private final Context mContext; private final ArrayMap mMap = new ArrayMap<>(); diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java index 4810c7227b3..30a2fce8d7e 100644 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ b/src/com/android/settings/dashboard/DashboardSummary.java @@ -152,9 +152,6 @@ public class DashboardSummary extends InstrumentedFragment mMetricsFeatureProvider.hidden(getContext(), c.getMetricsConstant()); } } - if (!getActivity().isChangingConfigurations()) { - mAdapter.onPause(); - } } @Override diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java index 2a9463fe929..8502fa7f2cf 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java @@ -21,7 +21,6 @@ import android.service.settings.suggestions.Suggestion; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.Log; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -131,7 +130,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter if (!mSuggestionsShownLogged.contains(suggestionId)) { mMetricsFeatureProvider.action( mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, suggestionId, - getSuggestionTaggedData()); + mSuggestionFeatureProvider.getLoggingTaggedData(mContext)); mSuggestionsShownLogged.add(suggestionId); } if (suggestion.remoteViews != null) { @@ -165,7 +164,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter clickHandler.setOnClickListener(v -> { mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_SUGGESTION, suggestionId, - getSuggestionTaggedData()); + mSuggestionFeatureProvider.getLoggingTaggedData(mContext)); ((SettingsActivity) mContext).startSuggestion(suggestion.intent); }); } @@ -237,11 +236,6 @@ public class SuggestionAdapter extends RecyclerView.Adapter notifyDataSetChanged(); } - private Pair[] getSuggestionTaggedData() { - return SuggestionLogHelper.getSuggestionTaggedData( - mSuggestionFeatureProvider.isSmartSuggestionEnabled(mContext)); - } - public void removeSuggestion(Suggestion suggestion) { mSuggestionsV2.remove(suggestion); notifyDataSetChanged(); diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java index 0f8bccc660d..f9114011a0e 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.service.settings.suggestions.Suggestion; import android.support.annotation.NonNull; +import android.util.Pair; import com.android.settingslib.drawer.Tile; import com.android.settingslib.suggestions.SuggestionParser; @@ -93,6 +94,14 @@ public interface SuggestionFeatureProvider { /** * Returns an identifier for the suggestion + * + * @deprecated in favor or {@link Suggestion#getId()} */ + @Deprecated String getSuggestionIdentifier(Context context, Tile suggestion); + + /** + * Returns common tagged data for suggestion logging. + */ + Pair[] getLoggingTaggedData(Context context); } diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java index 02a9223fec6..783987dc8b0 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java @@ -170,8 +170,7 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider if (parser == null || suggestion == null || context == null) { return; } - final Pair[] taggedData = - SuggestionLogHelper.getSuggestionTaggedData(isSmartSuggestionEnabled(context)); + final Pair[] taggedData = getLoggingTaggedData(context); mMetricsFeatureProvider.action( context, MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION, @@ -213,6 +212,14 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider return packageName; } + @Override + public Pair[] getLoggingTaggedData(Context context) { + final boolean isSmartSuggestionEnabled = isSmartSuggestionEnabled(context); + return new Pair[]{Pair.create( + MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, + isSmartSuggestionEnabled ? 1 : 0)}; + } + @VisibleForTesting boolean hasUsedNightDisplay(Context context) { final ContentResolver cr = context.getContentResolver(); diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionLogHelper.java b/src/com/android/settings/dashboard/suggestions/SuggestionLogHelper.java deleted file mode 100644 index 339392fa780..00000000000 --- a/src/com/android/settings/dashboard/suggestions/SuggestionLogHelper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2017 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.dashboard.suggestions; - -import android.util.Pair; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; - -public class SuggestionLogHelper { - - public static Pair[] getSuggestionTaggedData(boolean enabled) { - return new Pair[]{ - Pair.create( - MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, enabled ? 1 : 0)}; - } -} diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java index d00749d837e..fb8119c60e4 100644 --- a/src/com/android/settings/datausage/BillingCycleSettings.java +++ b/src/com/android/settings/datausage/BillingCycleSettings.java @@ -264,7 +264,7 @@ public class BillingCycleSettings extends DataUsageBase implements formatter.getUnitDisplayName(MeasureUnit.GIGABYTE) }; final ArrayAdapter adapter = new ArrayAdapter( - getContext(), android.R.layout.simple_spinner_item, unitNames); + getContext(), R.layout.data_usage_spinner_item, unitNames); type.setAdapter(adapter); if (bytes > 1.5f * GB_IN_BYTES) { diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index a867330d040..8f61c52d897 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -280,7 +280,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new WifiRoamScansPreferenceController(context)); controllers.add(new MobileDataAlwaysOnPreferenceController(context)); controllers.add(new TetheringHardwareAccelPreferenceController(context)); - // select usb configuration + controllers.add(new SelectUsbConfigPreferenceController(context, lifecycle)); controllers.add(new BluetoothDeviceNoNamePreferenceController(context)); controllers.add(new BluetoothAbsoluteVolumePreferenceController(context)); controllers.add(new BluetoothInbandRingingPreferenceController(context)); diff --git a/src/com/android/settings/development/SelectUsbConfigPreferenceController.java b/src/com/android/settings/development/SelectUsbConfigPreferenceController.java new file mode 100644 index 00000000000..41fe6a3967e --- /dev/null +++ b/src/com/android/settings/development/SelectUsbConfigPreferenceController.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 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.development; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; + +import com.android.settings.R; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnCreate; +import com.android.settingslib.core.lifecycle.events.OnDestroy; + +public class SelectUsbConfigPreferenceController extends + DeveloperOptionsPreferenceController implements + Preference.OnPreferenceChangeListener, LifecycleObserver, OnCreate, OnDestroy { + + private static final String USB_CONFIGURATION_KEY = "select_usb_configuration"; + + private final String[] mListValues; + private final String[] mListSummaries; + private final UsbManager mUsbManager; + private BroadcastReceiver mUsbReceiver; + private ListPreference mPreference; + + public SelectUsbConfigPreferenceController(Context context, Lifecycle lifecycle) { + super(context); + + mListValues = context.getResources().getStringArray(R.array.usb_configuration_values); + mListSummaries = context.getResources().getStringArray(R.array.usb_configuration_titles); + mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); + mUsbReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mPreference != null) { + updateUsbConfigurationValues(); + } + } + }; + if (lifecycle != null) { + lifecycle.addObserver(this); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + IntentFilter filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_STATE); + mContext.registerReceiver(mUsbReceiver, filter); + } + + @Override + public String getPreferenceKey() { + return USB_CONFIGURATION_KEY; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mPreference = (ListPreference) screen.findPreference(getPreferenceKey()); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + writeUsbConfigurationOption(newValue.toString()); + updateUsbConfigurationValues(); + return true; + } + + @Override + public void updateState(Preference preference) { + updateUsbConfigurationValues(); + } + + @Override + public void onDestroy() { + mContext.unregisterReceiver(mUsbReceiver); + } + + @Override + protected void onDeveloperOptionsSwitchEnabled() { + mPreference.setEnabled(true); + } + + @Override + protected void onDeveloperOptionsSwitchDisabled() { + mPreference.setEnabled(false); + } + + @VisibleForTesting + void setCurrentFunction(String newValue, boolean usbDataUnlocked) { + mUsbManager.setCurrentFunction(newValue, usbDataUnlocked); + } + + private void updateUsbConfigurationValues() { + int index = 0; + for (int i = 0; i < mListValues.length; i++) { + if (mUsbManager.isFunctionEnabled(mListValues[i])) { + index = i; + break; + } + } + mPreference.setValue(mListValues[index]); + mPreference.setSummary(mListSummaries[index]); + } + + private void writeUsbConfigurationOption(String newValue) { + if (TextUtils.equals(newValue, "none")) { + setCurrentFunction(newValue, false); + } else { + setCurrentFunction(newValue, true); + } + } + +} diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java index 382c6921dbf..3791d89c8de 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java @@ -17,6 +17,7 @@ package com.android.settings.fuelgauge.anomaly; import android.content.Context; +import android.net.Uri; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; @@ -25,6 +26,10 @@ import android.util.Log; import com.android.settings.wrapper.KeyValueListParserWrapper; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + /** * Class to store the policy for anomaly detection, which comes from * {@link android.provider.Settings.Global} @@ -45,6 +50,8 @@ public class AnomalyDetectionPolicy { @VisibleForTesting static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold"; @VisibleForTesting + static final String KEY_WAKEUP_BLACKLISTED_TAGS = "wakeup_blacklisted_tags"; + @VisibleForTesting static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold"; /** @@ -95,6 +102,14 @@ public class AnomalyDetectionPolicy { */ public final long wakeupAlarmThreshold; + /** + * Array of blacklisted wakeups, by tag. + * + * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS + * @see #KEY_WAKEUP_BLACKLISTED_TAGS + */ + public final Set wakeupBlacklistedTags; + /** * Threshold for bluetooth unoptimized scanning time in milli seconds * @@ -121,15 +136,18 @@ public class AnomalyDetectionPolicy { Log.e(TAG, "Bad anomaly detection constants"); } - anomalyDetectionEnabled = mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, true); - wakeLockDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED, true); - wakeupAlarmDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED, - false); + anomalyDetectionEnabled = + mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, false); + wakeLockDetectionEnabled = + mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED,false); + wakeupAlarmDetectionEnabled = + mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,false); bluetoothScanDetectionEnabled = mParserWrapper.getBoolean( - KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true); + KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false); wakeLockThreshold = mParserWrapper.getLong(KEY_WAKELOCK_THRESHOLD, DateUtils.HOUR_IN_MILLIS); - wakeupAlarmThreshold = mParserWrapper.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 60); + wakeupAlarmThreshold = mParserWrapper.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 10); + wakeupBlacklistedTags = parseStringSet(KEY_WAKEUP_BLACKLISTED_TAGS, null); bluetoothScanThreshold = mParserWrapper.getLong(KEY_BLUETOOTH_SCAN_THRESHOLD, 30 * DateUtils.MINUTE_IN_MILLIS); } @@ -150,4 +168,14 @@ public class AnomalyDetectionPolicy { return false; // Disabled when no this type } } + + private Set parseStringSet(final String key, final Set defaultSet) { + final String value = mParserWrapper.getString(key, null); + if (value != null) { + return Arrays.stream(value.split(":")) + .map(String::trim).map(Uri::decode).collect(Collectors.toSet()); + } else { + return defaultSet; + } + } } diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java index 8823a177092..46f31ab3a8e 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java @@ -21,6 +21,8 @@ import android.os.BatteryStats; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Log; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -29,10 +31,12 @@ import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; import com.android.settings.fuelgauge.anomaly.AnomalyUtils; -import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; /** * Check whether apps has too many wakeup alarms @@ -42,6 +46,7 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { @VisibleForTesting BatteryUtils mBatteryUtils; private long mWakeupAlarmThreshold; + private Set mWakeupBlacklistedTags; private Context mContext; private AnomalyUtils mAnomalyUtils; @@ -56,6 +61,7 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { mBatteryUtils = BatteryUtils.getInstance(context); mAnomalyUtils = anomalyUtils; mWakeupAlarmThreshold = policy.wakeupAlarmThreshold; + mWakeupBlacklistedTags = policy.wakeupBlacklistedTags; } @Override @@ -123,11 +129,14 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { final BatteryStats.Uid.Pkg ps = packageStats.valueAt(ipkg); final ArrayMap alarms = ps.getWakeupAlarmStats(); - for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) { - int count = alarms.valueAt(iwa).getCountLocked(BatteryStats.STATS_SINCE_CHARGED); + for (Map.Entry alarm : alarms.entrySet()) { + if (mWakeupBlacklistedTags != null + && mWakeupBlacklistedTags.contains(alarm.getKey())) { + continue; + } + int count = alarm.getValue().getCountLocked(BatteryStats.STATS_SINCE_CHARGED); wakeups += count; } - } return wakeups; diff --git a/src/com/android/settings/wrapper/KeyValueListParserWrapper.java b/src/com/android/settings/wrapper/KeyValueListParserWrapper.java index 16dc50eecdc..3fab5711db0 100644 --- a/src/com/android/settings/wrapper/KeyValueListParserWrapper.java +++ b/src/com/android/settings/wrapper/KeyValueListParserWrapper.java @@ -56,12 +56,22 @@ public class KeyValueListParserWrapper { * Get the value for key as a boolean. * @param key The key to lookup. * @param defaultValue The value to return if the key was not found. - * @return the string value associated with the key. + * @return the boolean value associated with the key. */ public boolean getBoolean(String key, boolean defaultValue) { return mParser.getBoolean(key, defaultValue); } + /** + * Get the value for key as a string. + * @param key The key to lookup. + * @param defaultValue The value to return if the key was not found. + * @return the string value associated with the key. + */ + public String getString(String key, String defaultValue) { + return mParser.getString(key, defaultValue); + } + /** * Get the value for key as a long. * @param key The key to lookup. diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java index 595a9c6f739..14da5d6cd79 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java @@ -24,7 +24,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -39,12 +38,10 @@ import android.os.Bundle; import android.service.settings.suggestions.Suggestion; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.widget.RelativeLayout; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.TestConfig; @@ -61,8 +58,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; @@ -88,12 +83,6 @@ public class DashboardAdapterTest { private Condition mCondition; @Mock private Resources mResources; - @Captor - private ArgumentCaptor mActionCategoryCaptor = ArgumentCaptor.forClass(Integer.class); - @Captor - private ArgumentCaptor mActionPackageCaptor = ArgumentCaptor.forClass(String.class); - @Captor - private ArgumentCaptor mTaggedDataCaptor = ArgumentCaptor.forClass(Pair.class); private FakeFeatureFactory mFactory; private DashboardAdapter mDashboardAdapter; private DashboardAdapter.SuggestionAndConditionHeaderHolder mSuggestionHolder; @@ -110,7 +99,7 @@ public class DashboardAdapterTest { .getSuggestionIdentifier(any(Context.class), any(Tile.class))) .thenAnswer(invocation -> { final Object[] args = invocation.getArguments(); - return ((Tile)args[1]).intent.getComponent().getPackageName(); + return ((Tile) args[1]).intent.getComponent().getPackageName(); }); when(mContext.getResources()).thenReturn(mResources); @@ -125,282 +114,6 @@ public class DashboardAdapterTest { when(mView.getTag()).thenReturn(mCondition); } - @Test - public void testSuggestionsLogs_NotExpanded() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - verify(mFactory.metricsFeatureProvider, times(2)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly("pkg1", "pkg2"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_NotExpandedAndPaused() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(4)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg2", "pkg1", "pkg2"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_Expanded() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - - verify(mFactory.metricsFeatureProvider, times(3)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg2", "pkg3"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedAndPaused() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(6)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg2", "pkg3", "pkg1", "pkg2", "pkg3"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedAfterPause() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - mDashboardAdapter.onPause(); - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - - verify(mFactory.metricsFeatureProvider, times(7)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg2", "pkg1", "pkg2", "pkg1", "pkg2", "pkg3"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedAfterPauseAndPausedAgain() { - setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3")); - - mDashboardAdapter.onPause(); - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(10)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg2", "pkg1", "pkg2", "pkg1", "pkg2", "pkg3", "pkg1", "pkg2", "pkg3"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedWithLessThanDefaultShown() { - setupSuggestions(makeSuggestions("pkg1")); - - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - - verify(mFactory.metricsFeatureProvider, times(1)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly("pkg1"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAndPaused() { - setupSuggestions(makeSuggestions("pkg1")); - - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(2)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly("pkg1", "pkg1"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPause() { - setupSuggestions(makeSuggestions("pkg1")); - - mDashboardAdapter.onPause(); - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - - verify(mFactory.metricsFeatureProvider, times(3)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly("pkg1", "pkg1", "pkg1"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPauseAndPausedAgain() { - setupSuggestions(makeSuggestions("pkg1")); - mDashboardAdapter.onPause(); - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(4)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly( - "pkg1", "pkg1", "pkg1", "pkg1"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testSuggestionsLogs_SmartSuggestionEnabled() { - when(mFactory.suggestionsFeatureProvider - .isSmartSuggestionEnabled(any(Context.class))).thenReturn(true); - setupSuggestions(makeSuggestions("pkg1")); - - mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); - mSuggestionHolder.itemView.callOnClick(); - mDashboardAdapter.onPause(); - - verify(mFactory.metricsFeatureProvider, times(2)).action( - any(Context.class), mActionCategoryCaptor.capture(), - mActionPackageCaptor.capture(), - mTaggedDataCaptor.capture()); - assertThat(mActionCategoryCaptor.getAllValues()).containsExactly( - MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION); - assertThat(mActionPackageCaptor.getAllValues()).containsExactly("pkg1", "pkg1"); - assertThat(mTaggedDataCaptor.getAllValues()).containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 1), - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 1)); - } - @Test public void testSuggestionsLogs_nullSuggestionsList_shouldNotCrash() { setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3", "pkg4", "pkg5")); @@ -618,6 +331,10 @@ public class DashboardAdapterTest { verify(data).setAdapter(any(ConditionAdapter.class)); } + /** + * @deprecated in favor of {@link #makeSuggestionsV2(String...)} + */ + @Deprecated private List makeSuggestions(String... pkgNames) { final List suggestions = new ArrayList<>(); for (String pkgName : pkgNames) { diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java index d43a1692abf..825b388f018 100644 --- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java @@ -39,6 +39,7 @@ import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.TextView; +import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.TestConfig; @@ -66,7 +67,7 @@ public class SuggestionAdapterTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private SettingsActivity mActivity; - + private FakeFeatureFactory mFeatureFactory; private Context mContext; private SuggestionAdapter mSuggestionAdapter; private DashboardAdapter.DashboardItemHolder mSuggestionHolder; @@ -79,7 +80,7 @@ public class SuggestionAdapterTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - FakeFeatureFactory.setupForTest(mActivity); + mFeatureFactory = FakeFeatureFactory.setupForTest(mActivity); final Tile suggestion1 = new Tile(); final Tile suggestion2 = new Tile(); @@ -171,6 +172,24 @@ public class SuggestionAdapterTest { verify(view).setOnClickListener(any(View.OnClickListener.class)); } + @Test + public void onBindViewHolder_shouldLog() { + final View view = spy(LayoutInflater.from(mContext).inflate( + R.layout.suggestion_tile, new LinearLayout(mContext), true)); + mSuggestionHolder = new DashboardAdapter.DashboardItemHolder(view); + mSuggestionAdapter = new SuggestionAdapter(mContext, null /* suggestionV1*/, + mOneSuggestionV2, new ArrayList<>()); + + // Bind twice + mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); + mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); + + // Log once + verify(mFeatureFactory.metricsFeatureProvider).action( + mContext, MetricsProto.MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, + mOneSuggestionV2.get(0).getId()); + } + @Test public void onBindViewHolder_shouldInflateRemoteView() { List packages = makeSuggestions("pkg1"); diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java index 69b76fa8a31..5e567144a2e 100644 --- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java @@ -22,6 +22,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -313,4 +314,19 @@ public class SuggestionFeatureProviderImplTest { new ComponentName(mContext, NightDisplaySuggestionActivity.class); assertThat(mProvider.isSuggestionComplete(mContext, componentName)).isFalse(); } + + @Test + public void testGetSmartSuggestionEnabledTaggedData_disabled() { + assertThat(mProvider.getLoggingTaggedData(mContext)).asList().containsExactly( + Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); + } + + @Test + public void testGetSmartSuggestionEnabledTaggedData_enabled() { + final SuggestionFeatureProvider provider = spy(mProvider); + when(provider.isSmartSuggestionEnabled(any(Context.class))).thenReturn(true); + + assertThat(provider.getLoggingTaggedData(mContext)).asList().containsExactly( + Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 1)); + } } diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionLogHelperTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionLogHelperTest.java deleted file mode 100644 index 01d253f7fb3..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionLogHelperTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 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.dashboard.suggestions; - -import static com.google.common.truth.Truth.assertThat; - -import android.util.Pair; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.TestConfig; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SuggestionLogHelperTest { - - @Test - public void testGetSmartSuggestionEnabledTaggedData_disabled() { - assertThat(SuggestionLogHelper.getSuggestionTaggedData(false)).asList().containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0)); - } - - @Test - public void testGetSmartSuggestionEnabledTaggedData_enabled() { - assertThat(SuggestionLogHelper.getSuggestionTaggedData(true)).asList().containsExactly( - Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 1)); - } -} - diff --git a/tests/robotests/src/com/android/settings/development/SelectUsbConfigPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/SelectUsbConfigPreferenceControllerTest.java new file mode 100644 index 00000000000..8b96af0f7e9 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/SelectUsbConfigPreferenceControllerTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2017 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.development; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.hardware.usb.UsbManager; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class SelectUsbConfigPreferenceControllerTest { + + @Mock + private ListPreference mPreference; + @Mock + private PreferenceScreen mScreen; + @Mock + private UsbManager mUsbManager; + + private Context mContext; + private Lifecycle mLifecycle; + private SelectUsbConfigPreferenceController mController; + + /** + * Array Values Key + * + * 0: Charging + * 1: MTP + * 2: PTP + * 3: RNDIS + * 4: Audio Source + * 5: MIDI + */ + private String[] mValues; + private String[] mSummaries; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mLifecycle = new Lifecycle(); + mContext = spy(RuntimeEnvironment.application); + doReturn(mUsbManager).when(mContext).getSystemService(Context.USB_SERVICE); + mValues = mContext.getResources().getStringArray(R.array.usb_configuration_values); + mSummaries = mContext.getResources().getStringArray(R.array.usb_configuration_titles); + mController = spy(new SelectUsbConfigPreferenceController(mContext, mLifecycle)); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + mController.displayPreference(mScreen); + + } + + @Test + public void onPreferenceChange_setCharging_shouldEnableCharging() { + when(mUsbManager.isFunctionEnabled(mValues[0])).thenReturn(true); + doNothing().when(mController).setCurrentFunction(anyString(), anyBoolean()); + mController.onPreferenceChange(mPreference, mValues[0]); + + verify(mController).setCurrentFunction(mValues[0], false /* usb data unlock */); + } + + @Test + public void onPreferenceChange_setMtp_shouldEnableMtp() { + when(mUsbManager.isFunctionEnabled(mValues[1])).thenReturn(true); + doNothing().when(mController).setCurrentFunction(anyString(), anyBoolean()); + mController.onPreferenceChange(mPreference, mValues[1]); + + verify(mController).setCurrentFunction(mValues[1], true /* usb data unlock */); + } + + @Test + public void updateState_chargingEnabled_shouldSetPreferenceToCharging() { + when(mUsbManager.isFunctionEnabled(mValues[0])).thenReturn(true); + + mController.updateState(mPreference); + + verify(mPreference).setValue(mValues[0]); + verify(mPreference).setSummary(mSummaries[0]); + } + + @Test + public void updateState_RndisEnabled_shouldEnableRndis() { + when(mUsbManager.isFunctionEnabled(mValues[3])).thenReturn(true); + + mController.updateState(mPreference); + + verify(mPreference).setValue(mValues[3]); + verify(mPreference).setSummary(mSummaries[3]); + } + + @Test + public void updateState_noValueSet_shouldEnableChargingAsDefault() { + mController.updateState(mPreference); + + verify(mPreference).setValue(mValues[0]); + verify(mPreference).setSummary(mSummaries[0]); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() { + mController.onDeveloperOptionsSwitchDisabled(); + + verify(mPreference).setEnabled(false); + } + + @Test + public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() { + mController.onDeveloperOptionsSwitchEnabled(); + + verify(mPreference).setEnabled(true); + } + + @Test + public void onCreate_shouldRegisterReceiver() { + mLifecycle.onCreate(null /* bundle */); + + verify(mContext).registerReceiver(any(), any()); + } + + @Test + public void onDestroy_shouldUnregisterReceiver() { + doNothing().when(mContext).unregisterReceiver(any()); + mLifecycle.onDestroy(); + + verify(mContext).unregisterReceiver(any()); + } +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java index 9bbc9bd7be6..46db6b37f92 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java @@ -41,11 +41,13 @@ import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class AnomalyDetectionPolicyTest { - private static final String ANOMALY_DETECTION_CONSTANTS_VALUE = "anomaly_detection_enabled=true" + private static final String ANOMALY_DETECTION_CONSTANTS_VALUE = + "anomaly_detection_enabled=true" + ",wakelock_enabled=false" + ",wakelock_threshold=3000" + ",wakeup_alarm_enabled=true" + ",wakeup_alarm_threshold=100" + + ",wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon" + ",bluetooth_scan_enabled=true" + ",bluetooth_scan_threshold=2000"; private Context mContext; @@ -59,7 +61,7 @@ public class AnomalyDetectionPolicyTest { } @Test - public void testInit_containsDataFromSettings() { + public void testInit_usesConfigValues() { AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig(); assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isTrue(); @@ -67,12 +69,14 @@ public class AnomalyDetectionPolicyTest { assertThat(anomalyDetectionPolicy.wakeLockThreshold).isEqualTo(3000); assertThat(anomalyDetectionPolicy.wakeupAlarmDetectionEnabled).isTrue(); assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(100); + assertThat(anomalyDetectionPolicy.wakeupBlacklistedTags) + .containsExactly("tag1", "tag2", "with,comma", "with:colon"); assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isTrue(); assertThat(anomalyDetectionPolicy.bluetoothScanThreshold).isEqualTo(2000); } @Test - public void testInit_containsDefaultData() { + public void testInit_defaultValues() { Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ANOMALY_DETECTION_CONSTANTS, ""); // Mock it to avoid noSuchMethodError @@ -82,18 +86,19 @@ public class AnomalyDetectionPolicyTest { AnomalyDetectionPolicy anomalyDetectionPolicy = new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper); - assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isTrue(); - assertThat(anomalyDetectionPolicy.wakeLockDetectionEnabled).isTrue(); + assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isFalse(); + assertThat(anomalyDetectionPolicy.wakeLockDetectionEnabled).isFalse(); assertThat(anomalyDetectionPolicy.wakeLockThreshold).isEqualTo(DateUtils.HOUR_IN_MILLIS); assertThat(anomalyDetectionPolicy.wakeupAlarmDetectionEnabled).isFalse(); - assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(60); - assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isTrue(); + assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(10); + assertThat(anomalyDetectionPolicy.wakeupBlacklistedTags).isNull(); + assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isFalse(); assertThat(anomalyDetectionPolicy.bluetoothScanThreshold).isEqualTo( 30 * DateUtils.MINUTE_IN_MILLIS); } @Test - public void testIsAnomalyDetectorEnabled() { + public void testIsAnomalyDetectorEnabled_usesConfigValues() { AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig(); assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( @@ -104,18 +109,37 @@ public class AnomalyDetectionPolicyTest { Anomaly.AnomalyType.BLUETOOTH_SCAN)).isTrue(); } + @Test + public void testIsAnomalyDetectorEnabled_usesDefaultValues() { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.ANOMALY_DETECTION_CONSTANTS, ""); + // Mock it to avoid noSuchMethodError + doReturn(true).when(mKeyValueListParserWrapper).getBoolean(anyString(), eq(true)); + doReturn(false).when(mKeyValueListParserWrapper).getBoolean(anyString(), eq(false)); + + AnomalyDetectionPolicy anomalyDetectionPolicy = new AnomalyDetectionPolicy(mContext, + mKeyValueListParserWrapper); + + assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( + Anomaly.AnomalyType.WAKE_LOCK)).isFalse(); + assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( + Anomaly.AnomalyType.WAKEUP_ALARM)).isFalse(); + assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( + Anomaly.AnomalyType.BLUETOOTH_SCAN)).isFalse(); + } + private AnomalyDetectionPolicy createAnomalyPolicyWithConfig() { Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ANOMALY_DETECTION_CONSTANTS, ANOMALY_DETECTION_CONSTANTS_VALUE); // Mock it to avoid noSuchMethodError doReturn(true).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, true); + AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, false); doReturn(false).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, true); + AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, false); doReturn(true).when(mKeyValueListParserWrapper).getBoolean( AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, false); doReturn(true).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true); + AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false); return new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper); } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java index 55be734e232..13a5ab8531f 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java @@ -30,6 +30,7 @@ import android.os.BatteryStats; import android.os.Build; import android.text.format.DateUtils; import android.util.ArrayMap; +import android.util.ArraySet; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -52,6 +53,7 @@ import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; +import java.util.Set; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -69,6 +71,7 @@ public class WakeupAlarmAnomalyDetectorTest { 1 * DateUtils.HOUR_IN_MILLIS + 10 * DateUtils.MINUTE_IN_MILLIS; private static final int ANOMALY_WAKEUP_COUNT = 500; private static final int NORMAL_WAKEUP_COUNT = 61; + private static final int BLACKLISTED_WAKEUP_COUNT = 37; private static final int ANOMALY_WAKEUP_FREQUENCY = 428; // count per hour @Mock private BatteryStatsHelper mBatteryStatsHelper; @@ -87,12 +90,12 @@ public class WakeupAlarmAnomalyDetectorTest { @Mock private BatteryUtils mBatteryUtils; @Mock - private ApplicationInfo mApplicationInfo; - @Mock private BatteryStats.Uid.Pkg mPkg; @Mock private BatteryStats.Counter mCounter; @Mock + private BatteryStats.Counter mCounter2; + @Mock private AnomalyDetectionPolicy mPolicy; @Mock private AnomalyAction mAnomalyAction; @@ -111,6 +114,9 @@ public class WakeupAlarmAnomalyDetectorTest { mContext = spy(RuntimeEnvironment.application); ReflectionHelpers.setField(mPolicy, "wakeupAlarmThreshold", 60); + final Set blacklistedTags = new ArraySet<>(); + blacklistedTags.add("blacklistedTag"); + ReflectionHelpers.setField(mPolicy, "wakeupBlacklistedTags", blacklistedTags); doReturn(false).when(mBatteryUtils).shouldHideSipper(any()); doReturn(RUNNING_TIME_MS).when(mBatteryUtils).calculateRunningTimeBasedOnStatsType(any(), @@ -207,4 +213,20 @@ public class WakeupAlarmAnomalyDetectorTest { assertThat(mWakeupAlarmAnomalyDetector.getWakeupAlarmCountFromUid(mAnomalyUid)).isEqualTo( 2 * NORMAL_WAKEUP_COUNT); } + + @Test + public void testGetWakeupAlarmCountFromUid_filterOutBlacklistedTags() { + final ArrayMap packageStats = new ArrayMap<>(); + final ArrayMap alarms = new ArrayMap<>(); + doReturn(alarms).when(mPkg).getWakeupAlarmStats(); + doReturn(NORMAL_WAKEUP_COUNT).when(mCounter).getCountLocked(anyInt()); + doReturn(BLACKLISTED_WAKEUP_COUNT).when(mCounter2).getCountLocked(anyInt()); + doReturn(packageStats).when(mAnomalyUid).getPackageStats(); + packageStats.put("", mPkg); + alarms.put("allowedTag", mCounter); + alarms.put("blacklistedTag", mCounter2); + + assertThat(mWakeupAlarmAnomalyDetector.getWakeupAlarmCountFromUid(mAnomalyUid)).isEqualTo( + NORMAL_WAKEUP_COUNT); + } }