• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 
30 /**
31  * Object representing the quality of a network as perceived by the user.
32  *
33  * A NetworkScore object represents the characteristics of a network that affects how good the
34  * network is considered for a particular use.
35  * @hide
36  */
37 @SystemApi
38 public final class NetworkScore implements Parcelable {
39     // This will be removed soon. Do *NOT* depend on it for any new code that is not part of
40     // a migration.
41     private final int mLegacyInt;
42 
43     /** @hide */
44     @Retention(RetentionPolicy.SOURCE)
45     @IntDef(value = {
46             KEEP_CONNECTED_NONE,
47             KEEP_CONNECTED_FOR_HANDOVER
48     })
49     public @interface KeepConnectedReason { }
50 
51     /**
52      * Do not keep this network connected if there is no outstanding request for it.
53      */
54     public static final int KEEP_CONNECTED_NONE = 0;
55     /**
56      * Keep this network connected even if there is no outstanding request for it, because it
57      * is being considered for handover.
58      */
59     public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;
60 
61     // Agent-managed policies
62     // This network should lose to a wifi that has ever been validated
63     // NOTE : temporarily this policy is managed by ConnectivityService, because of legacy. The
64     // legacy design has this bit global to the system and tacked on WiFi which means it will affect
65     // networks from carriers who don't want it and non-carrier networks, which is bad for users.
66     // The S design has this on mobile networks only, so this can be fixed eventually ; as CS
67     // doesn't know what carriers need this bit, the initial S implementation will continue to
68     // affect other carriers but will at least leave non-mobile networks alone. Eventually Telephony
69     // should set this on networks from carriers that require it.
70     /** @hide */
71     public static final int POLICY_YIELD_TO_BAD_WIFI = 1;
72     // This network is primary for this transport.
73     /** @hide */
74     public static final int POLICY_TRANSPORT_PRIMARY = 2;
75     // This network is exiting : it will likely disconnect in a few seconds.
76     /** @hide */
77     public static final int POLICY_EXITING = 3;
78 
79     /** @hide */
80     public static final int MIN_AGENT_MANAGED_POLICY = POLICY_YIELD_TO_BAD_WIFI;
81     /** @hide */
82     public static final int MAX_AGENT_MANAGED_POLICY = POLICY_EXITING;
83 
84     // Bitmask of all the policies applied to this score.
85     private final long mPolicies;
86 
87     private final int mKeepConnectedReason;
88 
89     /** @hide */
NetworkScore(final int legacyInt, final long policies, @KeepConnectedReason final int keepConnectedReason)90     NetworkScore(final int legacyInt, final long policies,
91             @KeepConnectedReason final int keepConnectedReason) {
92         mLegacyInt = legacyInt;
93         mPolicies = policies;
94         mKeepConnectedReason = keepConnectedReason;
95     }
96 
NetworkScore(@onNull final Parcel in)97     private NetworkScore(@NonNull final Parcel in) {
98         mLegacyInt = in.readInt();
99         mPolicies = in.readLong();
100         mKeepConnectedReason = in.readInt();
101     }
102 
103     /**
104      * Get the legacy int score embedded in this NetworkScore.
105      * @see Builder#setLegacyInt(int)
106      */
getLegacyInt()107     public int getLegacyInt() {
108         return mLegacyInt;
109     }
110 
111     /**
112      * Returns the keep-connected reason, or KEEP_CONNECTED_NONE.
113      */
getKeepConnectedReason()114     public int getKeepConnectedReason() {
115         return mKeepConnectedReason;
116     }
117 
118     /**
119      * @return whether this score has a particular policy.
120      *
121      * @hide
122      */
123     @VisibleForTesting
hasPolicy(final int policy)124     public boolean hasPolicy(final int policy) {
125         return 0 != (mPolicies & (1L << policy));
126     }
127 
128     /**
129      * To the exclusive usage of FullScore
130      * @hide
131      */
getPolicies()132     public long getPolicies() {
133         return mPolicies;
134     }
135 
136     /**
137      * Whether this network should yield to a previously validated wifi gone bad.
138      *
139      * If this policy is set, other things being equal, the device will prefer a previously
140      * validated WiFi even if this network is validated and the WiFi is not.
141      * If this policy is not set, the device prefers the validated network.
142      *
143      * @hide
144      */
145     // TODO : Unhide this for telephony and have telephony call it on the relevant carriers.
146     // In the mean time this is handled by Connectivity in a backward-compatible manner.
shouldYieldToBadWifi()147     public boolean shouldYieldToBadWifi() {
148         return hasPolicy(POLICY_YIELD_TO_BAD_WIFI);
149     }
150 
151     /**
152      * Whether this network is primary for this transport.
153      *
154      * When multiple networks of the same transport are active, the device prefers the ones that
155      * are primary. This is meant in particular for DS-DA devices with a user setting to choose the
156      * default SIM card, or for WiFi STA+STA and make-before-break cases.
157      *
158      * @hide
159      */
160     @SystemApi
isTransportPrimary()161     public boolean isTransportPrimary() {
162         return hasPolicy(POLICY_TRANSPORT_PRIMARY);
163     }
164 
165     /**
166      * Whether this network is exiting.
167      *
168      * If this policy is set, the device will expect this network to disconnect within seconds.
169      * It will try to migrate to some other network if any is available, policy permitting, to
170      * avoid service disruption.
171      * This is useful in particular when a good cellular network is available and WiFi is getting
172      * weak and risks disconnecting soon. The WiFi network should be marked as exiting so that
173      * the device will prefer the reliable mobile network over this soon-to-be-lost WiFi.
174      *
175      * @hide
176      */
177     @SystemApi
isExiting()178     public boolean isExiting() {
179         return hasPolicy(POLICY_EXITING);
180     }
181 
182     @Override
toString()183     public String toString() {
184         return "Score(" + mLegacyInt + " ; Policies : " + mPolicies + ")";
185     }
186 
187     @Override
writeToParcel(@onNull final Parcel dest, final int flags)188     public void writeToParcel(@NonNull final Parcel dest, final int flags) {
189         dest.writeInt(mLegacyInt);
190         dest.writeLong(mPolicies);
191         dest.writeInt(mKeepConnectedReason);
192     }
193 
194     @Override
describeContents()195     public int describeContents() {
196         return 0;
197     }
198 
199     @NonNull public static final Creator<NetworkScore> CREATOR = new Creator<>() {
200         @Override
201         @NonNull
202         public NetworkScore createFromParcel(@NonNull final Parcel in) {
203             return new NetworkScore(in);
204         }
205 
206         @Override
207         @NonNull
208         public NetworkScore[] newArray(int size) {
209             return new NetworkScore[size];
210         }
211     };
212 
213     /**
214      * A builder for NetworkScore.
215      */
216     public static final class Builder {
217         private static final long POLICY_NONE = 0L;
218         private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
219         private int mLegacyInt = INVALID_LEGACY_INT;
220         private int mKeepConnectedReason = KEEP_CONNECTED_NONE;
221         private int mPolicies = 0;
222 
223         /**
224          * Sets the legacy int for this score.
225          *
226          * This will be used for measurements and logs, but will no longer be used for ranking
227          * networks against each other. Callers that existed before Android S should send what
228          * they used to send as the int score.
229          *
230          * @param score the legacy int
231          * @return this
232          */
233         @NonNull
setLegacyInt(final int score)234         public Builder setLegacyInt(final int score) {
235             mLegacyInt = score;
236             return this;
237         }
238 
239 
240         /**
241          * Set for a network that should never be preferred to a wifi that has ever been validated
242          *
243          * If this policy is set, other things being equal, the device will prefer a previously
244          * validated WiFi even if this network is validated and the WiFi is not.
245          * If this policy is not set, the device prefers the validated network.
246          *
247          * @return this builder
248          * @hide
249          */
250         // TODO : Unhide this for telephony and have telephony call it on the relevant carriers.
251         // In the mean time this is handled by Connectivity in a backward-compatible manner.
252         @NonNull
setShouldYieldToBadWifi(final boolean val)253         public Builder setShouldYieldToBadWifi(final boolean val) {
254             if (val) {
255                 mPolicies |= (1L << POLICY_YIELD_TO_BAD_WIFI);
256             } else {
257                 mPolicies &= ~(1L << POLICY_YIELD_TO_BAD_WIFI);
258             }
259             return this;
260         }
261 
262         /**
263          * Set for a network that is primary for this transport.
264          *
265          * When multiple networks of the same transport are active, the device prefers the ones that
266          * are primary. This is meant in particular for DS-DA devices with a user setting to choose
267          * the default SIM card, or for WiFi STA+STA and make-before-break cases.
268          *
269          * @return this builder
270          * @hide
271          */
272         @SystemApi
273         @NonNull
setTransportPrimary(final boolean val)274         public Builder setTransportPrimary(final boolean val) {
275             if (val) {
276                 mPolicies |= (1L << POLICY_TRANSPORT_PRIMARY);
277             } else {
278                 mPolicies &= ~(1L << POLICY_TRANSPORT_PRIMARY);
279             }
280             return this;
281         }
282 
283         /**
284          * Set for a network that will likely disconnect in a few seconds.
285          *
286          * If this policy is set, the device will expect this network to disconnect within seconds.
287          * It will try to migrate to some other network if any is available, policy permitting, to
288          * avoid service disruption.
289          * This is useful in particular when a good cellular network is available and WiFi is
290          * getting weak and risks disconnecting soon. The WiFi network should be marked as exiting
291          * so that the device will prefer the reliable mobile network over this soon-to-be-lost
292          * WiFi.
293          *
294          * @return this builder
295          * @hide
296          */
297         @SystemApi
298         @NonNull
setExiting(final boolean val)299         public Builder setExiting(final boolean val) {
300             if (val) {
301                 mPolicies |= (1L << POLICY_EXITING);
302             } else {
303                 mPolicies &= ~(1L << POLICY_EXITING);
304             }
305             return this;
306         }
307 
308         /**
309          * Set the keep-connected reason.
310          *
311          * This can be reset by calling it again with {@link KEEP_CONNECTED_NONE}.
312          */
313         @NonNull
setKeepConnectedReason(@eepConnectedReason final int reason)314         public Builder setKeepConnectedReason(@KeepConnectedReason final int reason) {
315             mKeepConnectedReason = reason;
316             return this;
317         }
318 
319         /**
320          * Builds this NetworkScore.
321          * @return The built NetworkScore object.
322          */
323         @NonNull
build()324         public NetworkScore build() {
325             return new NetworkScore(mLegacyInt, mPolicies, mKeepConnectedReason);
326         }
327     }
328 }
329