diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/net/INetworkScoreService.aidl | 49 | ||||
-rw-r--r-- | core/java/android/net/NetworkKey.java | 23 | ||||
-rw-r--r-- | core/java/android/net/NetworkScoreManager.java | 73 | ||||
-rw-r--r-- | core/java/android/net/NetworkScorerAppManager.java (renamed from core/java/android/net/NetworkScorerApplication.java) | 20 | ||||
-rw-r--r-- | core/java/android/net/RssiCurve.java | 27 | ||||
-rw-r--r-- | core/java/android/net/ScoredNetwork.java | 18 | ||||
-rw-r--r-- | core/java/android/net/WifiKey.java | 16 | ||||
-rw-r--r-- | core/res/res/values/config.xml | 2 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
-rw-r--r-- | core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java (renamed from core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java) | 4 |
10 files changed, 213 insertions, 20 deletions
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl new file mode 100644 index 0000000..a72d9a0 --- /dev/null +++ b/core/java/android/net/INetworkScoreService.aidl @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.ScoredNetwork; + +/** + * A service for updating network scores from a network scorer application. + * @hide + */ +interface INetworkScoreService +{ + /** + * Update scores. + * @return whether the update was successful. + * @throws SecurityException if the caller is not the current active scorer. + */ + boolean updateScores(in ScoredNetwork[] networks); + + /** + * Clear all scores. + * @return whether the clear was successful. + * @throws SecurityException if the caller is neither the current active scorer nor the scorer + * manager. + */ + boolean clearScores(); + + /** + * Set the active scorer and clear existing scores. + * @param packageName the package name of the new scorer to use. + * @return true if the operation succeeded, or false if the new package is not a valid scorer. + * @throws SecurityException if the caller is not the scorer manager. + */ + boolean setActiveScorer(in String packageName); +} diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index cc3ad3e..bc19658 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -19,11 +19,19 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Information which identifies a specific network. * * @hide */ +// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific +// type, so that all networks appear the same and can be scored without concern to the network type +// itself. However, because no such cross-type identifier currently exists in the Android framework, +// and because systems might obtain information about networks from sources other than Android +// devices, we need to provide identifying details about each specific network type (wifi, cell, +// etc.) so that clients can pull out these details depending on the type of network. public class NetworkKey implements Parcelable { /** A wifi network, for which {@link #wifiKey} will be populated. */ @@ -79,6 +87,21 @@ public class NetworkKey implements Parcelable { } @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + NetworkKey that = (NetworkKey) o; + + return type == that.type && Objects.equals(wifiKey, that.wifiKey); + } + + @Override + public int hashCode() { + return Objects.hash(type, wifiKey); + } + + @Override public String toString() { switch (type) { case TYPE_WIFI: diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 3430547..5e61613 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -19,6 +19,9 @@ package android.net; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; /** * Class that manages communication between network subsystems and a network scorer. @@ -40,7 +43,7 @@ import android.content.Context; * <p>The system keeps track of a default scorer application; at any time, only this application * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call * {@link #updateScores}. Applications may determine the current default scorer with - * {@link #getDefaultScorerPackage()} and request to change the default scorer by sending an + * {@link #getActiveScorerPackage()} and request to change the default scorer by sending an * {@link #ACTION_CHANGE_DEFAULT} broadcast with another scorer. * * @hide @@ -81,38 +84,82 @@ public class NetworkScoreManager { public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; private final Context mContext; + private final INetworkScoreService mService; /** @hide */ public NetworkScoreManager(Context context) { mContext = context; + IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE); + mService = INetworkScoreService.Stub.asInterface(iBinder); } /** - * Obtain the package name of the current default network scorer. + * Obtain the package name of the current active network scorer. * - * At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS} + * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS} * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to * determine the current scorer and offer the user the ability to select a different scorer via * the {@link #ACTION_CHANGE_DEFAULT} intent. - * @return the full package name of the current default scorer, or null if there is no active + * @return the full package name of the current active scorer, or null if there is no active * scorer. */ - public String getDefaultScorerPackage() { - // TODO: Implement. - return null; + public String getActiveScorerPackage() { + return NetworkScorerAppManager.getActiveScorer(mContext); } /** * Update network scores. * - * This may be called at any time to re-score active networks. Scores will generally be updated - * quickly, but if this method is called too frequently, the scores may be held and applied at - * a later time. + * <p>This may be called at any time to re-score active networks. Scores will generally be + * updated quickly, but if this method is called too frequently, the scores may be held and + * applied at a later time. * * @param networks the networks which have been scored by the scorer. - * @throws SecurityException if the caller is not the default scorer. + * @return whether the update was successful. + * @throws SecurityException if the caller is not the active scorer. */ - public void updateScores(ScoredNetwork[] networks) throws SecurityException { - // TODO: Implement. + public boolean updateScores(ScoredNetwork[] networks) throws SecurityException { + try { + return mService.updateScores(networks); + } catch (RemoteException e) { + return false; + } + } + + /** + * Clear network scores. + * + * <p>Should be called when all scores need to be invalidated, i.e. because the scoring + * algorithm has changed and old scores can no longer be compared to future scores. + * + * <p>Note that scores will be cleared automatically when the active scorer changes, as scores + * from one scorer cannot be compared to those from another scorer. + * + * @return whether the clear was successful. + * @throws SecurityException if the caller is not the active scorer or privileged. + */ + public boolean clearScores() throws SecurityException { + try { + return mService.clearScores(); + } catch (RemoteException e) { + return false; + } + } + + /** + * Set the active scorer to a new package and clear existing scores. + * + * @return true if the operation succeeded, or false if the new package is not a valid scorer. + * @throws SecurityException if the caller does not hold the + * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that + * it can manage scorer applications. + * @hide + */ + public boolean setActiveScorer(String packageName) throws SecurityException { + try { + return mService.setActiveScorer(packageName); + } catch (RemoteException e) { + return false; + } } } diff --git a/core/java/android/net/NetworkScorerApplication.java b/core/java/android/net/NetworkScorerAppManager.java index b137ad3..726208a 100644 --- a/core/java/android/net/NetworkScorerApplication.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo; import android.provider.Settings; import android.provider.Settings.Global; import android.text.TextUtils; +import android.util.Log; import java.util.ArrayList; import java.util.Collection; @@ -36,13 +37,14 @@ import java.util.List; * * @hide */ -public final class NetworkScorerApplication { +public final class NetworkScorerAppManager { + private static final String TAG = "NetworkScorerAppManager"; private static final Intent SCORE_INTENT = new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS); /** This class cannot be instantiated. */ - private NetworkScorerApplication() {} + private NetworkScorerAppManager() {} /** * Returns the list of available scorer app package names. @@ -111,30 +113,38 @@ public final class NetworkScorerApplication { * @param context the context of the calling application * @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. + * @return true if the scorer was changed, or false if the package is not a valid scorer. */ - public static void setActiveScorer(Context context, String packageName) { + public static boolean setActiveScorer(Context context, String packageName) { String oldPackageName = Settings.Global.getString(context.getContentResolver(), Settings.Global.NETWORK_SCORER_APP); if (TextUtils.equals(oldPackageName, packageName)) { // No change. - return; + return true; } + Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName); + if (packageName == null) { Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP, null); + return true; } else { // We only make the change if the new package is valid. Collection<String> applications = getAllValidScorers(context); if (isPackageValidScorer(applications, packageName)) { Settings.Global.putString(context.getContentResolver(), Settings.Global.NETWORK_SCORER_APP, packageName); + return true; + } else { + Log.w(TAG, "Requested network scorer is not valid: " + packageName); + return false; } } } /** Determine whether the application with the given UID is the enabled scorer. */ - public static boolean isCallerDefaultScorer(Context context, int callingUid) { + public static boolean isCallerActiveScorer(Context context, int callingUid) { String defaultApp = getActiveScorer(context); if (defaultApp == null) { return false; diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java index 7af7998..33e81c2 100644 --- a/core/java/android/net/RssiCurve.java +++ b/core/java/android/net/RssiCurve.java @@ -19,6 +19,9 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; +import java.util.Objects; + /** * A curve defining the network score over a range of RSSI values. * @@ -94,6 +97,30 @@ public class RssiCurve implements Parcelable { out.writeByteArray(rssiBuckets); } + /** + * Determine if two RSSI curves are defined in the same way. + * + * <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one + * curve is split into two buckets in another. For the purpose of this method, these curves are + * not considered equal to each other. + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RssiCurve rssiCurve = (RssiCurve) o; + + return start == rssiCurve.start && + bucketWidth == rssiCurve.bucketWidth && + Arrays.equals(rssiBuckets, rssiCurve.rssiBuckets); + } + + @Override + public int hashCode() { + return Objects.hash(start, bucketWidth, rssiBuckets); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java index 8af3c3c..7902313 100644 --- a/core/java/android/net/ScoredNetwork.java +++ b/core/java/android/net/ScoredNetwork.java @@ -19,6 +19,8 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * A network identifier along with a score for the quality of that network. * @@ -80,6 +82,22 @@ public class ScoredNetwork implements Parcelable { } @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ScoredNetwork that = (ScoredNetwork) o; + + return Objects.equals(networkKey, that.networkKey) && + Objects.equals(rssiCurve, that.rssiCurve); + } + + @Override + public int hashCode() { + return Objects.hash(networkKey, rssiCurve); + } + + @Override public String toString() { return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]"; } diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java index ffcd85a..9e92e89 100644 --- a/core/java/android/net/WifiKey.java +++ b/core/java/android/net/WifiKey.java @@ -19,6 +19,7 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; import java.util.regex.Pattern; /** @@ -87,6 +88,21 @@ public class WifiKey implements Parcelable { } @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WifiKey wifiKey = (WifiKey) o; + + return Objects.equals(ssid, wifiKey.ssid) && Objects.equals(bssid, wifiKey.bssid); + } + + @Override + public int hashCode() { + return Objects.hash(ssid, bssid); + } + + @Override public String toString() { return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]"; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2df5dc1..c610146 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1432,4 +1432,6 @@ <!-- default window inset isRound property --> <bool name="config_windowIsRound">false</bool> + <!-- Package name for default network scorer app; overridden by product overlays. --> + <string name="config_defaultNetworkScorerPackageName"></string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 03c617a..26efe36 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1625,6 +1625,7 @@ <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" /> <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" /> <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" /> + <java-symbol type="string" name="config_defaultNetworkScorerPackageName" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> diff --git a/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java index 6d5ede8..cac6b93 100644 --- a/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java +++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java @@ -33,7 +33,7 @@ import org.mockito.MockitoAnnotations; import java.util.Iterator; -public class NetworkScorerApplicationTest extends InstrumentationTestCase { +public class NetworkScorerAppManagerTest extends InstrumentationTestCase { @Mock private Context mMockContext; @Mock private PackageManager mMockPm; @@ -64,7 +64,7 @@ public class NetworkScorerApplicationTest extends InstrumentationTestCase { setScorers(package1, package2, package3); Iterator<String> result = - NetworkScorerApplication.getAllValidScorers(mMockContext).iterator(); + NetworkScorerAppManager.getAllValidScorers(mMockContext).iterator(); assertTrue(result.hasNext()); assertEquals("package1", result.next()); |