Merge "Refactor NetworkScoreAppManager for testing."

am: 3af97482f1

Change-Id: I99537b7841021704c162db6b8fe3d472ede1e991
This commit is contained in:
Amin Shaikh
2016-12-01 02:10:55 +00:00
committed by android-build-merger
4 changed files with 44 additions and 31 deletions

View File

@@ -144,7 +144,7 @@ public class NetworkScoreManager {
* scorer. * scorer.
*/ */
public String getActiveScorerPackage() { public String getActiveScorerPackage() {
NetworkScorerAppData app = NetworkScorerAppManager.getActiveScorer(mContext); NetworkScorerAppData app = new NetworkScorerAppManager(mContext).getActiveScorer();
if (app == null) { if (app == null) {
return null; return null;
} }

View File

@@ -41,14 +41,17 @@ import java.util.List;
* *
* @hide * @hide
*/ */
public final class NetworkScorerAppManager { public class NetworkScorerAppManager {
private static final String TAG = "NetworkScorerAppManager"; private static final String TAG = "NetworkScorerAppManager";
private static final Intent SCORE_INTENT = private static final Intent SCORE_INTENT =
new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS); new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
/** This class cannot be instantiated. */ private final Context mContext;
private NetworkScorerAppManager() {}
public NetworkScorerAppManager(Context context) {
mContext = context;
}
public static class NetworkScorerAppData { public static class NetworkScorerAppData {
/** Package name of this scorer app. */ /** Package name of this scorer app. */
@@ -108,7 +111,7 @@ public final class NetworkScorerAppManager {
* *
* @return the list of scorers, or the empty list if there are no valid scorers. * @return the list of scorers, or the empty list if there are no valid scorers.
*/ */
public static Collection<NetworkScorerAppData> getAllValidScorers(Context context) { public Collection<NetworkScorerAppData> getAllValidScorers() {
// Network scorer apps can only run as the primary user so exit early if we're not the // Network scorer apps can only run as the primary user so exit early if we're not the
// primary user. // primary user.
if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) { if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
@@ -116,7 +119,7 @@ public final class NetworkScorerAppManager {
} }
List<NetworkScorerAppData> scorers = new ArrayList<>(); List<NetworkScorerAppData> scorers = new ArrayList<>();
PackageManager pm = context.getPackageManager(); PackageManager pm = mContext.getPackageManager();
// Only apps installed under the primary user of the device can be scorers. // Only apps installed under the primary user of the device can be scorers.
// TODO: http://b/23422763 // TODO: http://b/23422763
List<ResolveInfo> receivers = List<ResolveInfo> receivers =
@@ -179,10 +182,10 @@ public final class NetworkScorerAppManager {
* selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
* it was disabled or uninstalled). * it was disabled or uninstalled).
*/ */
public static NetworkScorerAppData getActiveScorer(Context context) { public NetworkScorerAppData getActiveScorer() {
String scorerPackage = Settings.Global.getString(context.getContentResolver(), String scorerPackage = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP); Settings.Global.NETWORK_SCORER_APP);
return getScorer(context, scorerPackage); return getScorer(scorerPackage);
} }
/** /**
@@ -190,13 +193,12 @@ public final class NetworkScorerAppManager {
* *
* <p>The caller must have permission to write to {@link android.provider.Settings.Global}. * <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
* *
* @param context the context of the calling application
* @param packageName the packageName of the new scorer to use. If null, scoring will be * @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. * disabled. 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. * @return true if the scorer was changed, or false if the package is not a valid scorer.
*/ */
public static boolean setActiveScorer(Context context, String packageName) { public boolean setActiveScorer(String packageName) {
String oldPackageName = Settings.Global.getString(context.getContentResolver(), String oldPackageName = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP); Settings.Global.NETWORK_SCORER_APP);
if (TextUtils.equals(oldPackageName, packageName)) { if (TextUtils.equals(oldPackageName, packageName)) {
// No change. // No change.
@@ -206,13 +208,13 @@ public final class NetworkScorerAppManager {
Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName); Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
if (packageName == null) { if (packageName == null) {
Settings.Global.putString(context.getContentResolver(), Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP, null); Settings.Global.NETWORK_SCORER_APP, null);
return true; return true;
} else { } else {
// We only make the change if the new package is valid. // We only make the change if the new package is valid.
if (getScorer(context, packageName) != null) { if (getScorer(packageName) != null) {
Settings.Global.putString(context.getContentResolver(), Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP, packageName); Settings.Global.NETWORK_SCORER_APP, packageName);
return true; return true;
} else { } else {
@@ -223,8 +225,8 @@ public final class NetworkScorerAppManager {
} }
/** Determine whether the application with the given UID is the enabled scorer. */ /** Determine whether the application with the given UID is the enabled scorer. */
public static boolean isCallerActiveScorer(Context context, int callingUid) { public boolean isCallerActiveScorer(int callingUid) {
NetworkScorerAppData defaultApp = getActiveScorer(context); NetworkScorerAppData defaultApp = getActiveScorer();
if (defaultApp == null) { if (defaultApp == null) {
return false; return false;
} }
@@ -233,16 +235,16 @@ public final class NetworkScorerAppManager {
} }
// To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always // To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always
// should, since it couldn't become the active scorer otherwise, but this can't hurt. // should, since it couldn't become the active scorer otherwise, but this can't hurt.
return context.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) == return mContext.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) ==
PackageManager.PERMISSION_GRANTED; PackageManager.PERMISSION_GRANTED;
} }
/** Returns the {@link NetworkScorerAppData} for the given app, or null if it's not a scorer. */ /** Returns the {@link NetworkScorerAppData} for the given app, or null if it's not a scorer. */
public static NetworkScorerAppData getScorer(Context context, String packageName) { public NetworkScorerAppData getScorer(String packageName) {
if (TextUtils.isEmpty(packageName)) { if (TextUtils.isEmpty(packageName)) {
return null; return null;
} }
Collection<NetworkScorerAppData> applications = getAllValidScorers(context); Collection<NetworkScorerAppData> applications = getAllValidScorers();
for (NetworkScorerAppData app : applications) { for (NetworkScorerAppData app : applications) {
if (packageName.equals(app.mPackageName)) { if (packageName.equals(app.mPackageName)) {
return app; return app;

View File

@@ -42,6 +42,8 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
@Mock private Context mMockContext; @Mock private Context mMockContext;
@Mock private PackageManager mMockPm; @Mock private PackageManager mMockPm;
private NetworkScorerAppManager mNetworkScorerAppManager;
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
@@ -54,6 +56,7 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
Mockito.when(mMockContext.getPackageManager()).thenReturn(mMockPm); Mockito.when(mMockContext.getPackageManager()).thenReturn(mMockPm);
mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext);
} }
public void testGetAllValidScorers() throws Exception { public void testGetAllValidScorers() throws Exception {
@@ -81,7 +84,7 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
setScorers(scorers); setScorers(scorers);
Iterator<NetworkScorerAppData> result = Iterator<NetworkScorerAppData> result =
NetworkScorerAppManager.getAllValidScorers(mMockContext).iterator(); mNetworkScorerAppManager.getAllValidScorers().iterator();
assertTrue(result.hasNext()); assertTrue(result.hasNext());
NetworkScorerAppData next = result.next(); NetworkScorerAppData next = result.next();

View File

@@ -41,6 +41,7 @@ import android.util.Log;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -61,6 +62,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
private static final boolean DBG = false; private static final boolean DBG = false;
private final Context mContext; private final Context mContext;
private final NetworkScorerAppManager mNetworkScorerAppManager;
private final Map<Integer, INetworkScoreCache> mScoreCaches; private final Map<Integer, INetworkScoreCache> mScoreCaches;
/** Lock used to update mPackageMonitor when scorer package changes occur. */ /** Lock used to update mPackageMonitor when scorer package changes occur. */
private final Object mPackageMonitorLock = new Object[0]; private final Object mPackageMonitorLock = new Object[0];
@@ -131,7 +133,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
+ ", forceUnbind=" + forceUnbind); + ", forceUnbind=" + forceUnbind);
} }
final NetworkScorerAppData activeScorer = final NetworkScorerAppData activeScorer =
NetworkScorerAppManager.getActiveScorer(mContext); mNetworkScorerAppManager.getActiveScorer();
if (activeScorer == null) { if (activeScorer == null) {
// Package change has invalidated a scorer, this will also unbind any service // Package change has invalidated a scorer, this will also unbind any service
// connection. // connection.
@@ -152,7 +154,13 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
} }
public NetworkScoreService(Context context) { public NetworkScoreService(Context context) {
this(context, new NetworkScorerAppManager(context));
}
@VisibleForTesting
NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) {
mContext = context; mContext = context;
mNetworkScorerAppManager = networkScoreAppManager;
mScoreCaches = new HashMap<>(); mScoreCaches = new HashMap<>();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
// TODO: Need to update when we support per-user scorers. http://b/23422763 // TODO: Need to update when we support per-user scorers. http://b/23422763
@@ -171,7 +179,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
String defaultPackage = mContext.getResources().getString( String defaultPackage = mContext.getResources().getString(
R.string.config_defaultNetworkScorerPackageName); R.string.config_defaultNetworkScorerPackageName);
if (!TextUtils.isEmpty(defaultPackage)) { if (!TextUtils.isEmpty(defaultPackage)) {
NetworkScorerAppManager.setActiveScorer(mContext, defaultPackage); mNetworkScorerAppManager.setActiveScorer(defaultPackage);
} }
Settings.Global.putInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 1); Settings.Global.putInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 1);
} }
@@ -192,7 +200,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
private void registerPackageMonitorIfNeeded() { private void registerPackageMonitorIfNeeded() {
if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded"); if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext); NetworkScorerAppData scorer = mNetworkScorerAppManager.getActiveScorer();
synchronized (mPackageMonitorLock) { synchronized (mPackageMonitorLock) {
// Unregister the current monitor if needed. // Unregister the current monitor if needed.
if (mPackageMonitor != null) { if (mPackageMonitor != null) {
@@ -220,7 +228,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
private void bindToScoringServiceIfNeeded() { private void bindToScoringServiceIfNeeded() {
if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded"); if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded");
NetworkScorerAppData scorerData = NetworkScorerAppManager.getActiveScorer(mContext); NetworkScorerAppData scorerData = mNetworkScorerAppManager.getActiveScorer();
bindToScoringServiceIfNeeded(scorerData); bindToScoringServiceIfNeeded(scorerData);
} }
@@ -257,7 +265,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override @Override
public boolean updateScores(ScoredNetwork[] networks) { public boolean updateScores(ScoredNetwork[] networks) {
if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) { if (!mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid())) {
throw new SecurityException("Caller with UID " + getCallingUid() + throw new SecurityException("Caller with UID " + getCallingUid() +
" is not the active scorer."); " is not the active scorer.");
} }
@@ -296,7 +304,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
public boolean clearScores() { public boolean clearScores() {
// Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED) // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
// should be allowed to flush all scores. // should be allowed to flush all scores.
if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) || if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) == mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
PackageManager.PERMISSION_GRANTED) { PackageManager.PERMISSION_GRANTED) {
clearInternal(); clearInternal();
@@ -326,7 +334,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
public void disableScoring() { public void disableScoring() {
// Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED) // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
// should be allowed to disable scoring. // should be allowed to disable scoring.
if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) || if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) == mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
PackageManager.PERMISSION_GRANTED) { PackageManager.PERMISSION_GRANTED) {
// The return value is discarded here because at this point, the call should always // The return value is discarded here because at this point, the call should always
@@ -350,8 +358,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
// only be allowing valid apps to be set as scorers, so failure here should be rare. // only be allowing valid apps to be set as scorers, so failure here should be rare.
clearInternal(); clearInternal();
// Get the scorer that is about to be replaced, if any, so we can notify it directly. // Get the scorer that is about to be replaced, if any, so we can notify it directly.
NetworkScorerAppData prevScorer = NetworkScorerAppManager.getActiveScorer(mContext); NetworkScorerAppData prevScorer = mNetworkScorerAppManager.getActiveScorer();
boolean result = NetworkScorerAppManager.setActiveScorer(mContext, packageName); boolean result = mNetworkScorerAppManager.setActiveScorer(packageName);
// Unconditionally attempt to bind to the current scorer. If setActiveScorer() failed // Unconditionally attempt to bind to the current scorer. If setActiveScorer() failed
// then we'll attempt to restore the previous binding (if any), otherwise an attempt // then we'll attempt to restore the previous binding (if any), otherwise an attempt
// will be made to bind to the new scorer. // will be made to bind to the new scorer.
@@ -409,7 +417,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override @Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
NetworkScorerAppData currentScorer = NetworkScorerAppManager.getActiveScorer(mContext); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
if (currentScorer == null) { if (currentScorer == null) {
writer.println("Scoring is disabled."); writer.println("Scoring is disabled.");
return; return;