Loading core/java/android/net/INetworkScoreService.aidl +11 −2 Original line number Original line Diff line number Diff line Loading @@ -56,16 +56,25 @@ interface INetworkScoreService void disableScoring(); void disableScoring(); /** /** * Register a network subsystem for scoring. * Register a cache to receive scoring updates. * * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller is not the system. * @throws SecurityException if the caller is not the system. * @throws IllegalArgumentException if a score cache is already registed for this type. * @hide * @hide */ */ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** * Unregister a cache to receive scoring updates. * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller is not the system. * @hide */ void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** /** * Request a recommendation for the best network to connect to * Request a recommendation for the best network to connect to * taking into account the inputs from the {@link RecommendationRequest}. * taking into account the inputs from the {@link RecommendationRequest}. Loading core/java/android/net/NetworkScoreManager.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -278,6 +278,24 @@ public class NetworkScoreManager { } } } } /** * Unregister a network score cache. * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { try { mService.unregisterNetworkScoreCache(networkType, scoreCache); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** /** * Request a recommendation for which network to connect to. * Request a recommendation for which network to connect to. * * Loading services/core/java/com/android/server/NetworkScoreService.java +98 −38 Original line number Original line Diff line number Diff line Loading @@ -36,10 +36,12 @@ import android.net.ScoredNetwork; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration; import android.os.Binder; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import com.android.internal.R; import com.android.internal.R; Loading @@ -52,11 +54,11 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; import java.util.Collection; import java.util.HashSet; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.function.Consumer; /** /** * Backing service for {@link android.net.NetworkScoreManager}. * Backing service for {@link android.net.NetworkScoreManager}. Loading @@ -68,7 +70,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub { private final Context mContext; private final Context mContext; private final NetworkScorerAppManager mNetworkScorerAppManager; private final NetworkScorerAppManager mNetworkScorerAppManager; private final Map<Integer, INetworkScoreCache> mScoreCaches; @GuardedBy("mScoreCaches") private final Map<Integer, RemoteCallbackList<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]; Loading Loading @@ -166,7 +169,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) { NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) { mContext = context; mContext = context; mNetworkScorerAppManager = networkScoreAppManager; mNetworkScorerAppManager = networkScoreAppManager; mScoreCaches = new HashMap<>(); mScoreCaches = new ArrayMap<>(); 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 mContext.registerReceiverAsUser( mContext.registerReceiverAsUser( Loading Loading @@ -276,7 +279,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } // Separate networks by type. // Separate networks by type. Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>(); Map<Integer, List<ScoredNetwork>> networksByType = new ArrayMap<>(); for (ScoredNetwork network : networks) { for (ScoredNetwork network : networks) { List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type); List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type); if (networkList == null) { if (networkList == null) { Loading @@ -287,19 +290,32 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } // Pass the scores of each type down to the appropriate network scorer. // Pass the scores of each type down to the appropriate network scorer. for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { for (final Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey()); final RemoteCallbackList<INetworkScoreCache> callbackList; if (scoreCache != null) { final boolean isEmpty; synchronized (mScoreCaches) { callbackList = mScoreCaches.get(entry.getKey()); isEmpty = callbackList == null || callbackList.getRegisteredCallbackCount() == 0; } if (isEmpty) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); } continue; } sendCallback(new Consumer<INetworkScoreCache>() { @Override public void accept(INetworkScoreCache networkScoreCache) { try { try { scoreCache.updateScores(entry.getValue()); networkScoreCache.updateScores(entry.getValue()); } catch (RemoteException e) { } catch (RemoteException e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); } } } } } else if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); } } }, Collections.singleton(callbackList)); } } return true; return true; Loading Loading @@ -394,28 +410,52 @@ public class NetworkScoreService extends INetworkScoreService.Stub { /** Clear scores. Callers are responsible for checking permissions as appropriate. */ /** Clear scores. Callers are responsible for checking permissions as appropriate. */ private void clearInternal() { private void clearInternal() { Set<INetworkScoreCache> cachesToClear = getScoreCaches(); sendCallback(new Consumer<INetworkScoreCache>() { @Override for (INetworkScoreCache scoreCache : cachesToClear) { public void accept(INetworkScoreCache networkScoreCache) { try { try { scoreCache.clearScores(); networkScoreCache.clearScores(); } catch (RemoteException e) { } catch (RemoteException e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to clear scores", e); Log.v(TAG, "Unable to clear scores", e); } } } } } } }, getScoreCacheLists()); } } @Override @Override public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); synchronized (mScoreCaches) { synchronized (mScoreCaches) { if (mScoreCaches.containsKey(networkType)) { RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); throw new IllegalArgumentException( if (callbackList == null) { "Score cache already registered for type " + networkType); callbackList = new RemoteCallbackList<>(); mScoreCaches.put(networkType, callbackList); } if (!callbackList.register(scoreCache)) { if (callbackList.getRegisteredCallbackCount() == 0) { mScoreCaches.remove(networkType); } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to register NetworkScoreCache for type " + networkType); } } } } @Override public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); synchronized (mScoreCaches) { RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); if (callbackList == null || !callbackList.unregister(scoreCache)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to unregister NetworkScoreCache for type " + networkType); } } else if (callbackList.getRegisteredCallbackCount() == 0) { mScoreCaches.remove(networkType); } } mScoreCaches.put(networkType, scoreCache); } } } } Loading @@ -430,7 +470,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } @Override @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) { mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer(); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer(); if (currentScorer == null) { if (currentScorer == null) { Loading @@ -439,13 +479,17 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } writer.println("Current scorer: " + currentScorer.mPackageName); writer.println("Current scorer: " + currentScorer.mPackageName); for (INetworkScoreCache scoreCache : getScoreCaches()) { sendCallback(new Consumer<INetworkScoreCache>() { @Override public void accept(INetworkScoreCache networkScoreCache) { try { try { TransferPipe.dumpAsync(scoreCache.asBinder(), fd, args); TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args); } catch (IOException | RemoteException e) { } catch (IOException | RemoteException e) { writer.println("Failed to dump score cache: " + e); writer.println("Failed to dump score cache: " + e); } } } } }, getScoreCacheLists()); if (mServiceConnection != null) { if (mServiceConnection != null) { mServiceConnection.dump(fd, writer, args); mServiceConnection.dump(fd, writer, args); } else { } else { Loading @@ -455,14 +499,30 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } /** /** * Returns a set of all score caches that are currently active. * Returns a {@link Collection} of all {@link RemoteCallbackList}s that are currently active. * * * <p>May be used to perform an action on all score caches without potentially strange behavior * <p>May be used to perform an action on all score caches without potentially strange behavior * if a new scorer is registered during that action's execution. * if a new scorer is registered during that action's execution. */ */ private Set<INetworkScoreCache> getScoreCaches() { private Collection<RemoteCallbackList<INetworkScoreCache>> getScoreCacheLists() { synchronized (mScoreCaches) { synchronized (mScoreCaches) { return new HashSet<>(mScoreCaches.values()); return new ArrayList<>(mScoreCaches.values()); } } private void sendCallback(Consumer<INetworkScoreCache> consumer, Collection<RemoteCallbackList<INetworkScoreCache>> remoteCallbackLists) { for (RemoteCallbackList<INetworkScoreCache> callbackList : remoteCallbackLists) { synchronized (callbackList) { // Ensure only one active broadcast per RemoteCallbackList final int count = callbackList.beginBroadcast(); try { for (int i = 0; i < count; i++) { consumer.accept(callbackList.getBroadcastItem(i)); } } finally { callbackList.finishBroadcast(); } } } } } } Loading services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java 0 → 100644 +422 −0 File added.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,21 @@ public class MockUtils { return Mockito.argThat(m); return Mockito.argThat(m); } } public static Intent checkIntent(final Intent intent) { final Matcher<Intent> m = new BaseMatcher<Intent>() { @Override public boolean matches(Object item) { if (item == null) return false; return intent.filterEquals((Intent) item); } @Override public void describeTo(Description description) { description.appendText(intent.toString()); } }; return Mockito.argThat(m); } public static Bundle checkUserRestrictions(String... keys) { public static Bundle checkUserRestrictions(String... keys) { final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys)); final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys)); final Matcher<Bundle> m = new BaseMatcher<Bundle>() { final Matcher<Bundle> m = new BaseMatcher<Bundle>() { Loading Loading
core/java/android/net/INetworkScoreService.aidl +11 −2 Original line number Original line Diff line number Diff line Loading @@ -56,16 +56,25 @@ interface INetworkScoreService void disableScoring(); void disableScoring(); /** /** * Register a network subsystem for scoring. * Register a cache to receive scoring updates. * * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller is not the system. * @throws SecurityException if the caller is not the system. * @throws IllegalArgumentException if a score cache is already registed for this type. * @hide * @hide */ */ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** * Unregister a cache to receive scoring updates. * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller is not the system. * @hide */ void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** /** * Request a recommendation for the best network to connect to * Request a recommendation for the best network to connect to * taking into account the inputs from the {@link RecommendationRequest}. * taking into account the inputs from the {@link RecommendationRequest}. Loading
core/java/android/net/NetworkScoreManager.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -278,6 +278,24 @@ public class NetworkScoreManager { } } } } /** * Unregister a network score cache. * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { try { mService.unregisterNetworkScoreCache(networkType, scoreCache); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** /** * Request a recommendation for which network to connect to. * Request a recommendation for which network to connect to. * * Loading
services/core/java/com/android/server/NetworkScoreService.java +98 −38 Original line number Original line Diff line number Diff line Loading @@ -36,10 +36,12 @@ import android.net.ScoredNetwork; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration; import android.os.Binder; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import com.android.internal.R; import com.android.internal.R; Loading @@ -52,11 +54,11 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; import java.util.Collection; import java.util.HashSet; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.function.Consumer; /** /** * Backing service for {@link android.net.NetworkScoreManager}. * Backing service for {@link android.net.NetworkScoreManager}. Loading @@ -68,7 +70,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub { private final Context mContext; private final Context mContext; private final NetworkScorerAppManager mNetworkScorerAppManager; private final NetworkScorerAppManager mNetworkScorerAppManager; private final Map<Integer, INetworkScoreCache> mScoreCaches; @GuardedBy("mScoreCaches") private final Map<Integer, RemoteCallbackList<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]; Loading Loading @@ -166,7 +169,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) { NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) { mContext = context; mContext = context; mNetworkScorerAppManager = networkScoreAppManager; mNetworkScorerAppManager = networkScoreAppManager; mScoreCaches = new HashMap<>(); mScoreCaches = new ArrayMap<>(); 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 mContext.registerReceiverAsUser( mContext.registerReceiverAsUser( Loading Loading @@ -276,7 +279,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } // Separate networks by type. // Separate networks by type. Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>(); Map<Integer, List<ScoredNetwork>> networksByType = new ArrayMap<>(); for (ScoredNetwork network : networks) { for (ScoredNetwork network : networks) { List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type); List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type); if (networkList == null) { if (networkList == null) { Loading @@ -287,19 +290,32 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } // Pass the scores of each type down to the appropriate network scorer. // Pass the scores of each type down to the appropriate network scorer. for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { for (final Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey()); final RemoteCallbackList<INetworkScoreCache> callbackList; if (scoreCache != null) { final boolean isEmpty; synchronized (mScoreCaches) { callbackList = mScoreCaches.get(entry.getKey()); isEmpty = callbackList == null || callbackList.getRegisteredCallbackCount() == 0; } if (isEmpty) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); } continue; } sendCallback(new Consumer<INetworkScoreCache>() { @Override public void accept(INetworkScoreCache networkScoreCache) { try { try { scoreCache.updateScores(entry.getValue()); networkScoreCache.updateScores(entry.getValue()); } catch (RemoteException e) { } catch (RemoteException e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); } } } } } else if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); } } }, Collections.singleton(callbackList)); } } return true; return true; Loading Loading @@ -394,28 +410,52 @@ public class NetworkScoreService extends INetworkScoreService.Stub { /** Clear scores. Callers are responsible for checking permissions as appropriate. */ /** Clear scores. Callers are responsible for checking permissions as appropriate. */ private void clearInternal() { private void clearInternal() { Set<INetworkScoreCache> cachesToClear = getScoreCaches(); sendCallback(new Consumer<INetworkScoreCache>() { @Override for (INetworkScoreCache scoreCache : cachesToClear) { public void accept(INetworkScoreCache networkScoreCache) { try { try { scoreCache.clearScores(); networkScoreCache.clearScores(); } catch (RemoteException e) { } catch (RemoteException e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to clear scores", e); Log.v(TAG, "Unable to clear scores", e); } } } } } } }, getScoreCacheLists()); } } @Override @Override public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); synchronized (mScoreCaches) { synchronized (mScoreCaches) { if (mScoreCaches.containsKey(networkType)) { RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); throw new IllegalArgumentException( if (callbackList == null) { "Score cache already registered for type " + networkType); callbackList = new RemoteCallbackList<>(); mScoreCaches.put(networkType, callbackList); } if (!callbackList.register(scoreCache)) { if (callbackList.getRegisteredCallbackCount() == 0) { mScoreCaches.remove(networkType); } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to register NetworkScoreCache for type " + networkType); } } } } @Override public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); synchronized (mScoreCaches) { RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); if (callbackList == null || !callbackList.unregister(scoreCache)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Unable to unregister NetworkScoreCache for type " + networkType); } } else if (callbackList.getRegisteredCallbackCount() == 0) { mScoreCaches.remove(networkType); } } mScoreCaches.put(networkType, scoreCache); } } } } Loading @@ -430,7 +470,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } @Override @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) { mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer(); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer(); if (currentScorer == null) { if (currentScorer == null) { Loading @@ -439,13 +479,17 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } writer.println("Current scorer: " + currentScorer.mPackageName); writer.println("Current scorer: " + currentScorer.mPackageName); for (INetworkScoreCache scoreCache : getScoreCaches()) { sendCallback(new Consumer<INetworkScoreCache>() { @Override public void accept(INetworkScoreCache networkScoreCache) { try { try { TransferPipe.dumpAsync(scoreCache.asBinder(), fd, args); TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args); } catch (IOException | RemoteException e) { } catch (IOException | RemoteException e) { writer.println("Failed to dump score cache: " + e); writer.println("Failed to dump score cache: " + e); } } } } }, getScoreCacheLists()); if (mServiceConnection != null) { if (mServiceConnection != null) { mServiceConnection.dump(fd, writer, args); mServiceConnection.dump(fd, writer, args); } else { } else { Loading @@ -455,14 +499,30 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } /** /** * Returns a set of all score caches that are currently active. * Returns a {@link Collection} of all {@link RemoteCallbackList}s that are currently active. * * * <p>May be used to perform an action on all score caches without potentially strange behavior * <p>May be used to perform an action on all score caches without potentially strange behavior * if a new scorer is registered during that action's execution. * if a new scorer is registered during that action's execution. */ */ private Set<INetworkScoreCache> getScoreCaches() { private Collection<RemoteCallbackList<INetworkScoreCache>> getScoreCacheLists() { synchronized (mScoreCaches) { synchronized (mScoreCaches) { return new HashSet<>(mScoreCaches.values()); return new ArrayList<>(mScoreCaches.values()); } } private void sendCallback(Consumer<INetworkScoreCache> consumer, Collection<RemoteCallbackList<INetworkScoreCache>> remoteCallbackLists) { for (RemoteCallbackList<INetworkScoreCache> callbackList : remoteCallbackLists) { synchronized (callbackList) { // Ensure only one active broadcast per RemoteCallbackList final int count = callbackList.beginBroadcast(); try { for (int i = 0; i < count; i++) { consumer.accept(callbackList.getBroadcastItem(i)); } } finally { callbackList.finishBroadcast(); } } } } } } Loading
services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java 0 → 100644 +422 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,21 @@ public class MockUtils { return Mockito.argThat(m); return Mockito.argThat(m); } } public static Intent checkIntent(final Intent intent) { final Matcher<Intent> m = new BaseMatcher<Intent>() { @Override public boolean matches(Object item) { if (item == null) return false; return intent.filterEquals((Intent) item); } @Override public void describeTo(Description description) { description.appendText(intent.toString()); } }; return Mockito.argThat(m); } public static Bundle checkUserRestrictions(String... keys) { public static Bundle checkUserRestrictions(String... keys) { final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys)); final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys)); final Matcher<Bundle> m = new BaseMatcher<Bundle>() { final Matcher<Bundle> m = new BaseMatcher<Bundle>() { Loading