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