Merge "Refactor NetworkScoreAppManager for testing."
am: 3af97482f1
Change-Id: I99537b7841021704c162db6b8fe3d472ede1e991
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user