Add public fields to NetworkScore and make it @SystemApi
Bug: 113554781
Bug: 146583853
Test: FrameworksNetTests
Change-Id: I19d965c0146196cb67b3417eb1790ccd90ce3233
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ce9693d..fa12c08 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3322,15 +3322,19 @@
// of dependent changes that would conflict throughout the automerger graph. Having this
// temporarily helps with the process of going through with all these dependent changes across
// the entire tree.
+ // STOPSHIP (b/148055573) : remove this before R is released.
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
* @return Network corresponding to NetworkAgent.
+ * @deprecated use the version that takes a NetworkScore and a provider ID.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @Deprecated
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config) {
- return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
+ final NetworkScore ns = new NetworkScore.Builder().setLegacyScore(score).build();
+ return registerNetworkAgent(messenger, ni, lp, nc, ns, config, NetworkProvider.ID_NONE);
}
/**
@@ -3340,7 +3344,7 @@
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
- NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
+ NetworkCapabilities nc, NetworkScore score, NetworkAgentConfig config, int providerId) {
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
} catch (RemoteException e) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 186196bd..c58ffd5 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -25,6 +25,7 @@
import android.net.NetworkInfo;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkState;
import android.net.ISocketKeepaliveCallback;
import android.net.ProxyInfo;
@@ -153,7 +154,7 @@
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
- in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
+ in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config,
in int factorySerialNumber);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 7cc569a..ddf8dbb 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -117,13 +117,6 @@
public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
/**
- * Centralize the place where base network score, and network score scaling, will be
- * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE
- * @hide
- */
- public static final int WIFI_BASE_SCORE = 60;
-
- /**
* Sent by the NetworkAgent to ConnectivityService to pass the current
* network score.
* obj = network score Integer
@@ -272,7 +265,13 @@
*/
public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
+ // STOPSHIP (b/148055573) : remove this before R is released.
+ private static NetworkScore makeNetworkScore(int score) {
+ return new NetworkScore.Builder().setLegacyScore(score).build();
+ }
+
/** @hide TODO: remove and replace usage with the public constructor. */
+ // STOPSHIP (b/148055573) : remove this before R is released.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE);
@@ -280,6 +279,7 @@
}
/** @hide TODO: remove and replace usage with the public constructor. */
+ // STOPSHIP (b/148055573) : remove this before R is released.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) {
this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE);
@@ -287,6 +287,7 @@
}
/** @hide TODO: remove and replace usage with the public constructor. */
+ // STOPSHIP (b/148055573) : remove this before R is released.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, int providerId) {
this(looper, context, logTag, ni, nc, lp, score, null, providerId);
@@ -294,10 +295,12 @@
}
/** @hide TODO: remove and replace usage with the public constructor. */
+ // STOPSHIP (b/148055573) : remove this before R is released.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config,
int providerId) {
- this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */);
+ this(looper, context, logTag, nc, lp, makeNetworkScore(score), config, providerId, ni,
+ true /* legacy */);
register();
}
@@ -323,8 +326,9 @@
* @param provider the {@link NetworkProvider} managing this agent.
*/
public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
- @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
- @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
+ @NonNull NetworkScore score, @NonNull NetworkAgentConfig config,
+ @Nullable NetworkProvider provider) {
this(looper, context, logTag, nc, lp, score, config,
provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
getLegacyNetworkInfo(config), false /* legacy */);
@@ -334,12 +338,12 @@
public final Context context;
public final NetworkCapabilities capabilities;
public final LinkProperties properties;
- public final int score;
+ public final NetworkScore score;
public final NetworkAgentConfig config;
public final NetworkInfo info;
InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities,
- @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config,
- @NonNull NetworkInfo info) {
+ @NonNull LinkProperties properties, @NonNull NetworkScore score,
+ @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) {
this.context = context;
this.capabilities = capabilities;
this.properties = properties;
@@ -351,7 +355,7 @@
private volatile InitialConfiguration mInitialConfiguration;
private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
- @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, NetworkScore score,
@NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni,
boolean legacy) {
mHandler = new NetworkAgentHandler(looper);
@@ -646,22 +650,8 @@
* Must be called by the agent to update the score of this network.
* @param score the new score.
*/
- public void sendNetworkScore(int score) {
- if (score < 0) {
- throw new IllegalArgumentException("Score must be >= 0");
- }
- final NetworkScore ns = new NetworkScore();
- ns.putIntExtension(NetworkScore.LEGACY_SCORE, score);
- updateScore(ns);
- }
-
- /**
- * Must be called by the agent when it has a new {@link NetworkScore} for this network.
- * @param ns the new score.
- * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore.
- */
- public void updateScore(@NonNull NetworkScore ns) {
- queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns));
+ public void sendNetworkScore(@NonNull final NetworkScore score) {
+ queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score);
}
/**
diff --git a/core/java/android/net/NetworkScore.aidl b/core/java/android/net/NetworkScore.aidl
new file mode 100644
index 0000000..be9a98b
--- /dev/null
+++ b/core/java/android/net/NetworkScore.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2020, 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;
+
+parcelable NetworkScore;
diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java
index 13f2994..ae17378 100644
--- a/core/java/android/net/NetworkScore.java
+++ b/core/java/android/net/NetworkScore.java
@@ -15,12 +15,18 @@
*/
package android.net;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -28,57 +34,392 @@
*
* A NetworkScore object represents the characteristics of a network that affects how good the
* network is considered for a particular use.
+ *
+ * This class is not thread-safe.
* @hide
*/
+@TestApi
+@SystemApi
public final class NetworkScore implements Parcelable {
+ /** An object containing scoring-relevant metrics for a network. */
+ public static class Metrics {
+ /** Value meaning the latency is unknown. */
+ public static final int LATENCY_UNKNOWN = -1;
- // The key of bundle which is used to get the legacy network score of NetworkAgentInfo.
- // TODO: Remove this when the transition to NetworkScore is over.
- public static final String LEGACY_SCORE = "LEGACY_SCORE";
+ /** Value meaning the bandwidth is unknown. */
+ public static final int BANDWIDTH_UNKNOWN = -1;
+
+ /**
+ * Round-trip delay in milliseconds to the relevant destination for this Metrics object.
+ *
+ * LATENCY_UNKNOWN if unknown.
+ */
+ @IntRange(from = LATENCY_UNKNOWN)
+ public final int latencyMs;
+
+ /**
+ * Downlink in kB/s with the relevant destination for this Metrics object.
+ *
+ * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink
+ * bandwidth can have the same value.
+ */
+ @IntRange(from = BANDWIDTH_UNKNOWN)
+ public final int downlinkBandwidthKBps;
+
+ /**
+ * Uplink in kB/s with the relevant destination for this Metrics object.
+ *
+ * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink
+ * bandwidth can have the same value.
+ */
+ @IntRange(from = BANDWIDTH_UNKNOWN)
+ public final int uplinkBandwidthKBps;
+
+ /** Constructor */
+ public Metrics(@IntRange(from = LATENCY_UNKNOWN) final int latency,
+ @IntRange(from = BANDWIDTH_UNKNOWN) final int downlinkBandwidth,
+ @IntRange(from = BANDWIDTH_UNKNOWN) final int uplinkBandwidth) {
+ latencyMs = latency;
+ downlinkBandwidthKBps = downlinkBandwidth;
+ uplinkBandwidthKBps = uplinkBandwidth;
+ }
+
+ /** toString */
+ public String toString() {
+ return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps
+ + "uplinkBandwidth = " + uplinkBandwidthKBps;
+ }
+
+ @NonNull
+ public static final Metrics EMPTY =
+ new Metrics(LATENCY_UNKNOWN, BANDWIDTH_UNKNOWN, BANDWIDTH_UNKNOWN);
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = "POLICY_", value = {
+ POLICY_LOCKDOWN_VPN,
+ POLICY_VPN,
+ POLICY_IGNORE_ON_WIFI,
+ POLICY_DEFAULT_SUBSCRIPTION
+ })
+ public @interface Policy {
+ }
+
+ /**
+ * This network is a VPN with lockdown enabled.
+ *
+ * If a network with this bit is present in the list of candidates and not connected,
+ * no network can satisfy the request.
+ */
+ public static final int POLICY_LOCKDOWN_VPN = 1 << 0;
+
+ /**
+ * This network is a VPN.
+ *
+ * If a network with this bit is present and the request UID is included in the UID ranges
+ * of this network, it outscores all other networks without this bit.
+ */
+ public static final int POLICY_VPN = 1 << 1;
+
+ /**
+ * This network should not be used if a previously validated WiFi network is available.
+ *
+ * If a network with this bit is present and a previously validated WiFi is present too, the
+ * network with this bit is outscored by it. This stays true if the WiFi network
+ * becomes unvalidated : this network will not be considered.
+ */
+ public static final int POLICY_IGNORE_ON_WIFI = 1 << 2;
+
+ /**
+ * This network is the default subscription for this transport.
+ *
+ * If a network with this bit is present, other networks of the same transport without this
+ * bit are outscored by it. A device with two active subscriptions and a setting
+ * to decide the default one would have this policy bit on the network for the default
+ * subscription so that when both are active at the same time, the device chooses the
+ * network associated with the default subscription rather than the one with the best link
+ * quality (which will happen if policy doesn't dictate otherwise).
+ */
+ public static final int POLICY_DEFAULT_SUBSCRIPTION = 1 << 3;
+
+ /**
+ * Policy bits for this network. Filled in by the NetworkAgent.
+ */
+ private final int mPolicy;
+
+ /**
+ * Predicted metrics to the gateway (it contains latency and bandwidth to the gateway).
+ * This is filled by the NetworkAgent with the theoretical values of the link if available,
+ * although they may fill it with predictions from historical data if available.
+ * Note that while this member cannot be null, any and all of its members can be unknown.
+ */
@NonNull
- private final Bundle mExtensions;
+ private final Metrics mLinkLayerMetrics;
- public NetworkScore() {
- mExtensions = new Bundle();
- }
+ /**
+ * Predicted metrics to representative servers.
+ * This is filled by connectivity with (if available) a best-effort estimate of the performance
+ * information to servers the user connects to in similar circumstances, and predicted from
+ * actual measurements if possible.
+ * Note that while this member cannot be null, any and all of its members can be unknown.
+ */
+ @NonNull
+ private final Metrics mEndToEndMetrics;
- public NetworkScore(@NonNull NetworkScore source) {
- mExtensions = new Bundle(source.mExtensions);
+ /** Value meaning the signal strength is unknown. */
+ public static final int UNKNOWN_SIGNAL_STRENGTH = -1;
+
+ /** The smallest meaningful signal strength. */
+ public static final int MIN_SIGNAL_STRENGTH = 0;
+
+ /** The largest meaningful signal strength. */
+ public static final int MAX_SIGNAL_STRENGTH = 1000;
+
+ /**
+ * User-visible measure of the strength of the signal normalized 1~1000.
+ * This represents a measure of the signal strength for this network.
+ * If unknown, this has value UNKNOWN_SIGNAL_STRENGTH.
+ */
+ // A good way to populate this value is to fill it with the number of bars displayed in
+ // the system UI, scaled 0 to 1000. This is what the user sees and it makes sense to them.
+ // Cellular for example could quantize the ASU value (see SignalStrength#getAsuValue) into
+ // this, while WiFi could scale the RSSI (see WifiManager#calculateSignalLevel).
+ @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH)
+ private final int mSignalStrength;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = "RANGE_", value = {
+ RANGE_UNKNOWN, RANGE_CLOSE, RANGE_SHORT, RANGE_MEDIUM, RANGE_LONG
+ })
+ public @interface Range {
}
/**
- * Put the value of parcelable inside the bundle by key.
+ * The range of this network is not known.
+ * This can be used by VPN the range of which depends on the range of the underlying network.
*/
- public void putExtension(@Nullable String key, @Nullable Parcelable value) {
- mExtensions.putParcelable(key, value);
+ public static final int RANGE_UNKNOWN = 0;
+
+ /**
+ * This network typically only operates at close range, like an NFC beacon.
+ */
+ public static final int RANGE_CLOSE = 1;
+
+ /**
+ * This network typically operates at a range of a few meters to a few dozen meters, like WiFi.
+ */
+ public static final int RANGE_SHORT = 2;
+
+ /**
+ * This network typically operates at a range of a few dozen to a few hundred meters, like CBRS.
+ */
+ public static final int RANGE_MEDIUM = 3;
+
+ /**
+ * This network typically offers continuous connectivity up to many kilometers away, like LTE.
+ */
+ public static final int RANGE_LONG = 4;
+
+ /**
+ * The typical range of this networking technology.
+ *
+ * This is one of the RANGE_* constants and is filled by the NetworkAgent.
+ * This may be useful when evaluating how desirable a network is, because for two networks that
+ * have equivalent performance and cost, the one that won't lose IP continuity when the user
+ * moves is probably preferable.
+ * Agents should fill this with the largest typical range this technology provides. See the
+ * descriptions of the individual constants for guidance.
+ *
+ * If unknown, this is set to RANGE_UNKNOWN.
+ */
+ @Range private final int mRange;
+
+ /**
+ * A prediction of whether this network is likely to be unusable in a few seconds.
+ *
+ * NetworkAgents set this to true to mean they are aware that usability is limited due to
+ * low signal strength, congestion, or other reasons, and indicates that the system should
+ * only use this network as a last resort. An example would be a WiFi network when the device
+ * is about to move outside of range.
+ *
+ * This is filled by the NetworkAgent. Agents that don't know whether this network is likely
+ * to be unusable soon should set this to false.
+ */
+ private final boolean mExiting;
+
+ /**
+ * The legacy score, as a migration strategy from Q to R.
+ * STOPSHIP : remove this before R ships.
+ */
+ private final int mLegacyScore;
+
+ /**
+ * Create a new NetworkScore object.
+ */
+ private NetworkScore(@Policy final int policy, @Nullable final Metrics l2Perf,
+ @Nullable final Metrics e2ePerf,
+ @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH)
+ final int signalStrength,
+ @Range final int range, final boolean exiting, final int legacyScore) {
+ mPolicy = policy;
+ mLinkLayerMetrics = null != l2Perf ? l2Perf : Metrics.EMPTY;
+ mEndToEndMetrics = null != e2ePerf ? e2ePerf : Metrics.EMPTY;
+ mSignalStrength = signalStrength;
+ mRange = range;
+ mExiting = exiting;
+ mLegacyScore = legacyScore;
}
/**
- * Put the value of int inside the bundle by key.
+ * Utility function to return a copy of this with a different exiting value.
*/
- public void putIntExtension(@Nullable String key, int value) {
- mExtensions.putInt(key, value);
+ @NonNull public NetworkScore withExiting(final boolean exiting) {
+ return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics,
+ mSignalStrength, mRange, exiting, mLegacyScore);
}
/**
- * Get the value of non primitive type by key.
+ * Utility function to return a copy of this with a different signal strength.
*/
- public <T extends Parcelable> T getExtension(@Nullable String key) {
- return mExtensions.getParcelable(key);
+ @NonNull public NetworkScore withSignalStrength(
+ @IntRange(from = UNKNOWN_SIGNAL_STRENGTH) final int signalStrength) {
+ return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics,
+ signalStrength, mRange, mExiting, mLegacyScore);
}
/**
- * Get the value of int by key.
+ * Returns whether this network has a particular policy flag.
+ * @param policy the policy, as one of the POLICY_* constants.
*/
- public int getIntExtension(@Nullable String key) {
- return mExtensions.getInt(key);
+ public boolean hasPolicy(@Policy final int policy) {
+ return 0 != (mPolicy & policy);
}
/**
- * Remove the entry by given key.
+ * Returns the Metrics representing the performance of the link layer.
+ *
+ * This contains the theoretical performance of the link, if available.
+ * Note that while this function cannot return null, any and/or all of the members of the
+ * returned object can be null if unknown.
*/
- public void removeExtension(@Nullable String key) {
- mExtensions.remove(key);
+ @NonNull public Metrics getLinkLayerMetrics() {
+ return mLinkLayerMetrics;
+ }
+
+ /**
+ * Returns the Metrics representing the end-to-end performance of the network.
+ *
+ * This contains the end-to-end performance of the link, if available.
+ * Note that while this function cannot return null, any and/or all of the members of the
+ * returned object can be null if unknown.
+ */
+ @NonNull public Metrics getEndToEndMetrics() {
+ return mEndToEndMetrics;
+ }
+
+ /**
+ * Returns the signal strength of this network normalized 0~1000, or UNKNOWN_SIGNAL_STRENGTH.
+ */
+ @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH)
+ public int getSignalStrength() {
+ return mSignalStrength;
+ }
+
+ /**
+ * Returns the typical range of this network technology as one of the RANGE_* constants.
+ */
+ @Range public int getRange() {
+ return mRange;
+ }
+
+ /** Returns a prediction of whether this network is likely to be unusable in a few seconds. */
+ public boolean isExiting() {
+ return mExiting;
+ }
+
+ /**
+ * Get the legacy score.
+ * @hide
+ */
+ public int getLegacyScore() {
+ return mLegacyScore;
+ }
+
+ /** Builder for NetworkScore. */
+ public static class Builder {
+ private int mPolicy = 0;
+ @NonNull
+ private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
+ Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
+ @NonNull
+ private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
+ Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
+ private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH;
+ private int mRange = RANGE_UNKNOWN;
+ private boolean mExiting = false;
+ private int mLegacyScore = 0;
+ @NonNull private Bundle mExtensions = new Bundle();
+
+ /** Create a new builder. */
+ public Builder() { }
+
+ /** Add a policy flag. */
+ @NonNull public Builder addPolicy(@Policy final int policy) {
+ mPolicy |= policy;
+ return this;
+ }
+
+ /** Clear a policy flag */
+ @NonNull public Builder clearPolicy(@Policy final int policy) {
+ mPolicy &= ~policy;
+ return this;
+ }
+
+ /** Set the link layer metrics. */
+ @NonNull public Builder setLinkLayerMetrics(@NonNull final Metrics linkLayerMetrics) {
+ mLinkLayerMetrics = linkLayerMetrics;
+ return this;
+ }
+
+ /** Set the end-to-end metrics. */
+ @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) {
+ mEndToMetrics = endToEndMetrics;
+ return this;
+ }
+
+ /** Set the signal strength. */
+ @NonNull public Builder setSignalStrength(
+ @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH)
+ final int signalStrength) {
+ mSignalStrength = signalStrength;
+ return this;
+ }
+
+ /** Set the range. */
+ @NonNull public Builder setRange(@Range final int range) {
+ mRange = range;
+ return this;
+ }
+
+ /** Set whether this network is exiting. */
+ @NonNull public Builder setExiting(final boolean exiting) {
+ mExiting = exiting;
+ return this;
+ }
+
+ /** Add a parcelable extension. */
+ @NonNull public Builder setLegacyScore(final int legacyScore) {
+ mLegacyScore = legacyScore;
+ return this;
+ }
+
+ /** Build the NetworkScore object represented by this builder. */
+ @NonNull public NetworkScore build() {
+ return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics,
+ mSignalStrength, mRange, mExiting, mLegacyScore);
+ }
}
@Override
@@ -88,9 +429,17 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- synchronized (this) {
- dest.writeBundle(mExtensions);
- }
+ dest.writeInt(mPolicy);
+ dest.writeInt(mLinkLayerMetrics.latencyMs);
+ dest.writeInt(mLinkLayerMetrics.downlinkBandwidthKBps);
+ dest.writeInt(mLinkLayerMetrics.uplinkBandwidthKBps);
+ dest.writeInt(mEndToEndMetrics.latencyMs);
+ dest.writeInt(mEndToEndMetrics.downlinkBandwidthKBps);
+ dest.writeInt(mEndToEndMetrics.uplinkBandwidthKBps);
+ dest.writeInt(mSignalStrength);
+ dest.writeInt(mRange);
+ dest.writeBoolean(mExiting);
+ dest.writeInt(mLegacyScore);
}
public static final @NonNull Creator<NetworkScore> CREATOR = new Creator<NetworkScore>() {
@@ -106,57 +455,52 @@
};
private NetworkScore(@NonNull Parcel in) {
- mExtensions = in.readBundle();
+ mPolicy = in.readInt();
+ mLinkLayerMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt());
+ mEndToEndMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt());
+ mSignalStrength = in.readInt();
+ mRange = in.readInt();
+ mExiting = in.readBoolean();
+ mLegacyScore = in.readInt();
}
- // TODO: Modify this method once new fields are added into this class.
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof NetworkScore)) {
return false;
}
final NetworkScore other = (NetworkScore) obj;
- return bundlesEqual(mExtensions, other.mExtensions);
+ return mPolicy == other.mPolicy
+ && mLinkLayerMetrics.latencyMs == other.mLinkLayerMetrics.latencyMs
+ && mLinkLayerMetrics.uplinkBandwidthKBps
+ == other.mLinkLayerMetrics.uplinkBandwidthKBps
+ && mEndToEndMetrics.latencyMs == other.mEndToEndMetrics.latencyMs
+ && mEndToEndMetrics.uplinkBandwidthKBps
+ == other.mEndToEndMetrics.uplinkBandwidthKBps
+ && mSignalStrength == other.mSignalStrength
+ && mRange == other.mRange
+ && mExiting == other.mExiting
+ && mLegacyScore == other.mLegacyScore;
}
@Override
public int hashCode() {
- int result = 29;
- for (String key : mExtensions.keySet()) {
- final Object value = mExtensions.get(key);
- // The key may be null, so call Objects.hash() is safer.
- result += 31 * value.hashCode() + 37 * Objects.hash(key);
- }
- return result;
- }
-
- // mExtensions won't be null since the constructor will create it.
- private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) {
- if (bundle1 == bundle2) {
- return true;
- }
-
- // This is unlikely but it's fine to add this clause here.
- if (null == bundle1 || null == bundle2) {
- return false;
- }
-
- if (bundle1.size() != bundle2.size()) {
- return false;
- }
-
- for (String key : bundle1.keySet()) {
- final Object value1 = bundle1.get(key);
- final Object value2 = bundle2.get(key);
- if (!Objects.equals(value1, value2)) {
- return false;
- }
- }
- return true;
+ return Objects.hash(mPolicy,
+ mLinkLayerMetrics.latencyMs, mLinkLayerMetrics.uplinkBandwidthKBps,
+ mEndToEndMetrics.latencyMs, mEndToEndMetrics.uplinkBandwidthKBps,
+ mSignalStrength, mRange, mExiting, mLegacyScore);
}
/** Convert to a string */
public String toString() {
- return "NetworkScore[" + mExtensions.toString() + "]";
+ return "NetworkScore ["
+ + "Policy = " + mPolicy
+ + " LinkLayerMetrics = " + mLinkLayerMetrics
+ + " EndToEndMetrics = " + mEndToEndMetrics
+ + " SignalStrength = " + mSignalStrength
+ + " Range = " + mRange
+ + " Exiting = " + mExiting
+ + " LegacyScore = " + mLegacyScore
+ + "]";
}
}