Snap for 4383207 from 88a2ed1954 to pi-release

Change-Id: I4ade6f30508148e3a9362f3cd3f4165c590d3d2b
This commit is contained in:
android-build-team Robot
2017-10-07 08:03:04 +00:00
21 changed files with 513 additions and 469 deletions

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<!-- Copied from frameworks/base/core/res/res/layout/simple_spinner_item.xml and modified
layout height and added padding. -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:ellipsize="marquee"
android:textAlignment="inherit"
android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"/>

View File

@@ -7998,7 +7998,7 @@
<!-- Link to the apps page for WRITE_SETTINGS settings [CHAR LIMIT=52] -->
<string name="write_settings_preference">App modify system settings permission</string>
<!-- Label for setting which controls whether app can write system settings [CHAR LIMIT=45] -->
<string name="permit_write_settings">Allow modify system settings</string>
<string name="permit_write_settings">Allow modifying system settings</string>
<!-- Description of the write system settings [CHAR LIMIT=NONE] -->
<string name="write_settings_description">This permission allows an app to modify system settings.</string>
<!-- Summary of app allowed to write system settings [CHAR LIMIT=45] -->

View File

@@ -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<DashboardAdapter.Dash
.setCategory(category)
.build();
notifyDashboardDataChanged(prevData);
List<Tile> 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<Suggestion> data) {
@@ -191,7 +170,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
.setSuggestionsV2(data)
.build();
notifyDashboardDataChanged(prevData);
// TODO: Replicate the metrics logging from setCategoriesAndSuggestions()
}
public void setCategory(DashboardCategory category) {
@@ -331,22 +309,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
mRecyclerView = recyclerView;
}
public void onPause() {
if (mDashboardData.getSuggestions() == null) {
return;
}
for (Tile suggestion : mDashboardData.getSuggestions()) {
String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier(
mContext, suggestion);
if (mSuggestionsShownLogged.contains(suggestionId)) {
mMetricsFeatureProvider.action(
mContext, MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, suggestionId,
getSuggestionTaggedData());
}
}
mSuggestionsShownLogged.clear();
}
public Object getItem(long itemId) {
return mDashboardData.getItemEntityById(itemId);
}
@@ -375,23 +337,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
}
}
private void logSuggestions() {
final List<Tile> 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<DashboardAdapter.Dash
holder.itemView.setPadding(0, padding, 0, padding);
holder.itemView.setOnClickListener(v -> {
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<DashboardAdapter.Dash
parent.setVisibility(View.VISIBLE);
}
private Pair<Integer, Object>[] getSuggestionTaggedData() {
return SuggestionLogHelper.getSuggestionTaggedData(
mSuggestionFeatureProvider.isSmartSuggestionEnabled(mContext));
}
public static class IconCache {
private final Context mContext;
private final ArrayMap<Icon, Drawable> mMap = new ArrayMap<>();

View File

@@ -152,9 +152,6 @@ public class DashboardSummary extends InstrumentedFragment
mMetricsFeatureProvider.hidden(getContext(), c.getMetricsConstant());
}
}
if (!getActivity().isChangingConfigurations()) {
mAdapter.onPause();
}
}
@Override

View File

@@ -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<DashboardItemHolder>
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<DashboardItemHolder>
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<DashboardItemHolder>
notifyDataSetChanged();
}
private Pair<Integer, Object>[] getSuggestionTaggedData() {
return SuggestionLogHelper.getSuggestionTaggedData(
mSuggestionFeatureProvider.isSmartSuggestionEnabled(mContext));
}
public void removeSuggestion(Suggestion suggestion) {
mSuggestionsV2.remove(suggestion);
notifyDataSetChanged();

View File

@@ -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<Integer, Object>[] getLoggingTaggedData(Context context);
}

View File

@@ -170,8 +170,7 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
if (parser == null || suggestion == null || context == null) {
return;
}
final Pair<Integer, Object>[] taggedData =
SuggestionLogHelper.getSuggestionTaggedData(isSmartSuggestionEnabled(context));
final Pair<Integer, Object>[] 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<Integer, Object>[] 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();

View File

@@ -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<Integer, Object>[] getSuggestionTaggedData(boolean enabled) {
return new Pair[]{
Pair.create(
MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, enabled ? 1 : 0)};
}
}

View File

@@ -264,7 +264,7 @@ public class BillingCycleSettings extends DataUsageBase implements
formatter.getUnitDisplayName(MeasureUnit.GIGABYTE)
};
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
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) {

View File

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

View File

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

View File

@@ -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<String> 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<String> parseStringSet(final String key, final Set<String> 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;
}
}
}

View File

@@ -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<String> 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<String, ? extends BatteryStats.Counter> 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<String, ? extends BatteryStats.Counter> alarm : alarms.entrySet()) {
if (mWakeupBlacklistedTags != null
&& mWakeupBlacklistedTags.contains(alarm.getKey())) {
continue;
}
int count = alarm.getValue().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
wakeups += count;
}
}
return wakeups;

View File

@@ -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.

View File

@@ -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<Integer> mActionCategoryCaptor = ArgumentCaptor.forClass(Integer.class);
@Captor
private ArgumentCaptor<String> mActionPackageCaptor = ArgumentCaptor.forClass(String.class);
@Captor
private ArgumentCaptor<Pair> 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<Tile> makeSuggestions(String... pkgNames) {
final List<Tile> suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {

View File

@@ -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<Tile> packages = makeSuggestions("pkg1");

View File

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

View File

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

View File

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

View File

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

View File

@@ -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<String> 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<String, BatteryStats.Uid.Pkg> packageStats = new ArrayMap<>();
final ArrayMap<String, BatteryStats.Counter> 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);
}
}