1 /*
2  * Copyright (C) 2018 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.telephony;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.telephony.RadioAccessSpecifier;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Objects;
31 
32 /**
33  * Defines available network information which includes corresponding subscription id,
34  * network plmns and corresponding priority to be used for network selection by Opportunistic
35  * Network Service when passed through {@link TelephonyManager#updateAvailableNetworks}
36  */
37 public final class AvailableNetworkInfo implements Parcelable {
38     /*
39      * Defines number of priority level high.
40      */
41     public static final int PRIORITY_HIGH = 1;
42 
43     /*
44      * Defines number of priority level medium.
45      */
46     public static final int PRIORITY_MED = 2;
47 
48     /*
49      * Defines number of priority level low.
50      */
51     public static final int PRIORITY_LOW = 3;
52 
53     /** @hide */
54     @IntDef({
55         PRIORITY_HIGH,
56         PRIORITY_MED,
57         PRIORITY_LOW,
58     })
59     @Retention(RetentionPolicy.SOURCE)
60     public @interface AvailableNetworkInfoPriority {}
61     /**
62      * subscription Id of the available network. This value must be one of the entry retrieved from
63      * {@link SubscriptionManager#getOpportunisticSubscriptions}
64      */
65     private int mSubId;
66 
67     /**
68      * Priority for the subscription id.
69      * Priorities are in the range of {@link AvailableNetworkInfo#PRIORITY_LOW} to
70      * {@link AvailableNetworkInfo#PRIORITY_HIGH}
71      * Among all networks available after network scan, subId with highest priority is chosen
72      * for network selection. If there are more than one subId with highest priority then the
73      * network with highest RSRP is chosen.
74      */
75     private @AvailableNetworkInfoPriority int mPriority;
76 
77     /**
78      * Describes the List of PLMN ids (MCC-MNC) associated with mSubId.
79      * Opportunistic Network Service will scan and verify specified PLMNs are available.
80      * If this entry is left empty, then the Opportunistic Network Service will not scan the network
81      * to validate the network availability.
82      */
83     private ArrayList<String> mMccMncs;
84 
85     /**
86      * Returns the frequency bands associated with the {@link #getMccMncs() MCC/MNCs}.
87      * Opportunistic network service will use these bands to scan.
88      *
89      * When no specific bands are specified (empty array or null) CBRS band
90      * {@link AccessNetworkConstants.EutranBand.BAND_48} will be used for network scan.
91      *
92      * See {@link AccessNetworkConstants} for details.
93      *
94      * @deprecated use {@link #mRadioAccessSpecifiers} instead
95      */
96     @Deprecated
97     private ArrayList<Integer> mBands;
98 
99     /**
100      * Returns a list of {@link RadioAccessSpecifier} associated with the available network.
101      * Opportunistic network service will use this to determine which bands to scan for.
102      *
103      * If this entry is left empty, {@link RadioAcccessSpecifier}s with {@link AccessNetworkType}s
104      * of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link
105      * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed
106      * by Opportunistic network service for a network scan.
107      */
108     private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers;
109 
110     /**
111      * Return subscription Id of the available network.
112      * This value must be one of the entry retrieved from
113      * {@link SubscriptionManager#getOpportunisticSubscriptions}
114      * @return subscription id
115      */
getSubId()116     public int getSubId() {
117         return mSubId;
118     }
119 
120     /**
121      * Return priority for the subscription id.
122      * Priorities are in the range of {@link AvailableNetworkInfo#PRIORITY_LOW} to
123      * {@link AvailableNetworkInfo#PRIORITY_HIGH}
124      * Among all networks available after network scan, subId with highest priority is chosen
125      * for network selection. If there are more than one subId with highest priority then the
126      * network with highest RSRP is chosen.
127      * @return priority level
128      */
129     @AvailableNetworkInfoPriority
getPriority()130     public int getPriority() {
131         return mPriority;
132     }
133 
134     /**
135      * Return List of PLMN ids (MCC-MNC) associated with the sub ID.
136      * Opportunistic Network Service will scan and verify specified PLMNs are available.
137      * If this entry is left empty, then the Opportunistic Network Service will not scan the network
138      * to validate the network availability.
139      * @return list of PLMN ids
140      */
getMccMncs()141     public @NonNull List<String> getMccMncs() {
142         return (List<String>) mMccMncs.clone();
143     }
144 
145     /**
146      * Returns the frequency bands that need to be scanned by opportunistic network service
147      *
148      * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
149      * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}
150      * See {@link AccessNetworkConstants.AccessNetworkType} for details regarding different network
151      * types. When no specific bands are specified (empty array or null) CBRS band
152      * {@link AccessNetworkConstants.EutranBand#BAND_48} will be used for network scan.
153      */
getBands()154     public @NonNull List<Integer> getBands() {
155         return (List<Integer>) mBands.clone();
156     }
157 
158     /**
159      * Returns a list of {@link RadioAccessSpecifier} associated with the available network.
160      * Opportunistic network service will use this to determine which bands to scan for.
161      *
162      * @return the access network type associated with the available network.
163      */
getRadioAccessSpecifiers()164     public @NonNull List<RadioAccessSpecifier> getRadioAccessSpecifiers() {
165         return (List<RadioAccessSpecifier>) mRadioAccessSpecifiers.clone();
166     }
167 
168     @Override
describeContents()169     public int describeContents() {
170         return 0;
171     }
172 
173     @Override
writeToParcel(Parcel dest, int flags)174     public void writeToParcel(Parcel dest, int flags) {
175         dest.writeInt(mSubId);
176         dest.writeInt(mPriority);
177         dest.writeStringList(mMccMncs);
178         dest.writeList(mBands);
179         dest.writeList(mRadioAccessSpecifiers);
180     }
181 
AvailableNetworkInfo(Parcel in)182     private AvailableNetworkInfo(Parcel in) {
183         mSubId = in.readInt();
184         mPriority = in.readInt();
185         mMccMncs = new ArrayList<>();
186         in.readStringList(mMccMncs);
187         mBands = new ArrayList<>();
188         in.readList(mBands, Integer.class.getClassLoader(), java.lang.Integer.class);
189         mRadioAccessSpecifiers = new ArrayList<>();
190         in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader(), android.telephony.RadioAccessSpecifier.class);
191     }
192 
AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs, @NonNull List<Integer> bands)193     public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
194             @NonNull List<Integer> bands) {
195         this(subId, priority, mccMncs, bands,
196                 new ArrayList<RadioAccessSpecifier>());
197     }
198 
199     /** @hide */
AvailableNetworkInfo(int subId, @AvailableNetworkInfoPriority int priority, @NonNull List<String> mccMncs, @NonNull List<Integer> bands, @NonNull List<RadioAccessSpecifier> radioAccessSpecifiers)200     private AvailableNetworkInfo(int subId, @AvailableNetworkInfoPriority int priority,
201             @NonNull List<String> mccMncs, @NonNull List<Integer> bands,
202             @NonNull List<RadioAccessSpecifier> radioAccessSpecifiers) {
203         mSubId = subId;
204         mPriority = priority;
205         mMccMncs = new ArrayList<String>(mccMncs);
206         mBands = new ArrayList<Integer>(bands);
207         mRadioAccessSpecifiers = new ArrayList<RadioAccessSpecifier>(radioAccessSpecifiers);
208     }
209 
210     @Override
equals(Object o)211     public boolean equals(Object o) {
212         AvailableNetworkInfo ani;
213 
214         try {
215             ani = (AvailableNetworkInfo) o;
216         } catch (ClassCastException ex) {
217             return false;
218         }
219 
220         if (o == null) {
221             return false;
222         }
223 
224         return (mSubId == ani.mSubId
225             && mPriority == ani.mPriority
226             && (((mMccMncs != null)
227             && mMccMncs.equals(ani.mMccMncs)))
228             && mBands.equals(ani.mBands))
229             && mRadioAccessSpecifiers.equals(ani.getRadioAccessSpecifiers());
230     }
231 
232     @Override
hashCode()233     public int hashCode() {
234         return Objects.hash(mSubId, mPriority, mMccMncs, mBands, mRadioAccessSpecifiers);
235     }
236 
237     public static final @android.annotation.NonNull Parcelable.Creator<AvailableNetworkInfo> CREATOR =
238             new Creator<AvailableNetworkInfo>() {
239                 @Override
240                 public AvailableNetworkInfo createFromParcel(Parcel in) {
241                     return new AvailableNetworkInfo(in);
242                 }
243 
244                 @Override
245                 public AvailableNetworkInfo[] newArray(int size) {
246                     return new AvailableNetworkInfo[size];
247                 }
248             };
249 
250     @Override
toString()251     public String toString() {
252         return ("AvailableNetworkInfo:"
253             + " mSubId: " + mSubId
254             + " mPriority: " + mPriority
255             + " mMccMncs: " + Arrays.toString(mMccMncs.toArray())
256             + " mBands: " + Arrays.toString(mBands.toArray())
257             + " mRadioAccessSpecifiers: " + Arrays.toString(mRadioAccessSpecifiers.toArray()));
258     }
259 
260     /**
261      * Provides a convenient way to set the fields of a {@link AvailableNetworkInfo} when
262      * creating a new instance.
263      *
264      * <p>The example below shows how you might create a new {@code AvailableNetworkInfo}:
265      *
266      * <pre><code>
267      *
268      * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder(subId)
269      *     .setPriority(AvailableNetworkInfo.PRIORITY_MED)
270      *     .setRadioAccessSpecifiers(radioAccessSpecifiers)
271      *     .setMccMncs(mccMncs)
272      *     .build();
273      * </code></pre>
274      */
275     public static final class Builder {
276         private int mSubId = Integer.MIN_VALUE;
277         private @AvailableNetworkInfoPriority int mPriority = AvailableNetworkInfo.PRIORITY_LOW;
278         private ArrayList<String> mMccMncs = new ArrayList<>();
279         private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers = new ArrayList<>();
280 
281         /**
282          *
283          */
284         /**
285          * Creates an AvailableNetworkInfo Builder with specified subscription id.
286          *
287          * @param subId of the availableNetwork.
288          */
Builder(int subId)289         public Builder(int subId) {
290             mSubId = subId;
291         }
292 
293         /**
294          * Sets the priority for the subscription id.
295          *
296          * @param priority of the subscription id. See {@link AvailableNetworkInfo#getPriority} for
297          * more details
298          * @return the original Builder object.
299          */
setPriority(@vailableNetworkInfoPriority int priority)300         public @NonNull Builder setPriority(@AvailableNetworkInfoPriority int priority) {
301             if (priority > AvailableNetworkInfo.PRIORITY_LOW
302                     || priority < AvailableNetworkInfo.PRIORITY_HIGH) {
303                 throw new IllegalArgumentException("A valid priority must be set");
304             }
305             mPriority = priority;
306             return this;
307         }
308 
309         /**
310          * Sets the list of mccmncs associated with the subscription id.
311          *
312          * @param mccMncs nonull list of mccmncs. An empty List is still accepted. Please read
313          * documentation in {@link AvailableNetworkInfo} to see consequences of an empty List.
314          * @return the original Builder object.
315          */
setMccMncs(@onNull List<String> mccMncs)316         public @NonNull Builder setMccMncs(@NonNull List<String> mccMncs) {
317             Objects.requireNonNull(mccMncs, "A non-null List of mccmncs must be set. An empty "
318                     + "List is still accepted. Please read documentation in "
319                     + "AvailableNetworkInfo to see consequences of an empty List.");
320             mMccMncs = new ArrayList<>(mccMncs);
321             return this;
322         }
323 
324         /**
325          * Sets the list of mccmncs associated with the subscription id.
326          *
327          * @param radioAccessSpecifiers nonull list of radioAccessSpecifiers. An empty List is still
328          * accepted. Please read documentation in {@link AvailableNetworkInfo} to see
329          * consequences of an empty List.
330          * @return the original Builder object.
331          */
setRadioAccessSpecifiers( @onNull List<RadioAccessSpecifier> radioAccessSpecifiers)332         public @NonNull Builder setRadioAccessSpecifiers(
333                 @NonNull List<RadioAccessSpecifier> radioAccessSpecifiers) {
334             Objects.requireNonNull(radioAccessSpecifiers, "A non-null List of "
335                     + "RadioAccessSpecifiers must be set. An empty List is still accepted. Please "
336                     + "read documentation in AvailableNetworkInfo to see consequences of an "
337                     + "empty List.");
338             mRadioAccessSpecifiers = new ArrayList<>(radioAccessSpecifiers);
339             return this;
340         }
341 
342         /**
343          * @return an AvailableNetworkInfo object with all the fields previously set by the Builder.
344          */
build()345         public @NonNull AvailableNetworkInfo build() {
346             if (mSubId == Integer.MIN_VALUE) {
347                 throw new IllegalArgumentException("A valid subId must be set");
348             }
349 
350             return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, new ArrayList<>(),
351                     mRadioAccessSpecifiers);
352         }
353     }
354 }
355