Initial implementation of NetworkScoreManager's backing service.
This service will ultimately be responsible for propagating scores down to lower-level network subsystems. For now, it just keeps scores in memory and exposes these for debugging purposes via "adb shell dumpsys network_score". This change also adds provisioning of a default scorer. When NetworkScoreService is first initialized, it checks to see if it has ever set a default scorer; if not, it reads a package name from a build config property and attempts to set it as the default. Also add autogenerated equals/hashCode methods to all parcelables. Bug: 14111427 Bug: 13786258 Change-Id: I02271171653d42e12acd240b73b9e23950744f6b
This commit is contained in:
@@ -155,6 +155,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/INetworkScoreService.aidl \
|
||||
core/java/android/net/INetworkStatsService.aidl \
|
||||
core/java/android/net/INetworkStatsSession.aidl \
|
||||
core/java/android/net/nsd/INsdManager.aidl \
|
||||
|
||||
49
core/java/android/net/INetworkScoreService.aidl
Normal file
49
core/java/android/net/INetworkScoreService.aidl
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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. */
|
||||
@@ -78,6 +86,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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
@@ -79,6 +81,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 + "]";
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.net;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@@ -86,6 +87,21 @@ public class WifiKey implements Parcelable {
|
||||
out.writeString(bssid);
|
||||
}
|
||||
|
||||
@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 + "]";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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());
|
||||
136
services/core/java/com/android/server/NetworkScoreService.java
Normal file
136
services/core/java/com/android/server/NetworkScoreService.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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 com.android.server;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.INetworkScoreService;
|
||||
import android.net.NetworkKey;
|
||||
import android.net.NetworkScorerAppManager;
|
||||
import android.net.RssiCurve;
|
||||
import android.net.ScoredNetwork;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Backing service for {@link android.net.NetworkScoreManager}.
|
||||
* @hide
|
||||
*/
|
||||
public class NetworkScoreService extends INetworkScoreService.Stub {
|
||||
private static final String TAG = "NetworkScoreService";
|
||||
|
||||
/** SharedPreference bit set to true after the service is first initialized. */
|
||||
private static final String PREF_SCORING_PROVISIONED = "is_provisioned";
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
// TODO: Delete this temporary class once we have a real place for scores.
|
||||
private final Map<NetworkKey, RssiCurve> mScoredNetworks;
|
||||
|
||||
public NetworkScoreService(Context context) {
|
||||
mContext = context;
|
||||
mScoredNetworks = new HashMap<>();
|
||||
}
|
||||
|
||||
/** Called when the system is ready to run third-party code but before it actually does so. */
|
||||
void systemReady() {
|
||||
SharedPreferences prefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE);
|
||||
if (!prefs.getBoolean(PREF_SCORING_PROVISIONED, false)) {
|
||||
// On first run, we try to initialize the scorer to the one configured at build time.
|
||||
// This will be a no-op if the scorer isn't actually valid.
|
||||
String defaultPackage = mContext.getResources().getString(
|
||||
R.string.config_defaultNetworkScorerPackageName);
|
||||
if (!TextUtils.isEmpty(defaultPackage)) {
|
||||
NetworkScorerAppManager.setActiveScorer(mContext, defaultPackage);
|
||||
}
|
||||
prefs.edit().putBoolean(PREF_SCORING_PROVISIONED, true).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateScores(ScoredNetwork[] networks) {
|
||||
if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
|
||||
throw new SecurityException("Caller with UID " + getCallingUid() +
|
||||
" is not the active scorer.");
|
||||
}
|
||||
|
||||
// TODO: Propagate these scores down to the network subsystem layer instead of just holding
|
||||
// them in memory.
|
||||
for (ScoredNetwork network : networks) {
|
||||
mScoredNetworks.put(network.networkKey, network.rssiCurve);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearScores() {
|
||||
// Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETWORKS) should
|
||||
// be allowed to flush all scores.
|
||||
if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) ||
|
||||
mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) ==
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
clearInternal();
|
||||
return true;
|
||||
} else {
|
||||
throw new SecurityException(
|
||||
"Caller is neither the active scorer nor the scorer manager.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setActiveScorer(String packageName) {
|
||||
mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
|
||||
// Preemptively clear scores even though the set operation could fail. We do this for safety
|
||||
// as scores should never be compared across apps; in practice, Settings should only be
|
||||
// allowing valid apps to be set as scorers, so failure here should be rare.
|
||||
clearInternal();
|
||||
return NetworkScorerAppManager.setActiveScorer(mContext, packageName);
|
||||
}
|
||||
|
||||
/** Clear scores. Callers are responsible for checking permissions as appropriate. */
|
||||
private void clearInternal() {
|
||||
// TODO: Propagate the flush down to the network subsystem layer.
|
||||
mScoredNetworks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
|
||||
String currentScorer = NetworkScorerAppManager.getActiveScorer(mContext);
|
||||
if (currentScorer == null) {
|
||||
writer.println("Scoring is disabled.");
|
||||
return;
|
||||
}
|
||||
writer.println("Current scorer: " + currentScorer);
|
||||
if (mScoredNetworks.isEmpty()) {
|
||||
writer.println("No networks scored.");
|
||||
} else {
|
||||
for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) {
|
||||
writer.println(entry.getKey() + ": " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +311,7 @@ public final class SystemServer {
|
||||
NetworkStatsService networkStats = null;
|
||||
NetworkPolicyManagerService networkPolicy = null;
|
||||
ConnectivityService connectivity = null;
|
||||
NetworkScoreService networkScore = null;
|
||||
NsdService serviceDiscovery= null;
|
||||
IPackageManager pm = null;
|
||||
WindowManagerService wm = null;
|
||||
@@ -642,6 +643,14 @@ public final class SystemServer {
|
||||
reportWtf("starting Connectivity Service", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "Network Score Service");
|
||||
networkScore = new NetworkScoreService(context);
|
||||
ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
|
||||
} catch (Throwable e) {
|
||||
reportWtf("starting Network Score Service", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "Network Service Discovery Service");
|
||||
serviceDiscovery = NsdService.create(context);
|
||||
@@ -1021,6 +1030,7 @@ public final class SystemServer {
|
||||
final NetworkStatsService networkStatsF = networkStats;
|
||||
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
|
||||
final ConnectivityService connectivityF = connectivity;
|
||||
final NetworkScoreService networkScoreF = networkScore;
|
||||
final DockObserver dockF = dock;
|
||||
final WallpaperManagerService wallpaperF = wallpaper;
|
||||
final InputMethodManagerService immF = imm;
|
||||
@@ -1068,6 +1078,11 @@ public final class SystemServer {
|
||||
} catch (Throwable e) {
|
||||
reportWtf("making Battery Service ready", e);
|
||||
}
|
||||
try {
|
||||
if (networkScoreF != null) networkScoreF.systemReady();
|
||||
} catch (Throwable e) {
|
||||
reportWtf("making Network Score Service ready", e);
|
||||
}
|
||||
try {
|
||||
if (networkManagementF != null) networkManagementF.systemReady();
|
||||
} catch (Throwable e) {
|
||||
|
||||
Reference in New Issue
Block a user