diff options
| author | 2019-11-25 06:05:07 -0800 | |
|---|---|---|
| committer | 2019-11-25 06:05:07 -0800 | |
| commit | 126fb85c2953e6eb6770c3adbca158400eb3c310 (patch) | |
| tree | 9413f9fdca17f6714c1ee51f7014331de77c8fdc | |
| parent | c376fb681cad6009eba82903e9cd2499c8cd8933 (diff) | |
| parent | 0564779e76a2ba86ddfcd54da1491d6ae30c7cef (diff) | |
Merge "NetworkScoreManager: Add @SystemApi for wifi mainline module" am: 5b57190f08
am: 0564779e76
Change-Id: I04580ad32eefb2ce4c8df8f1037b8457238c30eb
| -rw-r--r-- | api/system-current.txt | 18 | ||||
| -rw-r--r-- | core/java/android/net/NetworkKey.java | 11 | ||||
| -rw-r--r-- | core/java/android/net/NetworkScoreManager.java | 111 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NetworkScoreService.java | 14 | ||||
| -rwxr-xr-x | wifi/java/android/net/wifi/WifiNetworkScoreCache.java | 18 |
5 files changed, 146 insertions, 26 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index ac8581a83511..0b8cdf29a8f4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4179,6 +4179,7 @@ package android.net { public class NetworkKey implements android.os.Parcelable { ctor public NetworkKey(android.net.WifiKey); + method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR; @@ -4201,16 +4202,23 @@ package android.net { method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage(); + method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException; + method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException; - method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException; - field public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; + method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException; + field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE"; field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS"; field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED"; - field public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; - field public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; + field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; + field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; field public static final String EXTRA_NEW_SCORER = "newScorer"; - field public static final String EXTRA_PACKAGE_NAME = "packageName"; + field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName"; + } + + public static interface NetworkScoreManager.NetworkScoreCallback { + method public void clearScores(); + method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>); } public class NetworkStack { diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index 04cb877305b9..9af1407f6007 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -27,6 +28,8 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -48,6 +51,13 @@ public class NetworkKey implements Parcelable { /** A wifi network, for which {@link #wifiKey} will be populated. */ public static final int TYPE_WIFI = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"TYPE_"}, value = { + TYPE_WIFI + }) + public @interface NetworkType {} + /** * The type of this network. * @see #TYPE_WIFI @@ -65,7 +75,6 @@ public class NetworkKey implements Parcelable { * * @return A new {@link NetworkKey} instance or <code>null</code> if the given * {@link ScanResult} instance is malformed. - * @hide */ @Nullable public static NetworkKey createFromScanResult(@Nullable ScanResult result) { diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 50dd468aa905..f6dc52522cb2 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -17,7 +17,9 @@ package android.net; import android.Manifest.permission; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; @@ -25,13 +27,16 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; +import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.concurrent.Executor; /** * Class that manages communication between network subsystems and a network scorer. @@ -50,19 +55,25 @@ import java.util.List; @SystemApi @SystemService(Context.NETWORK_SCORE_SERVICE) public class NetworkScoreManager { + private static final String TAG = "NetworkScoreManager"; + /** * Activity action: ask the user to change the active network scorer. This will show a dialog * that asks the user whether they want to replace the current active scorer with the one * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the * active scorer was changed or RESULT_CANCELED if it failed for any reason. + * @deprecated No longer sent. */ + @Deprecated @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; /** * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with * {@link android.content.Intent#putExtra(String, String)}. + * @deprecated No longer sent. */ + @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName"; /** @@ -73,7 +84,9 @@ public class NetworkScoreManager { * configured by the user as well as any open networks. * * <p class="note">This is a protected intent that can only be sent by the system. + * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead. */ + @Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; @@ -81,7 +94,9 @@ public class NetworkScoreManager { * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an * array of {@link NetworkKey}s. Can be obtained with * {@link android.content.Intent#getParcelableArrayExtra(String)}}. + * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead. */ + @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; /** @@ -285,7 +300,7 @@ public class NetworkScoreManager { * @throws SecurityException if the caller is not the active scorer. */ @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) - public boolean updateScores(ScoredNetwork[] networks) throws SecurityException { + public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException { try { return mService.updateScores(networks); } catch (RemoteException e) { @@ -359,13 +374,21 @@ public class NetworkScoreManager { /** * Request scoring for networks. * - * @return true if the broadcast was sent, or false if there is no active scorer. + * <p> + * Note: The results (i.e scores) for these networks, when available will be provided via the + * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor, + * NetworkScoreCallback)}. The calling module is responsible for registering a callback to + * receive the results before requesting new scores via this API. + * + * @return true if the request was successfully sent, or false if there is no active scorer. * @throws SecurityException if the caller does not hold the * {@link permission#REQUEST_NETWORK_SCORES} permission. + * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) - public boolean requestScores(NetworkKey[] networks) throws SecurityException { + public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException { try { return mService.requestScores(networks); } catch (RemoteException e) { @@ -431,6 +454,88 @@ public class NetworkScoreManager { } /** + * Base class for network score cache callback. Should be extended by applications and set + * when calling {@link #registerNetworkScoreCallback(int, int, NetworkScoreCallback, + * Executor)} + * + * @hide + */ + @SystemApi + public interface NetworkScoreCallback { + /** + * Called when a new set of network scores are available. + * This is triggered in response when the client invokes + * {@link #requestScores(NetworkKey[])} to score a new set of networks. + * + * @param networks List of {@link ScoredNetwork} containing updated scores. + */ + void updateScores(@NonNull List<ScoredNetwork> networks); + + /** + * Invokes when all the previously provided scores are no longer valid. + */ + void clearScores(); + } + + /** + * Callback proxy for {@link NetworkScoreCallback} objects. + */ + private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub { + private final Executor mExecutor; + private final NetworkScoreCallback mCallback; + + NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) { + mExecutor = executor; + mCallback = callback; + } + + @Override + public void updateScores(@NonNull List<ScoredNetwork> networks) { + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.updateScores(networks); + }); + } + + @Override + public void clearScores() { + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.clearScores(); + }); + } + } + + /** + * Register a network score callback. + * + * @param networkType the type of network this cache can handle. See {@link NetworkKey#type} + * @param filterType the {@link CacheUpdateFilter} to apply + * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the + * scores change. + * @param executor The executor on which to execute the callbacks. + * @throws SecurityException if the caller does not hold the + * {@link permission#REQUEST_NETWORK_SCORES} permission. + * @throws IllegalArgumentException if a callback is already registered for this type. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) + public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType, + @CacheUpdateFilter int filterType, + @NonNull @CallbackExecutor Executor executor, + @NonNull NetworkScoreCallback callback) throws SecurityException { + if (callback == null || executor == null) { + throw new IllegalArgumentException("callback / executor cannot be null"); + } + Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor=" + + executor); + // Use the @hide method. + registerNetworkScoreCache( + networkType, new NetworkScoreCallbackProxy(executor, callback), filterType); + } + + /** * Determine whether the application with the given UID is the enabled scorer. * * @param callingUid the UID to check diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 80d7ac931111..9a7a4e79ab33 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -60,12 +60,9 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; -import com.android.internal.os.TransferPipe; -import com.android.internal.telephony.SmsApplication; import com.android.internal.util.DumpUtils; import java.io.FileDescriptor; -import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; @@ -908,17 +905,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } writer.println("Current scorer: " + currentScorer); - sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() { - @Override - public void accept(INetworkScoreCache networkScoreCache, Object cookie) { - try { - TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args); - } catch (IOException | RemoteException e) { - writer.println("Failed to dump score cache: " + e); - } - } - }, getScoreCacheLists()); - synchronized (mServiceConnectionLock) { if (mServiceConnection != null) { mServiceConnection.dump(fd, writer, args); diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java index b22ae07015c8..5a212a824452 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.content.Context; import android.net.INetworkScoreCache; import android.net.NetworkKey; +import android.net.NetworkScoreManager; import android.net.ScoredNetwork; import android.os.Handler; import android.os.Process; @@ -40,7 +41,8 @@ import java.util.List; * * @hide */ -public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { +public class WifiNetworkScoreCache extends INetworkScoreCache.Stub + implements NetworkScoreManager.NetworkScoreCallback { private static final String TAG = "WifiNetworkScoreCache"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); @@ -246,6 +248,17 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + dumpWithLatestScanResults(fd, writer, args, wifiManager.getScanResults()); + } + + /** + * This is directly invoked from within Wifi-Service (on it's instance of this class), hence + * avoid making the WifiManager.getScanResults() call to avoid a deadlock. + */ + public final void dumpWithLatestScanResults( + FileDescriptor fd, PrintWriter writer, String[] args, + List<ScanResult> latestScanResults) { mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); String header = String.format("WifiNetworkScoreCache (%s/%d)", mContext.getPackageName(), Process.myUid()); @@ -256,8 +269,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { writer.println(" " + score); } writer.println(" Network scores for latest ScanResults:"); - WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - for (ScanResult scanResult : wifiManager.getScanResults()) { + for (ScanResult scanResult : latestScanResults) { writer.println( " " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); } |