Bind to the recommendation service specified in the Setting.
High level changes to NetworkScorerAppManager:
* Implemented getAllValidScorers() and removed the old
config-based discovery code.
* Implemented setActiveScorer() to persist its given package
name to Settings if it represents a valid network
recommendation app.
* Added a new method that reverts the setting back to the
configured default if the current setting represents an
invalid app.
High level changes to NetworkScoreService:
* Updated the PackageMonitor to only watch a single package.
* Moved most of the startup logic to onUserUnlocked() so we
don't have to worry about whether or not the device is encrypted
when querying the PackageManager.
* The PackageMonitor is only registered/unregistered when the
package it's watching changes.
Test: runtest frameworks-services -c com.android.server.NetworkScorerAppManagerTest
Test: runtest frameworks-services -c com.android.server.NetworkScoreServiceTest
Bug: 35095406
Change-Id: Ib32aca72dac4b831a64ceb3cd5c31e8fa2f61396
This commit is contained in:
@@ -131,10 +131,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
* manages the service connection.
|
||||
*/
|
||||
private class NetworkScorerPackageMonitor extends PackageMonitor {
|
||||
final List<String> mPackagesToWatch;
|
||||
final String mPackageToWatch;
|
||||
|
||||
private NetworkScorerPackageMonitor(List<String> packagesToWatch) {
|
||||
mPackagesToWatch = packagesToWatch;
|
||||
private NetworkScorerPackageMonitor(String packageToWatch) {
|
||||
mPackageToWatch = packageToWatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,37 +167,27 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
evaluateBinding(packageName, true /* forceUnbind */);
|
||||
}
|
||||
|
||||
private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
|
||||
if (!mPackagesToWatch.contains(scorerPackageName)) {
|
||||
private void evaluateBinding(String changedPackageName, boolean forceUnbind) {
|
||||
if (!mPackageToWatch.equals(changedPackageName)) {
|
||||
// Early exit when we don't care about the package that has changed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Evaluating binding for: " + scorerPackageName
|
||||
Log.d(TAG, "Evaluating binding for: " + changedPackageName
|
||||
+ ", forceUnbind=" + forceUnbind);
|
||||
}
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
if (activeScorer == null) {
|
||||
// Package change has invalidated a scorer, this will also unbind any service
|
||||
// connection.
|
||||
if (DBG) Log.d(TAG, "No active scorers available.");
|
||||
unbindFromScoringServiceIfNeeded();
|
||||
} else if (activeScorer.getRecommendationServicePackageName().equals(scorerPackageName))
|
||||
{
|
||||
// The active scoring service changed in some way.
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Possible change to the active scorer: "
|
||||
+ activeScorer.getRecommendationServicePackageName());
|
||||
}
|
||||
refreshBinding();
|
||||
} else { // The scoring service changed in some way.
|
||||
if (forceUnbind) {
|
||||
unbindFromScoringServiceIfNeeded();
|
||||
}
|
||||
bindToScoringServiceIfNeeded(activeScorer);
|
||||
} else {
|
||||
// One of the scoring apps on the device has changed and we may no longer be
|
||||
// bound to the correct scoring app. The logic in bindToScoringServiceIfNeeded()
|
||||
// will sort that out to leave us bound to the most recent active scorer.
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Binding to " + activeScorer.getRecommendationServiceComponent()
|
||||
+ " if needed.");
|
||||
@@ -271,60 +261,71 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
/** Called when the system is ready to run third-party code but before it actually does so. */
|
||||
void systemReady() {
|
||||
if (DBG) Log.d(TAG, "systemReady");
|
||||
registerPackageMonitorIfNeeded();
|
||||
registerRecommendationSettingsObserver();
|
||||
refreshRecommendationRequestTimeoutMs();
|
||||
}
|
||||
|
||||
/** Called when the system is ready for us to start third-party code. */
|
||||
void systemRunning() {
|
||||
if (DBG) Log.d(TAG, "systemRunning");
|
||||
bindToScoringServiceIfNeeded();
|
||||
}
|
||||
|
||||
private void onUserUnlocked(int userId) {
|
||||
@VisibleForTesting
|
||||
void onUserUnlocked(int userId) {
|
||||
if (DBG) Log.d(TAG, "onUserUnlocked(" + userId + ")");
|
||||
refreshBinding();
|
||||
}
|
||||
|
||||
private void refreshBinding() {
|
||||
if (DBG) Log.d(TAG, "refreshBinding()");
|
||||
// Apply the default package name if the Setting isn't set.
|
||||
mNetworkScorerAppManager.revertToDefaultIfNoActive();
|
||||
registerPackageMonitorIfNeeded();
|
||||
bindToScoringServiceIfNeeded();
|
||||
}
|
||||
|
||||
private void registerRecommendationSettingsObserver() {
|
||||
final List<String> providerPackages =
|
||||
mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
|
||||
if (!providerPackages.isEmpty()) {
|
||||
final Uri enabledUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
|
||||
mContentObserver.observe(enabledUri,
|
||||
ServiceHandler.MSG_RECOMMENDATIONS_ENABLED_CHANGED);
|
||||
}
|
||||
final Uri packageNameUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_PACKAGE);
|
||||
mContentObserver.observe(packageNameUri,
|
||||
ServiceHandler.MSG_RECOMMENDATIONS_PACKAGE_CHANGED);
|
||||
|
||||
final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
|
||||
mContentObserver.observe(timeoutUri,
|
||||
ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the package manager is registered to monitor the current active scorer.
|
||||
* If a discrepancy is found any previous monitor will be cleaned up
|
||||
* and a new monitor will be created.
|
||||
*
|
||||
* This method is idempotent.
|
||||
*/
|
||||
private void registerPackageMonitorIfNeeded() {
|
||||
if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
|
||||
final List<String> providerPackages =
|
||||
mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
|
||||
if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded()");
|
||||
final NetworkScorerAppData appData = mNetworkScorerAppManager.getActiveScorer();
|
||||
synchronized (mPackageMonitorLock) {
|
||||
// Unregister the current monitor if needed.
|
||||
if (mPackageMonitor != null) {
|
||||
if (mPackageMonitor != null && (appData == null
|
||||
|| !appData.getRecommendationServicePackageName().equals(
|
||||
mPackageMonitor.mPackageToWatch))) {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Unregistering package monitor for "
|
||||
+ mPackageMonitor.mPackagesToWatch);
|
||||
+ mPackageMonitor.mPackageToWatch);
|
||||
}
|
||||
mPackageMonitor.unregister();
|
||||
mPackageMonitor = null;
|
||||
}
|
||||
|
||||
// Create and register the monitor if there are packages that could be providers.
|
||||
if (!providerPackages.isEmpty()) {
|
||||
mPackageMonitor = new NetworkScorerPackageMonitor(providerPackages);
|
||||
// Create and register the monitor if a scorer is active.
|
||||
if (appData != null && mPackageMonitor == null) {
|
||||
mPackageMonitor = new NetworkScorerPackageMonitor(
|
||||
appData.getRecommendationServicePackageName());
|
||||
// TODO: Need to update when we support per-user scorers. http://b/23422763
|
||||
mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
|
||||
false /* externalStorage */);
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Registered package monitor for "
|
||||
+ mPackageMonitor.mPackagesToWatch);
|
||||
+ mPackageMonitor.mPackageToWatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,6 +337,13 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
bindToScoringServiceIfNeeded(scorerData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the service connection is bound to the current active scorer.
|
||||
* If a discrepancy is found any previous connection will be cleaned up
|
||||
* and a new connection will be created.
|
||||
*
|
||||
* This method is idempotent.
|
||||
*/
|
||||
private void bindToScoringServiceIfNeeded(NetworkScorerAppData appData) {
|
||||
if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + appData + ")");
|
||||
if (appData != null) {
|
||||
@@ -364,6 +372,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
if (mServiceConnection != null) {
|
||||
mServiceConnection.disconnect(mContext);
|
||||
if (DBG) Log.d(TAG, "Disconnected from: "
|
||||
+ mServiceConnection.mAppData.getRecommendationServiceComponent());
|
||||
}
|
||||
mServiceConnection = null;
|
||||
}
|
||||
@@ -652,17 +662,13 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
|
||||
@Override
|
||||
public boolean setActiveScorer(String packageName) {
|
||||
// TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
|
||||
// to directly set the scorer app rather than having to use the consent dialog. The
|
||||
// assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
|
||||
// do the right thing and not enable this feature without explaining it to the user.
|
||||
// In the future, should this API be opened to 3p apps, we will need to lock this down and
|
||||
// figure out another way to streamline the UX.
|
||||
|
||||
mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
|
||||
|
||||
// Scorers (recommendation providers) are selected and no longer set.
|
||||
return false;
|
||||
// Only the system can set the active scorer
|
||||
if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
|
||||
return mNetworkScorerAppManager.setActiveScorer(packageName);
|
||||
} else {
|
||||
throw new SecurityException(
|
||||
"Caller is neither the system process nor a score requester.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,7 +705,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
|
||||
*/
|
||||
@@ -726,7 +731,13 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
*/
|
||||
@Override
|
||||
public List<NetworkScorerAppData> getAllValidScorers() {
|
||||
return mNetworkScorerAppManager.getAllValidScorers();
|
||||
// Only the system can access this data.
|
||||
if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
|
||||
return mNetworkScorerAppManager.getAllValidScorers();
|
||||
} else {
|
||||
throw new SecurityException(
|
||||
"Caller is neither the system process nor a score requester.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1158,7 +1169,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
@VisibleForTesting
|
||||
public final class ServiceHandler extends Handler {
|
||||
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1;
|
||||
public static final int MSG_RECOMMENDATIONS_ENABLED_CHANGED = 2;
|
||||
public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2;
|
||||
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3;
|
||||
|
||||
public ServiceHandler(Looper looper) {
|
||||
@@ -1180,8 +1191,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
sendDefaultRecommendationResponse(request, remoteCallback);
|
||||
break;
|
||||
|
||||
case MSG_RECOMMENDATIONS_ENABLED_CHANGED:
|
||||
bindToScoringServiceIfNeeded();
|
||||
case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
|
||||
refreshBinding();
|
||||
break;
|
||||
|
||||
case MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED:
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.server;
|
||||
import android.Manifest.permission;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -27,12 +26,12 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.NetworkScoreManager;
|
||||
import android.net.NetworkScorerAppData;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -43,78 +42,68 @@ import java.util.List;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public class NetworkScorerAppManager {
|
||||
private static final String TAG = "NetworkScorerAppManager";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
|
||||
private final Context mContext;
|
||||
private final SettingsFacade mSettingsFacade;
|
||||
|
||||
public NetworkScorerAppManager(Context context) {
|
||||
mContext = context;
|
||||
this(context, new SettingsFacade());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public NetworkScorerAppManager(Context context, SettingsFacade settingsFacade) {
|
||||
mContext = context;
|
||||
mSettingsFacade = settingsFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of available scorer apps. The list will be empty if there are
|
||||
* no valid scorers.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public List<NetworkScorerAppData> getAllValidScorers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link NetworkScorerAppData} instance containing information about the
|
||||
* best configured network recommendation provider installed or {@code null}
|
||||
* if none of the configured packages can recommend networks.
|
||||
*
|
||||
* <p>A network recommendation provider is any application which:
|
||||
* <ul>
|
||||
* <li>Is listed in the <code>config_networkRecommendationPackageNames</code> config.
|
||||
* <li>Declares the {@link permission#SCORE_NETWORKS} permission.
|
||||
* <li>Includes a Service for {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS}.
|
||||
* </ul>
|
||||
*/
|
||||
@Nullable public NetworkScorerAppData getNetworkRecommendationProviderData() {
|
||||
// Network recommendation apps can only run as the primary user right now.
|
||||
// http://b/23422763
|
||||
if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
|
||||
return null;
|
||||
if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
|
||||
final List<ResolveInfo> resolveInfos =
|
||||
pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
|
||||
if (resolveInfos == null || resolveInfos.isEmpty()) {
|
||||
if (DEBUG) Log.d(TAG, "Found 0 Services able to handle " + serviceIntent);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> potentialPkgs = getPotentialRecommendationProviderPackages();
|
||||
if (potentialPkgs.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No Network Recommendation Providers specified.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < potentialPkgs.size(); i++) {
|
||||
final String potentialPkg = potentialPkgs.get(i);
|
||||
|
||||
// Look for the recommendation service class and required receiver.
|
||||
final ServiceInfo serviceInfo = findRecommendationService(potentialPkg);
|
||||
if (serviceInfo != null) {
|
||||
List<NetworkScorerAppData> appDataList = new ArrayList<>();
|
||||
for (int i = 0; i < resolveInfos.size(); i++) {
|
||||
final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
|
||||
if (hasPermissions(serviceInfo.packageName)) {
|
||||
if (VERBOSE) {
|
||||
Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
|
||||
}
|
||||
final ComponentName serviceComponentName =
|
||||
new ComponentName(potentialPkg, serviceInfo.name);
|
||||
new ComponentName(serviceInfo.packageName, serviceInfo.name);
|
||||
final ComponentName useOpenWifiNetworksActivity =
|
||||
findUseOpenWifiNetworksActivity(serviceInfo);
|
||||
return new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
|
||||
serviceComponentName, useOpenWifiNetworksActivity);
|
||||
appDataList.add(
|
||||
new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
|
||||
serviceComponentName, useOpenWifiNetworksActivity));
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, potentialPkg + " does not have the required components, skipping.");
|
||||
}
|
||||
if (VERBOSE) Log.v(TAG, serviceInfo.packageName
|
||||
+ " is NOT a valid scorer/recommender.");
|
||||
}
|
||||
}
|
||||
|
||||
// None of the configured packages are valid.
|
||||
return null;
|
||||
return appDataList;
|
||||
}
|
||||
|
||||
@Nullable private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
|
||||
@Nullable
|
||||
private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
|
||||
if (serviceInfo.metaData == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No metadata found on recommendation service.");
|
||||
Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -122,7 +111,8 @@ public class NetworkScorerAppManager {
|
||||
.getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
|
||||
if (TextUtils.isEmpty(useOpenWifiPackage)) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No use_open_wifi_package metadata found.");
|
||||
Log.d(TAG, "No use_open_wifi_package metadata found on "
|
||||
+ serviceInfo.getComponentName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -131,7 +121,7 @@ public class NetworkScorerAppManager {
|
||||
final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
|
||||
.resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
|
||||
if (VERBOSE) {
|
||||
Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + serviceInfo);
|
||||
Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + resolveActivityInfo);
|
||||
}
|
||||
|
||||
if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
|
||||
@@ -141,66 +131,6 @@ public class NetworkScorerAppManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A priority order list of package names that have been granted the
|
||||
* permission needed for them to act as a network recommendation provider.
|
||||
* The packages in the returned list may not contain the other required
|
||||
* network recommendation provider components so additional checks are required
|
||||
* before making a package the network recommendation provider.
|
||||
*/
|
||||
public List<String> getPotentialRecommendationProviderPackages() {
|
||||
final String[] packageArray = mContext.getResources().getStringArray(
|
||||
R.array.config_networkRecommendationPackageNames);
|
||||
if (packageArray == null || packageArray.length == 0) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No Network Recommendation Providers specified.");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
Log.d(TAG, "Configured packages: " + TextUtils.join(", ", packageArray));
|
||||
}
|
||||
|
||||
List<String> packages = new ArrayList<>();
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
for (String potentialPkg : packageArray) {
|
||||
if (pm.checkPermission(permission.SCORE_NETWORKS, potentialPkg)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
packages.add(potentialPkg);
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, potentialPkg + " has not been granted " + permission.SCORE_NETWORKS
|
||||
+ ", skipping.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Nullable private ServiceInfo findRecommendationService(String packageName) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
final int resolveFlags = PackageManager.GET_META_DATA;
|
||||
final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
|
||||
serviceIntent.setPackage(packageName);
|
||||
final ResolveInfo resolveServiceInfo =
|
||||
pm.resolveService(serviceIntent, resolveFlags);
|
||||
|
||||
if (VERBOSE) {
|
||||
Log.d(TAG, "Resolved " + serviceIntent + " to " + resolveServiceInfo);
|
||||
}
|
||||
|
||||
if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
|
||||
return resolveServiceInfo.serviceInfo;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
Log.v(TAG, packageName + " does not have a service for " + serviceIntent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application to use for scoring networks.
|
||||
*
|
||||
@@ -209,35 +139,107 @@ public class NetworkScorerAppManager {
|
||||
* it was disabled or uninstalled).
|
||||
*/
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
public NetworkScorerAppData getActiveScorer() {
|
||||
if (isNetworkRecommendationsDisabled()) {
|
||||
// If recommendations are disabled then there can't be an active scorer.
|
||||
return getScorer(getNetworkRecommendationsPackage());
|
||||
}
|
||||
|
||||
private NetworkScorerAppData getScorer(String packageName) {
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Otherwise return the recommendation provider (which may be null).
|
||||
return getNetworkRecommendationProviderData();
|
||||
List<NetworkScorerAppData> apps = getAllValidScorers();
|
||||
for (int i = 0; i < apps.size(); i++) {
|
||||
NetworkScorerAppData app = apps.get(i);
|
||||
if (app.getRecommendationServicePackageName().equals(packageName)) {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasPermissions(String packageName) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specified package as the default scorer application.
|
||||
*
|
||||
* <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
|
||||
* <p>The caller must have permission to write to {@link Settings.Global}.
|
||||
*
|
||||
* @param packageName the packageName of the new scorer to use. If null, scoring will be
|
||||
* disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
|
||||
* @param packageName the packageName of the new scorer to use. If null, the scoring app will
|
||||
* revert back to the configured default. Otherwise, the scorer will only
|
||||
* be set if it is a valid scorer application.
|
||||
* @return true if the scorer was changed, or false if the package is not a valid scorer or
|
||||
* a valid network recommendation provider exists.
|
||||
* @deprecated Scorers are now selected from a configured list.
|
||||
*/
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public boolean setActiveScorer(String packageName) {
|
||||
return false;
|
||||
String oldPackageName = getNetworkRecommendationsPackage();
|
||||
if (TextUtils.equals(oldPackageName, packageName)) {
|
||||
// No change.
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
|
||||
|
||||
if (packageName == null) {
|
||||
// revert to the default setting.
|
||||
setNetworkRecommendationsPackage(getDefaultPackageSetting());
|
||||
return true;
|
||||
} else {
|
||||
// We only make the change if the new package is valid.
|
||||
if (getScorer(packageName) != null) {
|
||||
setNetworkRecommendationsPackage(packageName);
|
||||
return true;
|
||||
} else {
|
||||
Log.w(TAG, "Requested network scorer is not valid: " + packageName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNetworkRecommendationsDisabled() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
// A value of 1 indicates enabled.
|
||||
return Settings.Global.getInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) != 1;
|
||||
/**
|
||||
* If the active scorer is null then revert to the default scorer.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void revertToDefaultIfNoActive() {
|
||||
if (getActiveScorer() == null) {
|
||||
final String defaultPackage = getDefaultPackageSetting();
|
||||
setNetworkRecommendationsPackage(defaultPackage);
|
||||
Log.i(TAG, "Defaulted the network recommendations app to: " + defaultPackage);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDefaultPackageSetting() {
|
||||
return mContext.getResources().getString(
|
||||
R.string.config_defaultNetworkRecommendationProviderPackage);
|
||||
}
|
||||
|
||||
private String getNetworkRecommendationsPackage() {
|
||||
return mSettingsFacade.getString(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE);
|
||||
}
|
||||
|
||||
private void setNetworkRecommendationsPackage(String packageName) {
|
||||
mSettingsFacade.putString(mContext,
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around Settings to make testing easier.
|
||||
*/
|
||||
public static class SettingsFacade {
|
||||
public boolean putString(Context context, String name, String value) {
|
||||
return Settings.Global.putString(context.getContentResolver(), name, value);
|
||||
}
|
||||
|
||||
public String getString(Context context, String name) {
|
||||
return Settings.Global.getString(context.getContentResolver(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,10 +200,10 @@ public class NetworkScoreServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemRunning() {
|
||||
public void testOnUserUnlocked() {
|
||||
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
|
||||
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
|
||||
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
|
||||
new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
|
||||
@@ -548,9 +548,9 @@ public class NetworkScoreServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetActiveScorer_noScoreNetworksPermission() {
|
||||
doThrow(new SecurityException()).when(mContext)
|
||||
.enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
|
||||
public void testSetActiveScorer_noRequestNetworkScoresPermission() {
|
||||
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
|
||||
.thenReturn(PackageManager.PERMISSION_DENIED);
|
||||
|
||||
try {
|
||||
mNetworkScoreService.setActiveScorer(null);
|
||||
@@ -629,7 +629,7 @@ public class NetworkScoreServiceTest {
|
||||
|
||||
@Test
|
||||
public void testIsCallerActiveScorer_noBoundService() throws Exception {
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
|
||||
assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
|
||||
}
|
||||
@@ -650,7 +650,7 @@ public class NetworkScoreServiceTest {
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorerPackage_notActive() throws Exception {
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
|
||||
assertNull(mNetworkScoreService.getActiveScorerPackage());
|
||||
}
|
||||
@@ -658,7 +658,7 @@ public class NetworkScoreServiceTest {
|
||||
@Test
|
||||
public void testGetActiveScorerPackage_active() throws Exception {
|
||||
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
|
||||
assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
|
||||
mNetworkScoreService.getActiveScorerPackage());
|
||||
@@ -959,7 +959,7 @@ public class NetworkScoreServiceTest {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
}
|
||||
|
||||
private void bindToScorer(boolean callerIsScorer) {
|
||||
@@ -973,7 +973,7 @@ public class NetworkScoreServiceTest {
|
||||
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
|
||||
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
|
||||
isA(UserHandle.class))).thenReturn(true);
|
||||
mNetworkScoreService.systemRunning();
|
||||
mNetworkScoreService.onUserUnlocked(0);
|
||||
}
|
||||
|
||||
private static class OnResultListener implements RemoteCallback.OnResultListener {
|
||||
|
||||
@@ -16,11 +16,20 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
@@ -33,141 +42,80 @@ import android.net.NetworkScoreManager;
|
||||
import android.net.NetworkScorerAppData;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class NetworkScorerAppManagerTest {
|
||||
@Mock private Context mMockContext;
|
||||
@Mock private PackageManager mMockPm;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private ContentResolver mContentResolver;
|
||||
private Context mTargetContext;
|
||||
@Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
|
||||
private NetworkScorerAppManager mNetworkScorerAppManager;
|
||||
private List<ResolveInfo> mAvailableServices;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
// Configuration needed to make mockito/dexcache work.
|
||||
mTargetContext = getInstrumentation().getTargetContext();
|
||||
System.setProperty("dexmaker.dexcache", mTargetContext.getCacheDir().getPath());
|
||||
ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(newClassLoader);
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mAvailableServices = new ArrayList<>();
|
||||
when(mMockContext.getPackageManager()).thenReturn(mMockPm);
|
||||
when(mMockPm.queryIntentServices(Mockito.argThat(new ArgumentMatcher<Intent>() {
|
||||
@Override
|
||||
public boolean matches(Object object) {
|
||||
Intent intent = (Intent) object;
|
||||
return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction());
|
||||
}
|
||||
}), eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
|
||||
when(mMockContext.getResources()).thenReturn(mResources);
|
||||
when(mMockContext.getContentResolver()).thenReturn(mTargetContext.getContentResolver());
|
||||
mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext);
|
||||
}
|
||||
|
||||
public void testGetPotentialRecommendationProviderPackages_emptyConfig() throws Exception {
|
||||
setNetworkRecommendationPackageNames(/*no configured packages*/);
|
||||
assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
|
||||
}
|
||||
|
||||
public void testGetPotentialRecommendationProviderPackages_permissionNotGranted()
|
||||
throws Exception {
|
||||
setNetworkRecommendationPackageNames("package1");
|
||||
mockScoreNetworksDenied("package1");
|
||||
|
||||
assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
|
||||
}
|
||||
|
||||
public void testGetPotentialRecommendationProviderPackages_permissionGranted()
|
||||
throws Exception {
|
||||
setNetworkRecommendationPackageNames("package1");
|
||||
mockScoreNetworksGranted("package1");
|
||||
|
||||
List<String> potentialProviderPackages =
|
||||
mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
|
||||
|
||||
assertFalse(potentialProviderPackages.isEmpty());
|
||||
assertEquals("package1", potentialProviderPackages.get(0));
|
||||
}
|
||||
|
||||
public void testGetPotentialRecommendationProviderPackages_multipleConfigured()
|
||||
throws Exception {
|
||||
setNetworkRecommendationPackageNames("package1", "package2");
|
||||
mockScoreNetworksDenied("package1");
|
||||
mockScoreNetworksGranted("package2");
|
||||
|
||||
List<String> potentialProviderPackages =
|
||||
mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
|
||||
|
||||
assertEquals(1, potentialProviderPackages.size());
|
||||
assertEquals("package2", potentialProviderPackages.get(0));
|
||||
}
|
||||
|
||||
public void testGetNetworkRecommendationProviderData_noPotentialPackages() throws Exception {
|
||||
setNetworkRecommendationPackageNames(/*no configured packages*/);
|
||||
assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
|
||||
}
|
||||
|
||||
public void testGetNetworkRecommendationProviderData_serviceMissing() throws Exception {
|
||||
setNetworkRecommendationPackageNames("package1");
|
||||
mockScoreNetworksGranted("package1");
|
||||
|
||||
assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
|
||||
}
|
||||
|
||||
public void testGetNetworkRecommendationProviderData_scoreNetworksNotGranted()
|
||||
throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
mockScoreNetworksDenied(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
|
||||
|
||||
assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
|
||||
}
|
||||
|
||||
public void testGetNetworkRecommendationProviderData_available() throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
|
||||
|
||||
NetworkScorerAppData appData =
|
||||
mNetworkScorerAppManager.getNetworkRecommendationProviderData();
|
||||
assertNotNull(appData);
|
||||
assertEquals(recoComponent, appData.getRecommendationServiceComponent());
|
||||
assertEquals(924, appData.packageUid);
|
||||
|
||||
mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorer_providerAvailable() throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
setNetworkRecoPackageSetting(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
|
||||
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNotNull(activeScorer);
|
||||
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
|
||||
assertEquals(924, activeScorer.packageUid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorer_permissionMissing() throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecoPackageSetting(recoComponent.getPackageName());
|
||||
mockScoreNetworksDenied(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNull(activeScorer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
|
||||
throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
setNetworkRecoPackageSetting(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
|
||||
null /* enableUseOpenWifiPackageActivityPackage*/);
|
||||
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNotNull(activeScorer);
|
||||
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
|
||||
@@ -175,17 +123,15 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
|
||||
assertNull(activeScorer.getEnableUseOpenWifiActivity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
|
||||
throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
setNetworkRecoPackageSetting(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
|
||||
"package2" /* enableUseOpenWifiPackageActivityPackage*/);
|
||||
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNotNull(activeScorer);
|
||||
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
|
||||
@@ -193,19 +139,17 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
|
||||
assertNull(activeScorer.getEnableUseOpenWifiActivity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
|
||||
throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
setNetworkRecoPackageSetting(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
|
||||
enableUseOpenWifiComponent.getPackageName());
|
||||
mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
|
||||
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNotNull(activeScorer);
|
||||
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
|
||||
@@ -213,33 +157,105 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
|
||||
assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
|
||||
}
|
||||
|
||||
public void testGetActiveScorer_providerNotAvailable()
|
||||
@Test
|
||||
public void testGetActiveScorer_packageSettingIsNull()
|
||||
throws Exception {
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
|
||||
// NETWORK_RECOMMENDATIONS_PACKAGE is null
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNull(activeScorer);
|
||||
}
|
||||
|
||||
public void testGetActiveScorer_recommendationsDisabled() throws Exception {
|
||||
@Test
|
||||
public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
|
||||
final ComponentName recoComponent = new ComponentName("package1", "class1");
|
||||
setNetworkRecommendationPackageNames(recoComponent.getPackageName());
|
||||
setDefaultNetworkRecommendationPackage(recoComponent.getPackageName());
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
|
||||
ContentResolver cr = mTargetContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
|
||||
// NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
|
||||
|
||||
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
|
||||
assertNull(activeScorer);
|
||||
}
|
||||
|
||||
private void setNetworkRecommendationPackageNames(String... names) {
|
||||
if (names == null) {
|
||||
names = new String[0];
|
||||
}
|
||||
when(mResources.getStringArray(R.array.config_networkRecommendationPackageNames))
|
||||
.thenReturn(names);
|
||||
@Test
|
||||
public void testSetActiveScorer_noChange() throws Exception {
|
||||
String packageName = "package";
|
||||
setNetworkRecoPackageSetting(packageName);
|
||||
|
||||
assertTrue(mNetworkScorerAppManager.setActiveScorer(packageName));
|
||||
verify(mSettingsFacade, never()).putString(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetActiveScorer_nullPackage() throws Exception {
|
||||
String packageName = "package";
|
||||
String defaultPackage = "defaultPackage";
|
||||
setNetworkRecoPackageSetting(packageName);
|
||||
setDefaultNetworkRecommendationPackage(defaultPackage);
|
||||
|
||||
assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
|
||||
verify(mSettingsFacade).putString(mMockContext,
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetActiveScorer_validPackage() throws Exception {
|
||||
String packageName = "package";
|
||||
String newPackage = "newPackage";
|
||||
setNetworkRecoPackageSetting(packageName);
|
||||
final ComponentName recoComponent = new ComponentName(newPackage, "class1");
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
|
||||
|
||||
assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
|
||||
verify(mSettingsFacade).putString(mMockContext,
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetActiveScorer_invalidPackage() throws Exception {
|
||||
String packageName = "package";
|
||||
String newPackage = "newPackage";
|
||||
setNetworkRecoPackageSetting(packageName);
|
||||
// newPackage doesn't resolve to a valid recommender
|
||||
|
||||
assertFalse(mNetworkScorerAppManager.setActiveScorer(newPackage));
|
||||
verify(mSettingsFacade, never()).putString(any(), any(), any());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevertToDefaultIfNoActive_notActive() throws Exception {
|
||||
String defaultPackage = "defaultPackage";
|
||||
setDefaultNetworkRecommendationPackage(defaultPackage);
|
||||
|
||||
mNetworkScorerAppManager.revertToDefaultIfNoActive();
|
||||
|
||||
verify(mSettingsFacade).putString(mMockContext,
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertToDefaultIfNoActive_active() throws Exception {
|
||||
String packageName = "package";
|
||||
setNetworkRecoPackageSetting(packageName);
|
||||
final ComponentName recoComponent = new ComponentName(packageName, "class1");
|
||||
mockScoreNetworksGranted(recoComponent.getPackageName());
|
||||
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
|
||||
|
||||
mNetworkScorerAppManager.revertToDefaultIfNoActive();
|
||||
|
||||
verify(mSettingsFacade, never()).putString(any(), any(), any());
|
||||
}
|
||||
|
||||
private void setNetworkRecoPackageSetting(String packageName) {
|
||||
when(mSettingsFacade.getString(mMockContext,
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE)).thenReturn(packageName);
|
||||
}
|
||||
|
||||
private void setDefaultNetworkRecommendationPackage(String name) {
|
||||
when(mResources.getString(R.string.config_defaultNetworkRecommendationProviderPackage))
|
||||
.thenReturn(name);
|
||||
}
|
||||
|
||||
private void mockScoreNetworksGranted(String packageName) {
|
||||
@@ -282,6 +298,8 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
|
||||
&& compName.getPackageName().equals(intent.getPackage());
|
||||
}
|
||||
}), Mockito.eq(flags))).thenReturn(serviceInfo);
|
||||
|
||||
mAvailableServices.add(serviceInfo);
|
||||
}
|
||||
|
||||
private void mockEnableUseOpenWifiActivity(final ComponentName useOpenWifiComp) {
|
||||
|
||||
Reference in New Issue
Block a user