diff --git a/core/api/current.txt b/core/api/current.txt index b6b91daedf987..4fb42f2fc2fcf 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -41476,6 +41476,7 @@ package android.telephony { field public static final String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array"; field public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int"; field public static final String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array"; + field public static final String KEY_CELLULAR_USAGE_SETTING_INT = "cellular_usage_setting_int"; field public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL = "check_pricing_with_carrier_data_roaming_bool"; field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_BOOL = "ci_action_on_sys_update_bool"; field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string"; @@ -43092,6 +43093,7 @@ package android.telephony { method public int getSimSlotIndex(); method public int getSubscriptionId(); method public int getSubscriptionType(); + method public int getUsageSetting(); method public boolean isEmbedded(); method public boolean isOpportunistic(); method public void writeToParcel(android.os.Parcel, int); @@ -43166,6 +43168,10 @@ package android.telephony { field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1 field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0 field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1 + field public static final int USAGE_SETTING_DATA_CENTRIC = 2; // 0x2 + field public static final int USAGE_SETTING_DEFAULT = 0; // 0x0 + field public static final int USAGE_SETTING_UNKNOWN = -1; // 0xffffffff + field public static final int USAGE_SETTING_VOICE_CENTRIC = 1; // 0x1 } public static class SubscriptionManager.OnOpportunisticSubscriptionsChangedListener { diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index a00dd514112f4..e3c396976f6c5 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -5453,5 +5453,12 @@ public final class Telephony { */ public static final String COLUMN_PHONE_NUMBER_SOURCE_IMS = "phone_number_source_ims"; + + /** + * TelephonyProvider column name for the device's preferred usage setting. + * + * @hide + */ + public static final String COLUMN_USAGE_SETTING = "usage_setting"; } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 078d79b4c750a..050d20eb9ef5b 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3333,6 +3333,20 @@ and one pSIM) --> 1 + + 1 + + + + 1 + 2 + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1295210caf9e0..504ad237345ac 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -492,6 +492,8 @@ + + diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 4bfb2d815f90a..53261cb0a599e 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -4465,6 +4465,29 @@ public class CarrierConfigManager { public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING = "subscription_group_uuid_string"; + /** + * Controls the cellular usage setting. + * + * The usage setting indicates whether a device will remain attached to a network based on + * the primary use case for the service. A device will detach and search for a more-preferred + * network if the primary use case (voice or data) is not satisfied. Depending on the type + * of device, it may operate in a voice or data-centric mode by default. + * + *

Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3. + * Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221 + * Annex A. + * + * Either omit this key or pass a value of + * {@link SubscriptionManager#USAGE_SETTING_UNKNOWN unknown} to preserve the current setting. + * + * {@link SubscriptionManager#USAGE_SETTING_DEFAULT default}, + * {@link SubscriptionManager#USAGE_SETTING_VOICE_CENTRIC voice-centric}, + * or {@link SubscriptionManager#USAGE_SETTING_DATA_CENTRIC data-centric}. + * {@see SubscriptionInfo#getUsageSetting} + */ + public static final String KEY_CELLULAR_USAGE_SETTING_INT = + "cellular_usage_setting_int"; + /** * Data switch validation minimal gap time, in milliseconds. * @@ -6087,6 +6110,8 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY, new String[]{ "source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, " + "target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"}); + sDefaults.putInt(KEY_CELLULAR_USAGE_SETTING_INT, + SubscriptionManager.USAGE_SETTING_UNKNOWN); } /** diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index d11ad914061da..c36eb2f9cf657 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -37,6 +37,7 @@ import android.os.Build; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; +import android.telephony.SubscriptionManager.UsageSetting; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; @@ -226,6 +227,11 @@ public class SubscriptionInfo implements Parcelable { */ private final int mPortIndex; + /** + * Subscription's preferred usage setting. + */ + private @UsageSetting int mUsageSetting = SubscriptionManager.USAGE_SETTING_UNKNOWN; + /** * Public copy constructor. * @hide @@ -284,6 +290,7 @@ public class SubscriptionInfo implements Parcelable { cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass, subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 0); } + /** * @hide */ @@ -295,6 +302,24 @@ public class SubscriptionInfo implements Parcelable { int carrierId, int profileClass, int subType, @Nullable String groupOwner, @Nullable UiccAccessRule[] carrierConfigAccessRules, boolean areUiccApplicationsEnabled, int portIndex) { + this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, + roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, + cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass, + subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, + portIndex, SubscriptionManager.USAGE_SETTING_DEFAULT); + } + + /** + * @hide + */ + public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, + CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, + Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, + @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, + boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, + int carrierId, int profileClass, int subType, @Nullable String groupOwner, + @Nullable UiccAccessRule[] carrierConfigAccessRules, + boolean areUiccApplicationsEnabled, int portIndex, @UsageSetting int usageSetting) { this.mId = id; this.mIccId = iccId; this.mSimSlotIndex = simSlotIndex; @@ -322,6 +347,7 @@ public class SubscriptionInfo implements Parcelable { this.mCarrierConfigAccessRules = carrierConfigAccessRules; this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled; this.mPortIndex = portIndex; + this.mUsageSetting = usageSetting; } /** * @return the subscription ID. @@ -796,7 +822,18 @@ public class SubscriptionInfo implements Parcelable { return mAreUiccApplicationsEnabled; } - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { + /** + * Get the usage setting for this subscription. + * + * @return the usage setting used for this subscription. + */ + public @UsageSetting int getUsageSetting() { + return mUsageSetting; + } + + public static final @android.annotation.NonNull + Parcelable.Creator CREATOR = + new Parcelable.Creator() { @Override public SubscriptionInfo createFromParcel(Parcel source) { int id = source.readInt(); @@ -828,12 +865,14 @@ public class SubscriptionInfo implements Parcelable { UiccAccessRule[] carrierConfigAccessRules = source.createTypedArray( UiccAccessRule.CREATOR); boolean areUiccApplicationsEnabled = source.readBoolean(); + int usageSetting = source.readInt(); SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType, - groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, portId); + groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, + portId, usageSetting); info.setAssociatedPlmns(ehplmns, hplmns); return info; } @@ -875,6 +914,7 @@ public class SubscriptionInfo implements Parcelable { dest.writeString(mGroupOwner); dest.writeTypedArray(mCarrierConfigAccessRules, flags); dest.writeBoolean(mAreUiccApplicationsEnabled); + dest.writeInt(mUsageSetting); } @Override @@ -919,7 +959,8 @@ public class SubscriptionInfo implements Parcelable { + " subscriptionType=" + mSubscriptionType + " groupOwner=" + mGroupOwner + " carrierConfigAccessRules=" + Arrays.toString(mCarrierConfigAccessRules) - + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled + "}"; + + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled + + " usageSetting=" + mUsageSetting + "}"; } @Override @@ -927,7 +968,8 @@ public class SubscriptionInfo implements Parcelable { return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded, mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled, - mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex); + mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, + mUsageSetting); } @Override @@ -967,6 +1009,7 @@ public class SubscriptionInfo implements Parcelable { && Arrays.equals(mNativeAccessRules, toCompare.mNativeAccessRules) && mProfileClass == toCompare.mProfileClass && Arrays.equals(mEhplmns, toCompare.mEhplmns) - && Arrays.equals(mHplmns, toCompare.mHplmns); + && Arrays.equals(mHplmns, toCompare.mHplmns) + && mUsageSetting == toCompare.mUsageSetting; } } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 821b74ab87e4c..4e6a7a36d879e 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1037,12 +1037,75 @@ public class SubscriptionManager { public static final String UICC_APPLICATIONS_ENABLED = SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED; /** - * Indicate which network type is allowed. By default it's enabled. + * Indicate which network type is allowed. * @hide */ public static final String ALLOWED_NETWORK_TYPES = SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"USAGE_SETTING_"}, + value = { + USAGE_SETTING_UNKNOWN, + USAGE_SETTING_DEFAULT, + USAGE_SETTING_VOICE_CENTRIC, + USAGE_SETTING_DATA_CENTRIC}) + public @interface UsageSetting {} + + /** + * The usage setting is unknown. + * + * This will be the usage setting returned on devices that do not support querying the + * or setting the usage setting. + * + * It may also be provided by a carrier that wishes to provide a value to avoid making any + * settings changes. + */ + public static final int USAGE_SETTING_UNKNOWN = -1; + + /** + * Subscription uses the default setting. + * + * The value is based upon device capability and the other properties of the subscription. + * + * Most subscriptions will default to voice-centric when in a phone. + * + * An opportunistic subscription will default to data-centric. + * + * {@see SubscriptionInfo#isOpportunistic} + */ + public static final int USAGE_SETTING_DEFAULT = 0; + + /** + * This subscription is forced to voice-centric mode + * + *

Refer to voice-centric mode in 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3. + * Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221 + * Annex A. + */ + public static final int USAGE_SETTING_VOICE_CENTRIC = 1; + + /** + * This subscription is forced to data-centric mode + * + *

Refer to data-centric mode in 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3. + * Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221 + * Annex A. + */ + public static final int USAGE_SETTING_DATA_CENTRIC = 2; + + /** + * Indicate the preferred usage setting for the subscription. + * + * 0 - Default - If the value has not been explicitly set, it will be "default" + * 1 - Voice-centric + * 2 - Data-centric + * + * @hide + */ + public static final String USAGE_SETTING = SimInfo.COLUMN_USAGE_SETTING; + /** * Broadcast Action: The user has changed one of the default subs related to * data, phone calls, or sms

@@ -3950,4 +4013,33 @@ public class SubscriptionManager { throw ex.rethrowAsRuntimeException(); } } + + /** + * Set the preferred usage setting. + * + * The cellular usage setting is a switch which controls the mode of operation for the cellular + * radio to either require or not require voice service. It is not managed via Android’s + * Settings. + * + * @param subscriptionId the subId of the subscription. + * @param usageSetting the requested usage setting. + * + * @throws IllegalStateException if a specific mode or setting the mode is not supported on a + * particular device. + * + *

Requires {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * or that the calling app has CarrierPrivileges for the given subscription. + * + * Note: This method will not allow the setting of USAGE_SETTING_UNKNOWN. + * + * @hide + */ + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + void setUsageSetting(int subscriptionId, @UsageSetting int usageSetting) { + if (VDBG) logd("[setUsageSetting]+ setting:" + usageSetting + " subId:" + subscriptionId); + setSubscriptionPropertyHelper(subscriptionId, "setUsageSetting", + (iSub)-> iSub.setUsageSetting( + usageSetting, subscriptionId, mContext.getOpPackageName())); + } } + diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index a900c84c1819c..1e38b9215d76d 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -313,4 +313,15 @@ interface ISub { void setPhoneNumber(int subId, int source, String number, String callingPackage, String callingFeatureId); + + /** + * Set the Usage Setting for this subscription. + * + * @param usageSetting the usage setting for this subscription + * @param subId the unique SubscriptionInfo index in database + * @param callingPackage The package making the IPC. + * + * @throws SecurityException if doesn't have MODIFY_PHONE_STATE or Carrier Privileges + */ + int setUsageSetting(int usageSetting, int subId, String callingPackage); }