blob: 90244b3df3506223db269bed968d9c5538fd8bed [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import com.android.internal.util.CollectionUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Define capability of a modem group. That is, the capabilities
* are shared between those modems defined by list of modem IDs.
*/
public final class PhoneCapability implements Parcelable {
/** Modem feature indicating 3GPP2 capability. */
public static final long MODEM_FEATURE_3GPP2_REG = 1 << 0;
/** Modem feature indicating 3GPP capability. */
public static final long MODEM_FEATURE_3GPP_REG = 1 << 1;
/** Modem feature indicating CDMA 2000 with EHRPD capability. */
public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 1 << 2;
/** Modem feature indicating GSM capability. */
public static final long MODEM_FEATURE_GERAN_REG = 1 << 3;
/** Modem feature indicating UMTS capability. */
public static final long MODEM_FEATURE_UTRAN_REG = 1 << 4;
/** Modem feature indicating LTE capability. */
public static final long MODEM_FEATURE_EUTRAN_REG = 1 << 5;
/** Modem feature indicating 5G capability.*/
public static final long MODEM_FEATURE_NGRAN_REG = 1 << 6;
/** Modem feature indicating EN-DC capability. */
public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 1 << 7;
/** Modem feature indicating VoLTE capability (IMS registered). */
public static final long MODEM_FEATURE_PS_VOICE_REG = 1 << 8;
/** Modem feature indicating CS voice call capability. */
public static final long MODEM_FEATURE_CS_VOICE_SESSION = 1 << 9;
/** Modem feature indicating Internet connection capability. */
public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1 << 10;
/**
* Modem feature indicating dedicated bearer capability.
* For services that require a high level QoS (eg. VoLTE), the network can create
* a dedicated bearer with the required QoS on top of an established default bearer.
* This will provide a dedicated tunnel for one or more specific traffic types.
*/
public static final long MODEM_FEATURE_DEDICATED_BEARER = 1 << 11;
/** Modem feature indicating network scan capability. */
public static final long MODEM_FEATURE_NETWORK_SCAN = 1 << 12;
/** Modem feature indicating corresponding SIM has CDMA capability. */
public static final long MODEM_FEATURE_CSIM = 1 << 13;
/** @hide */
@LongDef(flag = true, prefix = {"MODEM_FEATURE_" }, value = {
MODEM_FEATURE_3GPP2_REG,
MODEM_FEATURE_3GPP_REG,
MODEM_FEATURE_CDMA2000_EHRPD_REG,
MODEM_FEATURE_GERAN_REG,
MODEM_FEATURE_UTRAN_REG,
MODEM_FEATURE_EUTRAN_REG,
MODEM_FEATURE_NGRAN_REG,
MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG,
MODEM_FEATURE_PS_VOICE_REG,
MODEM_FEATURE_CS_VOICE_SESSION,
MODEM_FEATURE_INTERACTIVE_DATA_SESSION,
MODEM_FEATURE_DEDICATED_BEARER,
MODEM_FEATURE_NETWORK_SCAN,
MODEM_FEATURE_CSIM,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ModemFeature {
}
/**
* Hardcoded default DSDS capability.
* @hide
*/
public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
/**
* Hardcoded default Single SIM single standby capability.
* @hide
*/
public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
static {
List<List<Long>> capabilities = new ArrayList<>();
List<Long> modem1 = new ArrayList<>();
List<Long> modem2 = new ArrayList<>();
modem1.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
| MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_CS_VOICE_SESSION
| MODEM_FEATURE_INTERACTIVE_DATA_SESSION | MODEM_FEATURE_DEDICATED_BEARER);
modem2.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
| MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_INTERACTIVE_DATA_SESSION
| MODEM_FEATURE_DEDICATED_BEARER);
capabilities.add(modem1);
capabilities.add(modem2);
List<String> uuids = new ArrayList<>();
uuids.add("com.xxxx.lm0");
uuids.add("com.xxxx.lm1");
long rats = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
| TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
| TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
| TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
DEFAULT_DSDS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
uuids, null, capabilities);
capabilities = new ArrayList<>();
capabilities.add(modem1);
uuids = new ArrayList<>();
uuids.add("com.xxxx.lm0");
DEFAULT_SSSS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
uuids, null, capabilities);
}
private final int mUtranUeCategoryDl;
private final int mUtranUeCategoryUl;
private final int mEutranUeCategoryDl;
private final int mEutranUeCategoryUl;
private final long mPsDataConnectionLingerTimeMillis;
private final @NetworkTypeBitMask long mSupportedRats;
private final List<Integer> mGeranBands;
private final List<Integer> mUtranBands;
private final List<Integer> mEutranBands;
private final List<Integer> mNgranBands;
private final List<String> mLogicalModemUuids;
private final List<SimSlotCapability> mSimSlotCapabilities;
private final @ModemFeature List<List<Long>> mConcurrentFeaturesSupport;
/**
* Default constructor to create a PhoneCapability object.
* @param utranUeCategoryDl 3GPP UE category for UTRAN downlink.
* @param utranUeCategoryUl 3GPP UE category for UTRAN uplink.
* @param eutranUeCategoryDl 3GPP UE category for EUTRAN downlink.
* @param eutranUeCategoryUl 3GPP UE category for EUTRAN uplink.
* @param psDataConnectionLingerTimeMillis length of the grace period to allow a smooth
* "handover" between data connections.
* @param supportedRats all radio access technologies this phone is capable of supporting.
* @param geranBands list of supported {@link AccessNetworkConstants.GeranBand}.
* @param utranBands list of supported {@link AccessNetworkConstants.UtranBand}.
* @param eutranBands list of supported {@link AccessNetworkConstants.EutranBand}.
* @param ngranBands list of supported {@link AccessNetworkConstants.NgranBands}.
* @param logicalModemUuids list of logical modem UUIDs, typically of the form
* "com.xxxx.lmX", where X is the logical modem ID.
* @param simSlotCapabilities list of {@link SimSlotCapability} for the device
* @param concurrentFeaturesSupport list of list of concurrently supportable modem feature sets.
* @hide
*/
public PhoneCapability(int utranUeCategoryDl, int utranUeCategoryUl, int eutranUeCategoryDl,
int eutranUeCategoryUl, long psDataConnectionLingerTimeMillis,
@NetworkTypeBitMask long supportedRats, @Nullable List<Integer> geranBands,
@Nullable List<Integer> utranBands, @Nullable List<Integer> eutranBands,
@Nullable List<Integer> ngranBands, @Nullable List<String> logicalModemUuids,
@Nullable List<SimSlotCapability> simSlotCapabilities,
@Nullable @ModemFeature List<List<Long>> concurrentFeaturesSupport) {
this.mUtranUeCategoryDl = utranUeCategoryDl;
this.mUtranUeCategoryUl = utranUeCategoryUl;
this.mEutranUeCategoryDl = eutranUeCategoryDl;
this.mEutranUeCategoryUl = eutranUeCategoryUl;
this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis;
this.mSupportedRats = supportedRats;
this.mGeranBands = CollectionUtils.emptyIfNull(geranBands);
this.mUtranBands = CollectionUtils.emptyIfNull(utranBands);
this.mEutranBands = CollectionUtils.emptyIfNull(eutranBands);
this.mNgranBands = CollectionUtils.emptyIfNull(ngranBands);
this.mLogicalModemUuids = CollectionUtils.emptyIfNull(logicalModemUuids);
this.mSimSlotCapabilities = CollectionUtils.emptyIfNull(simSlotCapabilities);
this.mConcurrentFeaturesSupport = CollectionUtils.emptyIfNull(concurrentFeaturesSupport);
}
private PhoneCapability(Parcel in) {
mUtranUeCategoryDl = in.readInt();
mUtranUeCategoryUl = in.readInt();
mEutranUeCategoryDl = in.readInt();
mEutranUeCategoryUl = in.readInt();
mPsDataConnectionLingerTimeMillis = in.readLong();
mSupportedRats = in.readLong();
mGeranBands = new ArrayList<>();
in.readList(mGeranBands, Integer.class.getClassLoader());
mUtranBands = new ArrayList<>();
in.readList(mUtranBands, Integer.class.getClassLoader());
mEutranBands = new ArrayList<>();
in.readList(mEutranBands, Integer.class.getClassLoader());
mNgranBands = new ArrayList<>();
in.readList(mNgranBands, Integer.class.getClassLoader());
mLogicalModemUuids = in.createStringArrayList();
mSimSlotCapabilities = in.createTypedArrayList(SimSlotCapability.CREATOR);
int length = in.readInt();
mConcurrentFeaturesSupport = new ArrayList<>();
for (int i = 0; i < length; i++) {
ArrayList<Long> feature = new ArrayList<>();
in.readList(feature, Long.class.getClassLoader());
mConcurrentFeaturesSupport.add(feature);
}
}
/**
* 3GPP UE category for a given Radio Access Network and direction.
*
* References are:
* TS 25.306 Table 4.1a EUTRAN downlink
* TS 25.306 Table 5.1a-2 EUTRAN uplink
* TS 25.306 Table 5.1a UTRAN downlink
* TS 25.306 Table 5.1g UTRAN uplink
*
* @param uplink true for uplink direction and false for downlink direction.
* @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
* @return the UE category, or -1 if it is not supported.
*/
public int getUeCategory(boolean uplink, @RadioAccessNetworkType int accessNetworkType) {
if (uplink) {
switch (accessNetworkType) {
case AccessNetworkType.UTRAN: return mUtranUeCategoryUl;
case AccessNetworkType.EUTRAN: return mEutranUeCategoryUl;
default: return -1;
}
} else {
switch (accessNetworkType) {
case AccessNetworkType.UTRAN: return mUtranUeCategoryDl;
case AccessNetworkType.EUTRAN: return mEutranUeCategoryDl;
default: return -1;
}
}
}
/**
* In cellular devices that support a greater number of logical modems than
* Internet connections, some devices support a grace period to allow a smooth "handover"
* between those connections. If that feature is supported, then this API will provide
* the length of that grace period in milliseconds. If it is not supported, the default value
* for the grace period is 0.
* @return handover linger time in milliseconds, or 0 if it is not supported.
*/
public long getPsDataConnectionLingerTimeMillis() {
return mPsDataConnectionLingerTimeMillis;
}
/**
* The radio access technologies this device is capable of supporting.
* @return a bitfield of all supported network types, defined in {@link TelephonyManager}
*/
public @NetworkTypeBitMask long getSupportedRats() {
return mSupportedRats;
}
/**
* List of supported cellular bands for the given accessNetworkType.
* @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
* @return a list of bands, or an empty list if the access network type is unsupported.
*/
public @NonNull List<Integer> getBands(@RadioAccessNetworkType int accessNetworkType) {
switch (accessNetworkType) {
case AccessNetworkType.GERAN: return mGeranBands;
case AccessNetworkType.UTRAN: return mUtranBands;
case AccessNetworkType.EUTRAN: return mEutranBands;
case AccessNetworkType.NGRAN: return mNgranBands;
default: return new ArrayList<>();
}
}
/**
* List of logical modem UUIDs, each typically "com.xxxx.lmX", where X is the logical modem ID.
* @return a list of modem UUIDs, one for every logical modem the device has.
*/
public @NonNull List<String> getLogicalModemUuids() {
return mLogicalModemUuids;
}
/**
* List of {@link SimSlotCapability} for the device. The order of SIMs corresponds to the
* order of modems in {@link #getLogicalModemUuids}.
* @return a list of SIM slot capabilities, one for every SIM slot the device has.
*/
public @NonNull List<SimSlotCapability> getSimSlotCapabilities() {
return mSimSlotCapabilities;
}
/**
* A List of Lists of concurrently supportable modem feature sets.
*
* Each entry in the top-level list is an independent configuration across all modems
* that describes the capabilities of the device as a whole.
*
* Each entry in the second-level list is a bitfield of ModemFeatures that describes
* the capabilities for a single modem. In the second-level list, the order of the modems
* corresponds to order of the UUIDs in {@link #getLogicalModemUuids}.
*
* For symmetric capabilities that can only be active on one modem at a time, there will be
* multiple configurations (equal to the number of modems) that shows it active on each modem.
* For asymmetric capabilities that are only available on one of the modems, all configurations
* will have that capability on just that one modem.
*
* The example below shows the concurrentFeaturesSupport for a 3-modem device with
* theoretical capabilities SYMMETRIC (available on all modems, but only one at a time) and
* ASYMMETRIC (only available on the first modem):
* {
* Configuration 1: ASYMMETRIC and SYMMETRIC on modem 1, modem 2 empty, modem 3 empty
* {(ASYMMETRIC | SYMMETRIC), (), ()},
*
* Configuration 2: ASYMMETRIC on modem 1, SYMMETRIC on modem 2, modem 3 empty
* {(ASYMMETRIC), (SYMMETRIC), ()},
*
* Configuration 3: ASYMMETRIC on modem 1, modem 2 empty, SYMMETRIC on modem 3
* {(ASYMMETRIC), (), (SYMMETRIC)}
* }
*
* @return List of all concurrently supportable modem features.
*/
public @NonNull @ModemFeature List<List<Long>> getConcurrentFeaturesSupport() {
return mConcurrentFeaturesSupport;
}
/**
* How many modems can simultaneously have PS attached.
* @return maximum number of active PS voice connections.
*/
public int getMaxActivePsVoice() {
return countFeature(MODEM_FEATURE_PS_VOICE_REG);
}
/**
* How many modems can simultaneously support active data connections.
* For DSDS, this will be 1, and for DSDA this will be 2.
* @return maximum number of active Internet data sessions.
*/
public int getMaxActiveInternetData() {
return countFeature(MODEM_FEATURE_INTERACTIVE_DATA_SESSION);
}
/**
* How many modems can simultaneously have dedicated bearer capability.
* @return maximum number of active dedicated bearers.
*/
public int getMaxActiveDedicatedBearers() {
return countFeature(MODEM_FEATURE_DEDICATED_BEARER);
}
/**
* Whether the CBRS band 48 is supported or not.
* @return true if any RadioAccessNetwork supports CBRS and false if none do.
* @hide
*/
public boolean isCbrsSupported() {
return mEutranBands.contains(AccessNetworkConstants.EutranBand.BAND_48)
|| mNgranBands.contains(AccessNetworkConstants.NgranBands.BAND_48);
}
private int countFeature(@ModemFeature long feature) {
int count = 0;
for (long featureSet : mConcurrentFeaturesSupport.get(0)) {
if ((featureSet & feature) != 0) {
count++;
}
}
return count;
}
@Override
public String toString() {
return "utranUeCategoryDl=" + mUtranUeCategoryDl
+ " utranUeCategoryUl=" + mUtranUeCategoryUl
+ " eutranUeCategoryDl=" + mEutranUeCategoryDl
+ " eutranUeCategoryUl=" + mEutranUeCategoryUl
+ " psDataConnectionLingerTimeMillis=" + mPsDataConnectionLingerTimeMillis
+ " supportedRats=" + mSupportedRats + " geranBands=" + mGeranBands
+ " utranBands=" + mUtranBands + " eutranBands=" + mEutranBands
+ " ngranBands=" + mNgranBands + " logicalModemUuids=" + mLogicalModemUuids
+ " simSlotCapabilities=" + mSimSlotCapabilities
+ " concurrentFeaturesSupport=" + mConcurrentFeaturesSupport;
}
@Override
public int hashCode() {
return Objects.hash(mUtranUeCategoryDl, mUtranUeCategoryUl, mEutranUeCategoryDl,
mEutranUeCategoryUl, mPsDataConnectionLingerTimeMillis, mSupportedRats, mGeranBands,
mUtranBands, mEutranBands, mNgranBands, mLogicalModemUuids, mSimSlotCapabilities,
mConcurrentFeaturesSupport);
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof PhoneCapability) || hashCode() != o.hashCode()) {
return false;
}
if (this == o) {
return true;
}
PhoneCapability s = (PhoneCapability) o;
return (mUtranUeCategoryDl == s.mUtranUeCategoryDl
&& mUtranUeCategoryUl == s.mUtranUeCategoryUl
&& mEutranUeCategoryDl == s.mEutranUeCategoryDl
&& mEutranUeCategoryUl == s.mEutranUeCategoryUl
&& mPsDataConnectionLingerTimeMillis == s.mPsDataConnectionLingerTimeMillis
&& mSupportedRats == s.mSupportedRats
&& mGeranBands.equals(s.mGeranBands)
&& mUtranBands.equals(s.mUtranBands)
&& mEutranBands.equals(s.mEutranBands)
&& mNgranBands.equals(s.mNgranBands)
&& mLogicalModemUuids.equals(s.mLogicalModemUuids)
&& mSimSlotCapabilities.equals(s.mSimSlotCapabilities)
&& mConcurrentFeaturesSupport.equals(s.mConcurrentFeaturesSupport));
}
/**
* {@link Parcelable#describeContents}
*/
public @Parcelable.ContentsFlags int describeContents() {
return 0;
}
/**
* {@link Parcelable#writeToParcel}
*/
public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
dest.writeInt(mUtranUeCategoryDl);
dest.writeInt(mUtranUeCategoryUl);
dest.writeInt(mEutranUeCategoryDl);
dest.writeInt(mEutranUeCategoryUl);
dest.writeLong(mPsDataConnectionLingerTimeMillis);
dest.writeLong(mSupportedRats);
dest.writeList(mGeranBands);
dest.writeList(mUtranBands);
dest.writeList(mEutranBands);
dest.writeList(mNgranBands);
dest.writeStringList(mLogicalModemUuids);
dest.writeTypedList(mSimSlotCapabilities);
dest.writeInt(mConcurrentFeaturesSupport.size());
for (List<Long> feature : mConcurrentFeaturesSupport) {
dest.writeList(feature);
}
}
public static final @NonNull Parcelable.Creator<PhoneCapability> CREATOR =
new Parcelable.Creator() {
public PhoneCapability createFromParcel(Parcel in) {
return new PhoneCapability(in);
}
public PhoneCapability[] newArray(int size) {
return new PhoneCapability[size];
}
};
}