Merge "Remove some dashboard alias"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f2898d..8673359 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3013,6 +3013,10 @@
<string name="sms_change_default_dialog_text" translatable="true">Use <xliff:g id="new_app">%1$s</xliff:g> instead of <xliff:g id="current_app">%2$s</xliff:g> as your SMS app?</string>
<string name="sms_change_default_no_previous_dialog_text" translatable="true">Use <xliff:g id="new_app">%s</xliff:g> as your SMS app?</string>
+ <!-- Network Scorer Picker title [CHAR LIMIT=40]-->
+ <string name="network_scorer_picker_title">Network Scorer</string>
+ <string name="network_scorer_picker_none_preference">None</string>
+
<!-- Wifi Assistant change wi-fi assistant title. [CHAR LIMIT=40] -->
<string name="network_scorer_change_active_dialog_title">Change Wi\u2011Fi assistant?</string>
<!-- Wifi Assistant request message. This message asks the user if it is okay for an app to become the Wifi Assistant instead of the current Wifi Assistant app. [CHAR LIMIT=100] -->
diff --git a/res/xml/network_scorer_picker_prefs.xml b/res/xml/network_scorer_picker_prefs.xml
new file mode 100644
index 0000000..fab69e7
--- /dev/null
+++ b/res/xml/network_scorer_picker_prefs.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/network_scorer_picker_title">
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index bf1dc75..8e51009 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -59,6 +59,11 @@
settings:keywords="@string/keywords_wifi_calling"/>
<Preference
+ android:key="network_scorer_picker"
+ android:title="@string/network_scorer_picker_title"
+ android:fragment="com.android.settings.network.NetworkScorerPicker"/>
+
+ <Preference
android:key="wifi_direct"
android:title="@string/wifi_menu_p2p">
<intent android:targetPackage="com.android.settings"
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index a5efcc1..6c23b39 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -21,6 +21,7 @@
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.overlay.FeatureFactory;
@@ -111,13 +112,17 @@
return;
}
// Pref key exists in set, log it's change in metrics.
- mMetricsFeature.count(mContext, prefKey + "|" + value, 1);
+ mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
+ Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
+ Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE, value));
}
private void logPackageName(String key, String value) {
- mMetricsFeature.count(mContext, mTag + "/" + key, 1);
+ final String prefKey = mTag + "/" + key;
+ mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
+ Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
mMetricsFeature.action(mContext, MetricsEvent.ACTION_GENERIC_PACKAGE,
- mTag + "/" + key + "|" + value);
+ prefKey + "|" + value);
}
private void safeLogValue(String key, String value) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index fc96340..f18ae65 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -59,7 +59,8 @@
UsageType.BLUETOOTH,
UsageType.USER,
UsageType.IDLE,
- UsageType.APP};
+ UsageType.APP,
+ UsageType.UNACCOUNTED};
private BatteryHistoryPreference mHistPref;
private PreferenceGroup mUsageListGroup;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
@@ -114,7 +115,7 @@
mUsageListGroup.removeAll();
for (int i = 0, size = dataList.size(); i < size; i++) {
final PowerUsageData batteryData = dataList.get(i);
- final PowerGaugePreference pref = new PowerGaugePreference(getContext());
+ final PowerGaugePreference pref = new PowerGaugePreference(getPrefContext());
pref.setTitle(batteryData.titleResId);
pref.setSummary(batteryData.summary);
@@ -139,6 +140,8 @@
return UsageType.USER;
} else if (drainType == DrainType.CELL) {
return UsageType.CELL;
+ } else if (drainType == DrainType.UNACCOUNTED) {
+ return UsageType.UNACCOUNTED;
} else if (mPowerUsageFeatureProvider.isTypeSystem(sipper)) {
return UsageType.SYSTEM;
} else if (mPowerUsageFeatureProvider.isTypeService(sipper)) {
@@ -200,7 +203,8 @@
UsageType.SYSTEM,
UsageType.BLUETOOTH,
UsageType.USER,
- UsageType.IDLE})
+ UsageType.IDLE,
+ UsageType.UNACCOUNTED})
public @interface UsageType {
int APP = 0;
int WIFI = 1;
@@ -210,6 +214,7 @@
int BLUETOOTH = 5;
int USER = 6;
int IDLE = 7;
+ int UNACCOUNTED = 8;
}
@StringRes
@@ -249,6 +254,8 @@
return R.string.power_user;
case UsageType.IDLE:
return R.string.power_idle;
+ case UsageType.UNACCOUNTED:
+ return R.string.power_unaccounted;
case UsageType.APP:
default:
return R.string.power_apps;
diff --git a/src/com/android/settings/network/NetworkScoreManagerWrapper.java b/src/com/android/settings/network/NetworkScoreManagerWrapper.java
new file mode 100644
index 0000000..0d35378
--- /dev/null
+++ b/src/com/android/settings/network/NetworkScoreManagerWrapper.java
@@ -0,0 +1,73 @@
+/*
+ * 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.network;
+
+import android.annotation.Nullable;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+
+import java.util.List;
+
+/**
+ * Wrapper around {@link NetworkScoreManager} to facilitate unit testing.
+ *
+ * TODO: delete this class once robolectric supports Android O
+ */
+public class NetworkScoreManagerWrapper {
+ private final NetworkScoreManager mNetworkScoreManager;
+
+ public NetworkScoreManagerWrapper(NetworkScoreManager networkScoreManager) {
+ mNetworkScoreManager = networkScoreManager;
+ }
+
+ /**
+ * Returns the list of available scorer apps. The list will be empty if there are
+ * no valid scorers.
+ */
+ public List<NetworkScorerAppData> getAllValidScorers() {
+ return mNetworkScoreManager.getAllValidScorers();
+ }
+
+ /**
+ * Obtain the package name of the current active network scorer.
+ *
+ * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
+ * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
+ * determine the current scorer and offer the user the ability to select a different scorer via
+ * the {@link #ACTION_CHANGE_ACTIVE} intent.
+ * @return the full package name of the current active scorer, or null if there is no active
+ * scorer.
+ */
+ @Nullable
+ public String getActiveScorerPackage() {
+ return mNetworkScoreManager.getActiveScorerPackage();
+ }
+
+
+ /**
+ * Set the active scorer to a new package and clear existing scores.
+ *
+ * <p>Should never be called directly without obtaining user consent. This can be done by using
+ * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
+ *
+ * @return true if the operation succeeded, or false if the new package is not a valid scorer.
+ * @throws SecurityException if the caller is not a system process or does not hold the
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission
+ */
+ public boolean setActiveScorer(String packageName) throws SecurityException {
+ return mNetworkScoreManager.setActiveScorer(packageName);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/NetworkScorerPicker.java b/src/com/android/settings/network/NetworkScorerPicker.java
new file mode 100644
index 0000000..da9d84f
--- /dev/null
+++ b/src/com/android/settings/network/NetworkScorerPicker.java
@@ -0,0 +1,135 @@
+/*
+ * 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.network;
+
+import android.content.Context;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.os.Bundle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.settings.R;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.instrumentation.Instrumentable;
+import com.android.settings.widget.RadioButtonPreference;
+
+import java.util.List;
+
+/**
+ * Fragment for choosing default network scorer.
+ */
+public class NetworkScorerPicker extends InstrumentedPreferenceFragment implements
+ RadioButtonPreference.OnClickListener {
+
+ private NetworkScoreManagerWrapper mNetworkScoreManager;
+
+ @Override
+ public int getMetricsCategory() {
+ //TODO(35854268): Add logging.
+ return Instrumentable.METRICS_CATEGORY_UNKNOWN;
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ super.onCreatePreferences(savedInstanceState, rootKey);
+ addPreferencesFromResource(R.xml.network_scorer_picker_prefs);
+ updateCandidates();
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mNetworkScoreManager = createNetworkScorerManagerWrapper(context);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = super.onCreateView(inflater, container, savedInstanceState);
+ // this is needed so the back button goes back to previous fragment
+ setHasOptionsMenu(true);
+ return view;
+ }
+
+ @VisibleForTesting
+ public void updateCandidates() {
+ final PreferenceScreen screen = getPreferenceScreen();
+ screen.removeAll();
+
+ final List<NetworkScorerAppData> scorers = mNetworkScoreManager.getAllValidScorers();
+ if (scorers.isEmpty()) {
+ final RadioButtonPreference nonePref = new RadioButtonPreference(getPrefContext());
+ nonePref.setTitle(R.string.network_scorer_picker_none_preference);
+ nonePref.setChecked(true);
+ screen.addPreference(nonePref);
+ return;
+ }
+ final String defaultAppKey = getActiveScorerPackage();
+ final int numScorers = scorers.size();
+ for (int i = 0; i < numScorers; i++) {
+ final RadioButtonPreference pref = new RadioButtonPreference(getPrefContext());
+ final NetworkScorerAppData appData = scorers.get(i);
+ final String appKey = appData.getRecommendationServicePackageName();
+ pref.setTitle(appData.getRecommendationServiceLabel());
+ pref.setKey(appKey);
+ pref.setChecked(TextUtils.equals(defaultAppKey, appKey));
+ pref.setOnClickListener(this);
+ screen.addPreference(pref);
+ }
+ }
+
+ private String getActiveScorerPackage() {
+ return mNetworkScoreManager.getActiveScorerPackage();
+ }
+
+ private boolean setActiveScorer(String key) {
+ if (!TextUtils.equals(key, getActiveScorerPackage())) {
+ return mNetworkScoreManager.setActiveScorer(key);
+ }
+ return false;
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference selected) {
+ final String selectedKey = selected.getKey();
+ final boolean success = setActiveScorer(selectedKey);
+ if (success) {
+ updateCheckedState(selectedKey);
+ }
+ }
+
+ private void updateCheckedState(String selectedKey) {
+ final PreferenceScreen screen = getPreferenceScreen();
+ final int count = screen.getPreferenceCount();
+ for (int i = 0; i < count; i++) {
+ final Preference pref = screen.getPreference(i);
+ if (pref instanceof RadioButtonPreference) {
+ final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
+ radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
+ }
+ }
+ }
+
+ @VisibleForTesting
+ NetworkScoreManagerWrapper createNetworkScorerManagerWrapper(Context context) {
+ return new NetworkScoreManagerWrapper(context.getSystemService(NetworkScoreManager.class));
+ }
+}
diff --git a/tests/robotests/src/android/net/NetworkScorerAppData.java b/tests/robotests/src/android/net/NetworkScorerAppData.java
new file mode 100644
index 0000000..1eaa8a7
--- /dev/null
+++ b/tests/robotests/src/android/net/NetworkScorerAppData.java
@@ -0,0 +1,112 @@
+package android.net;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Holds metadata about a discovered network scorer/recommendation application.
+ *
+ * TODO: delete this class once robolectric supports Android O
+ */
+public final class NetworkScorerAppData implements Parcelable {
+ /** UID of the scorer app. */
+ public final int packageUid;
+ private final ComponentName mRecommendationService;
+ /** User visible label in Settings for the recommendation service. */
+ private final String mRecommendationServiceLabel;
+ /**
+ * The {@link ComponentName} of the Activity to start before enabling the "connect to open
+ * wifi networks automatically" feature.
+ */
+ private final ComponentName mEnableUseOpenWifiActivity;
+
+ public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
+ String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity) {
+ this.packageUid = packageUid;
+ this.mRecommendationService = recommendationServiceComp;
+ this.mRecommendationServiceLabel = recommendationServiceLabel;
+ this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+ }
+
+ protected NetworkScorerAppData(Parcel in) {
+ packageUid = in.readInt();
+ mRecommendationService = ComponentName.readFromParcel(in);
+ mRecommendationServiceLabel = in.readString();
+ mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(packageUid);
+ ComponentName.writeToParcel(mRecommendationService, dest);
+ dest.writeString(mRecommendationServiceLabel);
+ ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<NetworkScorerAppData> CREATOR =
+ new Creator<NetworkScorerAppData>() {
+ @Override
+ public NetworkScorerAppData createFromParcel(Parcel in) {
+ return new NetworkScorerAppData(in);
+ }
+
+ @Override
+ public NetworkScorerAppData[] newArray(int size) {
+ return new NetworkScorerAppData[size];
+ }
+ };
+
+ public String getRecommendationServicePackageName() {
+ return mRecommendationService.getPackageName();
+ }
+
+ public ComponentName getRecommendationServiceComponent() {
+ return mRecommendationService;
+ }
+
+ @Nullable
+ public ComponentName getEnableUseOpenWifiActivity() {
+ return mEnableUseOpenWifiActivity;
+ }
+
+ @Nullable
+ public String getRecommendationServiceLabel() {
+ return mRecommendationServiceLabel;
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkScorerAppData{" +
+ "packageUid=" + packageUid +
+ ", mRecommendationService=" + mRecommendationService +
+ ", mRecommendationServiceLabel=" + mRecommendationServiceLabel +
+ ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkScorerAppData that = (NetworkScorerAppData) o;
+ return packageUid == that.packageUid &&
+ Objects.equals(mRecommendationService, that.mRecommendationService) &&
+ Objects.equals(mRecommendationServiceLabel, that.mRecommendationServiceLabel) &&
+ Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageUid, mRecommendationService, mRecommendationServiceLabel,
+ mEnableUseOpenWifiActivity);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
index eeaa175..763d6e3 100644
--- a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.util.Pair;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@@ -32,7 +33,6 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -71,7 +71,8 @@
editor.putInt(TEST_KEY, 2);
editor.putInt(TEST_KEY, 2);
- verify(mMetricsFeature, times(6)).count(any(Context.class), anyString(), anyInt());
+ verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
+ any(Pair.class), any(Pair.class));
}
@Test
@@ -83,7 +84,8 @@
editor.putBoolean(TEST_KEY, false);
editor.putBoolean(TEST_KEY, false);
- verify(mMetricsFeature, times(4)).count(any(Context.class), anyString(), anyInt());
+ verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
+ any(Pair.class), any(Pair.class));
}
@Test
@@ -95,7 +97,8 @@
editor.putLong(TEST_KEY, 1);
editor.putLong(TEST_KEY, 2);
- verify(mMetricsFeature, times(4)).count(any(Context.class), anyString(), anyInt());
+ verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
+ any(Pair.class), any(Pair.class));
}
@Test
@@ -107,7 +110,8 @@
editor.putFloat(TEST_KEY, 1);
editor.putFloat(TEST_KEY, 2);
- verify(mMetricsFeature, times(4)).count(any(Context.class), anyString(), anyInt());
+ verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
+ any(Pair.class), any(Pair.class));
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
index ed7e48b..494ac67 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -94,9 +94,9 @@
@Test
public void testExtractUsageType_TypeEqualsToDrainType_ReturnRelevantType() {
final DrainType drainTypes[] = {DrainType.WIFI, DrainType.BLUETOOTH, DrainType.IDLE,
- DrainType.USER, DrainType.CELL};
+ DrainType.USER, DrainType.CELL, DrainType.UNACCOUNTED};
final int usageTypes[] = {UsageType.WIFI, UsageType.BLUETOOTH, UsageType.IDLE,
- UsageType.USER, UsageType.CELL};
+ UsageType.USER, UsageType.CELL, UsageType.UNACCOUNTED};
assertThat(drainTypes.length).isEqualTo(usageTypes.length);
for (int i = 0, size = drainTypes.length; i < size; i++) {
@@ -147,7 +147,7 @@
assertThat(usageTypeSet).asList().containsExactly(UsageType.APP, UsageType.WIFI,
UsageType.CELL, UsageType.BLUETOOTH, UsageType.IDLE, UsageType.SERVICE,
- UsageType.USER, UsageType.SYSTEM);
+ UsageType.USER, UsageType.SYSTEM, UsageType.UNACCOUNTED);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
new file mode 100644
index 0000000..fef6f85
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.NetworkScorerAppData;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.widget.RadioButtonPreference;
+import com.google.android.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class NetworkScorerPickerTest {
+
+ private static final String TEST_SCORER_PACKAGE_1 = "Test Package 1";
+ private static final String TEST_SCORER_CLASS_1 = "Test Class 1";
+ private static final String TEST_SCORER_LABEL_1 = "Test Label 1";
+ private static final String TEST_SCORER_PACKAGE_2 = "Test Package 2";
+
+ private Context mContext;
+ @Mock
+ private NetworkScoreManagerWrapper mNetworkScoreManager;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private TestFragment mFragment;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mFragment = new TestFragment(mContext, mPreferenceScreen, mNetworkScoreManager);
+ mFragment.onAttach(mContext);
+ }
+
+ @Test
+ public void testOnRadioButtonClicked_success() {
+ RadioButtonPreference pref = new RadioButtonPreference(mContext);
+ pref.setKey(TEST_SCORER_PACKAGE_1);
+ when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
+ when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
+ when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
+ when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_2);
+
+ mFragment.onRadioButtonClicked(pref);
+
+ verify(mNetworkScoreManager).setActiveScorer(TEST_SCORER_PACKAGE_1);
+ assertThat(pref.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testOnRadioButtonClicked_currentScorer_doNothing() {
+ RadioButtonPreference pref = new RadioButtonPreference(mContext);
+ pref.setKey(TEST_SCORER_PACKAGE_1);
+ pref.setChecked(true);
+ when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
+ when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
+ when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
+ when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
+
+ mFragment.onRadioButtonClicked(pref);
+
+ verify(mNetworkScoreManager, never()).setActiveScorer(any());
+ assertThat(pref.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateCandidates_noValidScorers_nonePreference() {
+ when(mNetworkScoreManager.getAllValidScorers()).thenReturn(new ArrayList<>());
+ ArgumentCaptor<RadioButtonPreference> arg =
+ ArgumentCaptor.forClass(RadioButtonPreference.class);
+
+ mFragment.updateCandidates();
+
+ verify(mPreferenceScreen).addPreference(arg.capture());
+ assertThat(arg.getValue().getTitle()).isEqualTo(
+ mContext.getString(R.string.network_scorer_picker_none_preference));
+ }
+
+ @Test
+ public void testUpdateCandidates_validScorer() {
+ ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
+ NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
+ 0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */);
+ when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
+ Lists.newArrayList(scorerAppData));
+ when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
+ ArgumentCaptor<RadioButtonPreference> arg =
+ ArgumentCaptor.forClass(RadioButtonPreference.class);
+
+ mFragment.updateCandidates();
+
+ verify(mPreferenceScreen).addPreference(arg.capture());
+ RadioButtonPreference pref = arg.getValue();
+ assertThat(pref.getTitle()).isEqualTo(TEST_SCORER_LABEL_1);
+ assertThat(pref.isChecked()).isTrue();
+ }
+
+ public static class TestFragment extends NetworkScorerPicker {
+
+ private final Context mContext;
+ private final PreferenceScreen mScreen;
+ private final PreferenceManager mPrefManager;
+ private final NetworkScoreManagerWrapper mNetworkScoreManagerWrapper;
+
+ public TestFragment(Context context, PreferenceScreen preferenceScreen,
+ NetworkScoreManagerWrapper networkScoreManagerWrapper) {
+ mContext = context;
+ mScreen = preferenceScreen;
+ mNetworkScoreManagerWrapper = networkScoreManagerWrapper;
+ mPrefManager = mock(PreferenceManager.class);
+ when(mPrefManager.getContext()).thenReturn(context);
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public PreferenceManager getPreferenceManager() {
+ return mPrefManager;
+ }
+
+ @Override
+ public PreferenceScreen getPreferenceScreen() {
+ return mScreen;
+ }
+
+ @Override
+ NetworkScoreManagerWrapper createNetworkScorerManagerWrapper(Context context) {
+ return mNetworkScoreManagerWrapper;
+ }
+ }
+}