1 /*
2  * Copyright (C) 2017 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.annotation.Nullable;
22 import android.os.Parcel;
23 import android.os.Parcelable;
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.Objects;
30 
31 /**
32  * Defines a request to perform a network scan.
33  *
34  * This class defines whether the network scan will be performed only once or periodically until
35  * cancelled, when the scan is performed periodically, the time interval is not controlled by the
36  * user but defined by the modem vendor.
37  */
38 public final class NetworkScanRequest implements Parcelable {
39 
40     // Below size limits for RAN/Band/Channel are for pre-treble modems and will be removed later.
41     /** @hide */
42     public static final int MAX_RADIO_ACCESS_NETWORKS = 8;
43     /** @hide */
44     public static final int MAX_BANDS = 8;
45     /** @hide */
46     public static final int MAX_CHANNELS = 32;
47     /** @hide */
48     public static final int MAX_MCC_MNC_LIST_SIZE = 20;
49     /** @hide */
50     public static final int MIN_SEARCH_PERIODICITY_SEC = 5;
51     /** @hide */
52     public static final int MAX_SEARCH_PERIODICITY_SEC = 300;
53     /** @hide */
54     public static final int MIN_SEARCH_MAX_SEC = 60;
55     /** @hide */
56     public static final int MAX_SEARCH_MAX_SEC = 3600;
57     /** @hide */
58     public static final int MIN_INCREMENTAL_PERIODICITY_SEC = 1;
59     /** @hide */
60     public static final int MAX_INCREMENTAL_PERIODICITY_SEC = 10;
61 
62     /** @hide */
63     @Retention(RetentionPolicy.SOURCE)
64     @IntDef({
65         SCAN_TYPE_ONE_SHOT,
66         SCAN_TYPE_PERIODIC,
67     })
68     public @interface ScanType {}
69 
70     /** Performs the scan only once */
71     public static final int SCAN_TYPE_ONE_SHOT = 0;
72     /**
73      * Performs the scan periodically until cancelled
74      *
75      * The modem will start new scans periodically, and the interval between two scans is usually
76      * multiple minutes.
77      */
78     public static final int SCAN_TYPE_PERIODIC = 1;
79 
80     /** Defines the type of the scan. */
81     private int mScanType;
82 
83     /**
84      * Search periodicity (in seconds).
85      * Expected range for the input is [5s - 300s]
86      * This value must be less than or equal to mMaxSearchTime
87      */
88     private int mSearchPeriodicity;
89 
90     /**
91      * Maximum duration of the periodic search (in seconds).
92      * Expected range for the input is [60s - 3600s]
93      * If the search lasts this long, it will be terminated.
94      */
95     private int mMaxSearchTime;
96 
97     /**
98      * Indicates whether the modem should report incremental
99      * results of the network scan to the client.
100      * FALSE – Incremental results are not reported.
101      * TRUE (default) – Incremental results are reported
102      */
103     private boolean mIncrementalResults;
104 
105     /**
106      * Indicates the periodicity with which the modem should
107      * report incremental results to the client (in seconds).
108      * Expected range for the input is [1s - 10s]
109      * This value must be less than or equal to mMaxSearchTime
110      */
111     private int mIncrementalResultsPeriodicity;
112 
113     /** Describes the radio access technologies with bands or channels that need to be scanned. */
114     @Nullable
115     private RadioAccessSpecifier[] mSpecifiers;
116 
117     /**
118      * Describes the List of PLMN ids (MCC-MNC)
119      * If any PLMN of this list is found, search should end at that point and
120      * results with all PLMN found till that point should be sent as response.
121      * If list not sent, search to be completed till end and all PLMNs found to be reported.
122      * Max size of array is MAX_MCC_MNC_LIST_SIZE
123      */
124     @NonNull
125     private ArrayList<String> mMccMncs;
126 
127     /**
128      * Creates a new NetworkScanRequest with mScanType and network mSpecifiers
129      *
130      * @param scanType The type of the scan, can be either one shot or periodic
131      * @param specifiers the radio network with bands / channels to be scanned
132      * @param searchPeriodicity The modem will restart the scan every searchPeriodicity seconds if
133      *                          no network has been found, until it reaches the maxSearchTime. Only
134      *                          valid when scan type is periodic scan.
135      * @param maxSearchTime Maximum duration of the search (in seconds)
136      * @param incrementalResults Indicates whether the modem should report incremental
137      *                           results of the network scan to the client
138      * @param incrementalResultsPeriodicity Indicates the periodicity with which the modem should
139      *                                      report incremental results to the client (in seconds),
140      *                                      only valid when incrementalResults is true
141      * @param mccMncs Describes the list of PLMN ids (MCC-MNC), once any network in the list has
142      *                been found, the scan will be terminated by the modem.
143      */
NetworkScanRequest(int scanType, RadioAccessSpecifier[] specifiers, int searchPeriodicity, int maxSearchTime, boolean incrementalResults, int incrementalResultsPeriodicity, ArrayList<String> mccMncs)144     public NetworkScanRequest(int scanType, RadioAccessSpecifier[] specifiers,
145                     int searchPeriodicity,
146                     int maxSearchTime,
147                     boolean incrementalResults,
148                     int incrementalResultsPeriodicity,
149                     ArrayList<String> mccMncs) {
150         this.mScanType = scanType;
151         if (specifiers != null) {
152             this.mSpecifiers = specifiers.clone();
153         } else {
154             this.mSpecifiers = null;
155         }
156         this.mSearchPeriodicity = searchPeriodicity;
157         this.mMaxSearchTime = maxSearchTime;
158         this.mIncrementalResults = incrementalResults;
159         this.mIncrementalResultsPeriodicity = incrementalResultsPeriodicity;
160         if (mccMncs != null) {
161             this.mMccMncs = (ArrayList<String>) mccMncs.clone();
162         } else {
163             this.mMccMncs = new ArrayList<>();
164         }
165     }
166 
167     /** Returns the type of the scan. */
168     @ScanType
getScanType()169     public int getScanType() {
170         return mScanType;
171     }
172 
173     /** Returns the search periodicity in seconds. */
getSearchPeriodicity()174     public int getSearchPeriodicity() {
175         return mSearchPeriodicity;
176     }
177 
178     /** Returns maximum duration of the periodic search in seconds. */
getMaxSearchTime()179     public int getMaxSearchTime() {
180         return mMaxSearchTime;
181     }
182 
183     /**
184      * Returns whether incremental result is enabled.
185      * FALSE – Incremental results is not enabled.
186      * TRUE – Incremental results is reported.
187      */
getIncrementalResults()188     public boolean getIncrementalResults() {
189         return mIncrementalResults;
190     }
191 
192     /** Returns the periodicity in seconds of incremental results. */
getIncrementalResultsPeriodicity()193     public int getIncrementalResultsPeriodicity() {
194         return mIncrementalResultsPeriodicity;
195     }
196 
197     /** Returns the radio access technologies with bands or channels that need to be scanned. */
getSpecifiers()198     public RadioAccessSpecifier[] getSpecifiers() {
199         return mSpecifiers == null ? null : mSpecifiers.clone();
200     }
201 
202     /**
203      * Returns the List of PLMN ids (MCC-MNC) for early termination of scan.
204      * If any PLMN of this list is found, search should end at that point and
205      * results with all PLMN found till that point should be sent as response.
206      */
getPlmns()207     public ArrayList<String> getPlmns() {
208         return (ArrayList<String>) mMccMncs.clone();
209     }
210 
211     @Override
describeContents()212     public int describeContents() {
213         return 0;
214     }
215 
216     @Override
writeToParcel(Parcel dest, int flags)217     public void writeToParcel(Parcel dest, int flags) {
218         dest.writeInt(mScanType);
219         dest.writeParcelableArray(mSpecifiers, flags);
220         dest.writeInt(mSearchPeriodicity);
221         dest.writeInt(mMaxSearchTime);
222         dest.writeBoolean(mIncrementalResults);
223         dest.writeInt(mIncrementalResultsPeriodicity);
224         dest.writeStringList(mMccMncs);
225     }
226 
NetworkScanRequest(Parcel in)227     private NetworkScanRequest(Parcel in) {
228         mScanType = in.readInt();
229         Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader(),
230                 RadioAccessSpecifier.class);
231         if (tempSpecifiers != null) {
232             mSpecifiers = new RadioAccessSpecifier[tempSpecifiers.length];
233             for (int i = 0; i < tempSpecifiers.length; i++) {
234                 mSpecifiers[i] = (RadioAccessSpecifier) tempSpecifiers[i];
235             }
236         } else {
237             mSpecifiers = null;
238         }
239         mSearchPeriodicity = in.readInt();
240         mMaxSearchTime = in.readInt();
241         mIncrementalResults = in.readBoolean();
242         mIncrementalResultsPeriodicity = in.readInt();
243         mMccMncs = new ArrayList<>();
244         in.readStringList(mMccMncs);
245     }
246 
247     @Override
equals(Object other)248     public boolean equals(Object other) {
249         if (this == other) return true;
250 
251         if (!(other instanceof NetworkScanRequest)) return false;
252 
253         NetworkScanRequest nsr = (NetworkScanRequest) other;
254 
255         return mScanType == nsr.mScanType
256                 && Arrays.equals(mSpecifiers, nsr.mSpecifiers)
257                 && mSearchPeriodicity == nsr.mSearchPeriodicity
258                 && mMaxSearchTime == nsr.mMaxSearchTime
259                 && mIncrementalResults == nsr.mIncrementalResults
260                 && mIncrementalResultsPeriodicity == nsr.mIncrementalResultsPeriodicity
261                 && Objects.equals(mMccMncs, nsr.mMccMncs);
262     }
263 
264     @Override
hashCode()265     public int hashCode () {
266         return ((mScanType * 31)
267                 + (Arrays.hashCode(mSpecifiers)) * 37
268                 + (mSearchPeriodicity * 41)
269                 + (mMaxSearchTime * 43)
270                 + ((mIncrementalResults == true? 1 : 0) * 47)
271                 + (mIncrementalResultsPeriodicity * 53)
272                 + (mMccMncs.hashCode() * 59));
273     }
274 
275     public static final @android.annotation.NonNull Creator<NetworkScanRequest> CREATOR =
276             new Creator<NetworkScanRequest>() {
277                 @Override
278                 public NetworkScanRequest createFromParcel(Parcel in) {
279                     return new NetworkScanRequest(in);
280                 }
281 
282                 @Override
283                 public NetworkScanRequest[] newArray(int size) {
284                     return new NetworkScanRequest[size];
285                 }
286             };
287 }
288