diff --git a/Android.mk b/Android.mk index 966c64dea5f76..48415b3038305 100644 --- a/Android.mk +++ b/Android.mk @@ -157,6 +157,7 @@ LOCAL_SRC_FILES += \ core/java/android/net/INetworkManagementEventObserver.aidl \ core/java/android/net/INetworkPolicyListener.aidl \ core/java/android/net/INetworkPolicyManager.aidl \ + core/java/android/net/INetworkScoreCache.aidl \ core/java/android/net/INetworkScoreService.aidl \ core/java/android/net/INetworkStatsService.aidl \ core/java/android/net/INetworkStatsSession.aidl \ diff --git a/core/java/android/net/INetworkScoreCache.aidl b/core/java/android/net/INetworkScoreCache.aidl new file mode 100644 index 0000000000000..35601ce8b138a --- /dev/null +++ b/core/java/android/net/INetworkScoreCache.aidl @@ -0,0 +1,43 @@ +/** + * 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 which stores a subset of scored networks from the active network scorer. + * + *
To be implemented by network subsystems (e.g. Wi-Fi). NetworkScoreService will propagate + * scores down to each subsystem depending on the network type. Implementations may register for + * a given network type by calling NetworkScoreManager.registerNetworkSubsystem. + * + *
A proper implementation should throw SecurityException whenever the caller is not privileged. + * It may request scores by calling NetworkScoreManager#requestScores(NetworkKey[]); a call to + * updateScores may follow but may not depending on the active scorer's implementation, and in + * general this method may be called at any time. + * + *
Implementations should also override dump() so that "adb shell dumpsys network_score" includes
+ * the current scores for each network for debugging purposes.
+ * @hide
+ */
+interface INetworkScoreCache
+{
+ void updateScores(in List Note that this is just a helper method to assemble the broadcast, and will run in the
+ * calling process.
+ *
+ * @return true if the broadcast was sent, or false if there is no active scorer.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * @hide
+ */
+ public boolean requestScores(NetworkKey[] networks) throws SecurityException {
+ String activeScorer = getActiveScorerPackage();
+ if (activeScorer == null) {
+ return false;
+ }
+ Intent intent = new Intent(ACTION_SCORE_NETWORKS);
+ intent.setPackage(activeScorer);
+ intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
+ mContext.sendBroadcast(intent);
+ return true;
+ }
+
+ /**
+ * Register 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_SCORE_NETWORKS} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ try {
+ mService.registerNetworkScoreCache(networkType, scoreCache);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 33e81c257e23c..dd744d351fc0a 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -97,6 +97,27 @@ public class RssiCurve implements Parcelable {
out.writeByteArray(rssiBuckets);
}
+ /**
+ * Lookup the score for a given RSSI value.
+ *
+ * @param rssi The RSSI to lookup. If the RSSI falls below the start of the curve, the score at
+ * the start of the curve will be returned. If it falls after the end of the curve, the
+ * score at the end of the curve will be returned.
+ * @return the score for the given RSSI.
+ */
+ public byte lookupScore(int rssi) {
+ int index = (rssi - start) / bucketWidth;
+
+ // Snap the index to the closest bucket if it falls outside the curve.
+ if (index < 0) {
+ index = 0;
+ } else if (index > rssiBuckets.length - 1) {
+ index = rssiBuckets.length - 1;
+ }
+
+ return rssiBuckets[index];
+ }
+
/**
* Determine if two RSSI curves are defined in the same way.
*
diff --git a/core/tests/coretests/src/android/net/RssiCurveTest.java b/core/tests/coretests/src/android/net/RssiCurveTest.java
new file mode 100644
index 0000000000000..d4438df6a3524
--- /dev/null
+++ b/core/tests/coretests/src/android/net/RssiCurveTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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 junit.framework.TestCase;
+
+public class RssiCurveTest extends TestCase {
+ public void testLookupScore_constantCurve() {
+ RssiCurve curve = new RssiCurve(-100, 200, new byte[] { 10 });
+ assertEquals(10, curve.lookupScore(-200));
+ assertEquals(10, curve.lookupScore(-100));
+ assertEquals(10, curve.lookupScore(0));
+ assertEquals(10, curve.lookupScore(100));
+ assertEquals(10, curve.lookupScore(200));
+ }
+
+ public void testLookupScore_changingCurve() {
+ RssiCurve curve = new RssiCurve(-100, 100, new byte[] { -10, 10 });
+ assertEquals(-10, curve.lookupScore(-200));
+ assertEquals(-10, curve.lookupScore(-100));
+ assertEquals(-10, curve.lookupScore(-50));
+ assertEquals(10, curve.lookupScore(0));
+ assertEquals(10, curve.lookupScore(50));
+ assertEquals(10, curve.lookupScore(100));
+ assertEquals(10, curve.lookupScore(200));
+ }
+}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 8a30e50c9aaf7..4f0c9b537ff22 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -20,19 +20,24 @@ import android.Manifest.permission;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
-import android.net.NetworkKey;
import android.net.NetworkScorerAppManager;
-import android.net.RssiCurve;
import android.net.ScoredNetwork;
+import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.Log;
import com.android.internal.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Backing service for {@link android.net.NetworkScoreManager}.
@@ -46,12 +51,11 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
private final Context mContext;
- // TODO: Delete this temporary class once we have a real place for scores.
- private final Map 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.
+ */
+ private Set