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.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.SystemApi;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.Objects;
32 
33 /**
34  * Phone capability which describes the data connection capability of modem.
35  * It's used to evaluate possible phone config change, for example from single
36  * SIM device to multi-SIM device.
37  * @hide
38  */
39 @SystemApi
40 public final class PhoneCapability implements Parcelable {
41     // Hardcoded default DSDS capability.
42     /** @hide */
43     public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
44     // Hardcoded default Single SIM single standby capability.
45     /** @hide */
46     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
47 
48     /** @hide */
49     @Retention(RetentionPolicy.SOURCE)
50     @IntDef(prefix = { "DEVICE_NR_CAPABILITY_" }, value = {
51             DEVICE_NR_CAPABILITY_NSA,
52             DEVICE_NR_CAPABILITY_SA,
53     })
54     public @interface DeviceNrCapability {}
55 
56     /**
57      * Indicates DEVICE_NR_CAPABILITY_NSA determine that the device enable the non-standalone
58      * (NSA) mode of 5G NR.
59      * @hide
60      */
61     @SystemApi
62     public static final int DEVICE_NR_CAPABILITY_NSA = 1;
63 
64     /**
65      * Indicates DEVICE_NR_CAPABILITY_SA determine that the device enable the standalone (SA)
66      * mode of 5G NR.
67      * @hide
68      */
69     @SystemApi
70     public static final int DEVICE_NR_CAPABILITY_SA = 2;
71 
72     static {
73         ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true);
74         ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true);
75 
76         List<ModemInfo> logicalModemList = new ArrayList<>();
77         logicalModemList.add(modemInfo1);
78         logicalModemList.add(modemInfo2);
79         int[] deviceNrCapabilities = new int[0];
80 
81         DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, logicalModemList, false,
82                 deviceNrCapabilities);
83 
84         logicalModemList = new ArrayList<>();
85         logicalModemList.add(modemInfo1);
86         DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, logicalModemList, false,
87                 deviceNrCapabilities);
88     }
89 
90     /**
91      * mMaxActiveVoiceSubscriptions defines the maximum subscriptions that can support
92      * simultaneous voice calls. For a dual sim dual standby (DSDS) device it would be one, but
93      * for a dual sim dual active (DSDA) device, or a DSDS device that supports "virtual DSDA" (
94      * using the data line of 1 SIM to temporarily provide IMS voice connectivity to the other SIM)
95      * it would be 2.
96      *
97      * @hide
98      */
99     private final int mMaxActiveVoiceSubscriptions;
100 
101     /**
102      * mMaxActiveDataSubscriptions defines the maximum subscriptions that can support
103      * simultaneous data connections.
104      * For example, for dual sim dual active L+L device it should be 2.
105      *
106      * @hide
107      */
108     private final int mMaxActiveDataSubscriptions;
109 
110     /**
111      * Whether modem supports both internet PDN up so
112      * that we can do ping test before tearing down the
113      * other one.
114      *
115      * @hide
116      */
117     private final boolean mNetworkValidationBeforeSwitchSupported;
118 
119     /**
120      * List of logical modem information.
121      *
122      * @hide
123      */
124     @NonNull
125     private final List<ModemInfo> mLogicalModemList;
126 
127     /**
128      * Device NR capabilities.
129      *
130      * @hide
131      */
132     @NonNull
133     private final int[] mDeviceNrCapabilities;
134 
135     /** @hide */
PhoneCapability(int maxActiveVoiceSubscriptions, int maxActiveDataSubscriptions, List<ModemInfo> logicalModemList, boolean networkValidationBeforeSwitchSupported, int[] deviceNrCapabilities)136     public PhoneCapability(int maxActiveVoiceSubscriptions, int maxActiveDataSubscriptions,
137             List<ModemInfo> logicalModemList, boolean networkValidationBeforeSwitchSupported,
138             int[] deviceNrCapabilities) {
139         this.mMaxActiveVoiceSubscriptions = maxActiveVoiceSubscriptions;
140         this.mMaxActiveDataSubscriptions = maxActiveDataSubscriptions;
141         // Make sure it's not null.
142         this.mLogicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
143         this.mNetworkValidationBeforeSwitchSupported = networkValidationBeforeSwitchSupported;
144         this.mDeviceNrCapabilities = deviceNrCapabilities;
145     }
146 
PhoneCapability(@onNull Builder builder)147     private PhoneCapability(@NonNull Builder builder) {
148         this.mMaxActiveVoiceSubscriptions = builder.mMaxActiveVoiceSubscriptions;
149         this.mMaxActiveDataSubscriptions = builder.mMaxActiveDataSubscriptions;
150         // Make sure it's not null.
151         this.mLogicalModemList = builder.mLogicalModemList == null ? new ArrayList<>()
152                 : builder.mLogicalModemList;
153         this.mNetworkValidationBeforeSwitchSupported =
154                 builder.mNetworkValidationBeforeSwitchSupported;
155         this.mDeviceNrCapabilities = builder.mDeviceNrCapabilities;
156 
157     }
158 
159     @Override
toString()160     public String toString() {
161         return "mMaxActiveVoiceSubscriptions=" + mMaxActiveVoiceSubscriptions
162                 + " mMaxActiveDataSubscriptions=" + mMaxActiveDataSubscriptions
163                 + " mNetworkValidationBeforeSwitchSupported="
164                 + mNetworkValidationBeforeSwitchSupported
165                 + " mDeviceNrCapability " + Arrays.toString(mDeviceNrCapabilities);
166     }
167 
PhoneCapability(Parcel in)168     private PhoneCapability(Parcel in) {
169         mMaxActiveVoiceSubscriptions = in.readInt();
170         mMaxActiveDataSubscriptions = in.readInt();
171         mNetworkValidationBeforeSwitchSupported = in.readBoolean();
172         mLogicalModemList = new ArrayList<>();
173         in.readList(mLogicalModemList, ModemInfo.class.getClassLoader(), android.telephony.ModemInfo.class);
174         mDeviceNrCapabilities = in.createIntArray();
175     }
176 
177     @Override
hashCode()178     public int hashCode() {
179         return Objects.hash(mMaxActiveVoiceSubscriptions,
180                 mMaxActiveDataSubscriptions,
181                 mLogicalModemList,
182                 mNetworkValidationBeforeSwitchSupported,
183                 Arrays.hashCode(mDeviceNrCapabilities));
184     }
185 
186     @Override
equals(Object o)187     public boolean equals(Object o) {
188         if (o == null || !(o instanceof PhoneCapability) || hashCode() != o.hashCode()) {
189             return false;
190         }
191 
192         if (this == o) {
193             return true;
194         }
195 
196         PhoneCapability s = (PhoneCapability) o;
197 
198         return (mMaxActiveVoiceSubscriptions == s.mMaxActiveVoiceSubscriptions
199                 && mMaxActiveDataSubscriptions == s.mMaxActiveDataSubscriptions
200                 && mNetworkValidationBeforeSwitchSupported
201                 == s.mNetworkValidationBeforeSwitchSupported
202                 && mLogicalModemList.equals(s.mLogicalModemList)
203                 && Arrays.equals(mDeviceNrCapabilities, s.mDeviceNrCapabilities));
204     }
205 
206     /**
207      * {@link Parcelable#describeContents}
208      */
describeContents()209     public int describeContents() {
210         return 0;
211     }
212 
213     /**
214      * {@link Parcelable#writeToParcel}
215      */
writeToParcel(@onNull Parcel dest, @Parcelable.WriteFlags int flags)216     public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
217         dest.writeInt(mMaxActiveVoiceSubscriptions);
218         dest.writeInt(mMaxActiveDataSubscriptions);
219         dest.writeBoolean(mNetworkValidationBeforeSwitchSupported);
220         dest.writeList(mLogicalModemList);
221         dest.writeIntArray(mDeviceNrCapabilities);
222     }
223 
224     public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR =
225             new Parcelable.Creator() {
226         public PhoneCapability createFromParcel(Parcel in) {
227             return new PhoneCapability(in);
228         }
229 
230         public PhoneCapability[] newArray(int size) {
231             return new PhoneCapability[size];
232         }
233     };
234 
235     /**
236      * @return the maximum subscriptions that can support simultaneous voice calls. For a dual
237      * sim dual standby (DSDS) device it would be one, but for a dual sim dual active device it
238      * would be 2.
239      * @hide
240      */
241     @SystemApi
getMaxActiveVoiceSubscriptions()242     public @IntRange(from = 1) int getMaxActiveVoiceSubscriptions() {
243         return mMaxActiveVoiceSubscriptions;
244     }
245 
246     /**
247      * @return the maximum subscriptions that can support simultaneous data connections.
248      * For example, for L+L device it should be 2.
249      * @hide
250      */
251     @SystemApi
getMaxActiveDataSubscriptions()252     public @IntRange(from = 1) int getMaxActiveDataSubscriptions() {
253         return mMaxActiveDataSubscriptions;
254     }
255 
256     /**
257      * @return Check whether the Citizens Broadband Radio Service(CBRS) network validation before
258      * CBRS switch is supported or not.
259      *
260      * @hide
261      */
isNetworkValidationBeforeSwitchSupported()262     public boolean isNetworkValidationBeforeSwitchSupported() {
263         return mNetworkValidationBeforeSwitchSupported;
264     }
265 
266     /**
267      * @return The list of logical modem information.
268      * @hide
269      */
getLogicalModemList()270     public List<ModemInfo> getLogicalModemList() {
271         return mLogicalModemList;
272     }
273 
274     /**
275      * Return List of the device's NR capability. If the device doesn't support NR capability,
276      * then this api return empty array.
277      * @see DEVICE_NR_CAPABILITY_NSA
278      * @see DEVICE_NR_CAPABILITY_SA
279      *
280      * @return List of the device's NR capability.
281      * @hide
282      */
283     @SystemApi
getDeviceNrCapabilities()284     public @NonNull @DeviceNrCapability int[] getDeviceNrCapabilities() {
285         return mDeviceNrCapabilities == null ? (new int[0]) : mDeviceNrCapabilities;
286     }
287 
288 
289     /**
290      * Builder for {@link PhoneCapability}.
291      *
292      * @hide
293      */
294     public static class Builder {
295         /**
296          * mMaxActiveVoiceSubscriptions defines the maximum subscriptions that can support
297          * simultaneous voice calls. For a dual sim dual standby (DSDS) device it would be one, but
298          * for a dual sim dual active (DSDA) device, or a DSDS device that supports "virtual DSDA"
299          * (using the data line of 1 SIM to temporarily provide IMS voice connectivity to the other
300          * SIM) it would be 2.
301          *
302          * @hide
303          */
304         private int mMaxActiveVoiceSubscriptions = 0;
305 
306         /**
307          * mMaxActiveDataSubscriptions defines the maximum subscriptions that can support
308          * simultaneous data connections. For example, for L+L device it should be 2.
309          *
310          * @hide
311          */
312         private int mMaxActiveDataSubscriptions = 0;
313 
314         /**
315          * Whether modem supports both internet PDN up so that we can do ping test before tearing
316          * down the other one.
317          *
318          * @hide
319          */
320         private boolean mNetworkValidationBeforeSwitchSupported = false;
321 
322         /**
323          * List of logical modem information.
324          *
325          * @hide
326          */
327         @NonNull
328         private List<ModemInfo> mLogicalModemList = new ArrayList<>();
329 
330         /**
331          * Device NR capabilities.
332          *
333          * @hide
334          */
335         @NonNull
336         private int[] mDeviceNrCapabilities = new int[0];
337 
338         /**
339          * Default constructor.
340          */
Builder()341         public Builder() {
342         }
343 
Builder(@onNull PhoneCapability phoneCapability)344         public Builder(@NonNull PhoneCapability phoneCapability) {
345             mMaxActiveVoiceSubscriptions = phoneCapability.mMaxActiveVoiceSubscriptions;
346             mMaxActiveDataSubscriptions = phoneCapability.mMaxActiveDataSubscriptions;
347             mNetworkValidationBeforeSwitchSupported =
348                     phoneCapability.mNetworkValidationBeforeSwitchSupported;
349             mLogicalModemList = phoneCapability.mLogicalModemList;
350             mDeviceNrCapabilities = phoneCapability.mDeviceNrCapabilities;
351         }
352 
353         /**
354          * Sets the max active voice subscriptions supported by the device.
355          */
setMaxActiveVoiceSubscriptions(int maxActiveVoiceSubscriptions)356         public Builder setMaxActiveVoiceSubscriptions(int maxActiveVoiceSubscriptions) {
357             mMaxActiveVoiceSubscriptions = maxActiveVoiceSubscriptions;
358             return this;
359         }
360 
361         /**
362          * Sets the max active voice subscriptions supported by the device.
363          */
setMaxActiveDataSubscriptions(int maxActiveDataSubscriptions)364         public Builder setMaxActiveDataSubscriptions(int maxActiveDataSubscriptions) {
365             mMaxActiveDataSubscriptions = maxActiveDataSubscriptions;
366             return this;
367         }
368 
369         /**
370          * Sets the max active data subscriptions supported by the device. Can be fewer than the
371          * active voice subscriptions.
372          */
setNetworkValidationBeforeSwitchSupported( boolean networkValidationBeforeSwitchSupported)373         public Builder setNetworkValidationBeforeSwitchSupported(
374                 boolean networkValidationBeforeSwitchSupported) {
375             mNetworkValidationBeforeSwitchSupported = networkValidationBeforeSwitchSupported;
376             return this;
377         }
378 
379         /**
380          * Sets the logical modem list of the device.
381          */
setLogicalModemList(@onNull List<ModemInfo> logicalModemList)382         public Builder setLogicalModemList(@NonNull List<ModemInfo> logicalModemList) {
383             mLogicalModemList = logicalModemList;
384             return this;
385         }
386 
387         /**
388          * Sets the NR capabilities supported by the device.
389          */
setDeviceNrCapabilities(@onNull int[] deviceNrCapabilities)390         public Builder setDeviceNrCapabilities(@NonNull int[] deviceNrCapabilities) {
391             mDeviceNrCapabilities = deviceNrCapabilities;
392             return this;
393         }
394 
395         /**
396          * Build the {@link PhoneCapability}.
397          *
398          * @return The {@link PhoneCapability} instance.
399          */
build()400         public PhoneCapability build() {
401             return new PhoneCapability(this);
402         }
403     }
404 }
405