Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5080367a authored by Rambo Wang's avatar Rambo Wang Committed by Android (Google) Code Review
Browse files

Merge "Introduce APIs to support Data Only Cellular Service" into main

parents 6300e048 558016e7
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -43277,6 +43277,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 @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final String KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY = "cellular_service_capabilities_int_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";
@@ -45272,6 +45273,7 @@ package android.telephony {
    method @Nullable public String getMncString();
    method @Deprecated public String getNumber();
    method public int getPortIndex();
    method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") @NonNull public java.util.Set<java.lang.Integer> getServiceCapabilities();
    method public int getSimSlotIndex();
    method public int getSubscriptionId();
    method public int getSubscriptionType();
@@ -45353,6 +45355,9 @@ package android.telephony {
    field public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; // 0x2
    field public static final int PHONE_NUMBER_SOURCE_IMS = 3; // 0x3
    field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1
    field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_DATA = 3; // 0x3
    field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_SMS = 2; // 0x2
    field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_VOICE = 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
@@ -45601,6 +45606,8 @@ package android.telephony {
    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabled();
    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabledForReason(int);
    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataRoamingEnabled();
    method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public boolean isDeviceSmsCapable();
    method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public boolean isDeviceVoiceCapable();
    method public boolean isEmergencyNumber(@NonNull String);
    method public boolean isHearingAidCompatibilitySupported();
    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isManualNetworkSelectionAllowed();
@@ -45610,9 +45617,9 @@ package android.telephony {
    method @RequiresPermission(android.Manifest.permission.READ_BASIC_PHONE_STATE) public boolean isPremiumCapabilityAvailableForPurchase(int);
    method public boolean isRadioInterfaceCapabilitySupported(@NonNull String);
    method public boolean isRttSupported();
    method public boolean isSmsCapable();
    method @Deprecated public boolean isSmsCapable();
    method @Deprecated public boolean isTtyModeSupported();
    method public boolean isVoiceCapable();
    method @Deprecated public boolean isVoiceCapable();
    method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
    method public boolean isWorldPhone();
    method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
+9 −1
Original line number Diff line number Diff line
@@ -4940,6 +4940,13 @@ public final class Telephony {
         */
        public static final String COLUMN_IS_NTN = "is_ntn";

        /**
         * TelephonyProvider column name to indicate the service capability bitmasks.
         *
         * @hide
         */
        public static final String COLUMN_SERVICE_CAPABILITIES = "service_capabilities";

        /** All columns in {@link SimInfo} table. */
        private static final List<String> ALL_COLUMNS = List.of(
                COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
@@ -5011,7 +5018,8 @@ public final class Telephony {
                COLUMN_USER_HANDLE,
                COLUMN_SATELLITE_ENABLED,
                COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
                COLUMN_IS_NTN
                COLUMN_IS_NTN,
                COLUMN_SERVICE_CAPABILITIES
        );

        /**
+44 −0
Original line number Diff line number Diff line
@@ -10050,6 +10050,49 @@ public class CarrierConfigManager {
    public static final String KEY_AUTO_DATA_SWITCH_RAT_SIGNAL_SCORE_BUNDLE =
            "auto_data_switch_rat_signal_score_string_bundle";
    // TODO(b/316183370): replace @code with @link in javadoc after feature is released
    /**
     * An array of cellular services supported by a subscription.
     *
     * <p>Permissible values include:
     * <ul>
     *   <li>{@code SubscriptionManager#SERVICE_CAPABILITY_VOICE} for voice services</li>
     *   <li>{@code SubscriptionManager#SERVICE_CAPABILITY_SMS} for SMS services</li>
     *   <li>{@code SubscriptionManager#SERVICE_CAPABILITY_DATA} for data services</li>
     * </ul>
     *
     * <p>Carrier-specific factors may influence how these services are supported. Therefore,
     * modifying this carrier configuration might not always enable the specified services. These
     * capability bitmasks should be considered as indicators of a carrier's preferred services
     * to enhance user experience, rather than as absolute platform guarantees.
     *
     * <p>Device-level service capabilities, defined by
     * {@code TelephonyManager#isDeviceVoiceCapable} and
     * {@code TelephonyManager#isDeviceSmsCapable}, take precedence over these subscription-level
     * settings. For instance, a device where {@code TelephonyManager#isDeviceVoiceCapable} returns
     * false may not be able to make voice calls, even if subscribed to a service marked as
     * voice-capable.
     *
     * <p>To determine a subscription's cellular service capabilities, use
     * {@code SubscriptionInfo#getServiceCapabilities()}. To track changes in services, register
     * a {@link SubscriptionManager.OnSubscriptionsChangedListener} and invoke the
     * same method in its callback.
     *
     * <p>Emergency service availability may not depend on the cellular service capabilities.
     * For example, emergency calls might be possible on a subscription even if it lacks
     * {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE}.
     *
     * <p>If unset, the default value is “[1, 2, 3]” (supports all cellular services).
     *
     * @see TelephonyManager#isDeviceVoiceCapable
     * @see TelephonyManager#isDeviceSmsCapable
     * @see SubscriptionInfo#getServiceCapabilities()
     * @see SubscriptionManager.OnSubscriptionsChangedListener
     */
    @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
    public static final String KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY =
            "cellular_service_capabilities_int_array";
    /** The default value for every variable. */
    private static final PersistableBundle sDefaults;
@@ -10837,6 +10880,7 @@ public class CarrierConfigManager {
                new boolean[] {false, false, true, false, false});
        sDefaults.putStringArray(KEY_CARRIER_SERVICE_NAME_STRING_ARRAY, new String[0]);
        sDefaults.putStringArray(KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY, new String[0]);
        sDefaults.putIntArray(KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY, new int[]{1, 2, 3});
    }
    /**
+86 −2
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * A Parcelable class for Subscription Information.
@@ -261,6 +262,11 @@ public class SubscriptionInfo implements Parcelable {
     */
    private final boolean mIsOnlyNonTerrestrialNetwork;

    /**
     * The service capabilities (in the form of bitmask combination) the subscription supports.
     */
    private final int mServiceCapabilities;

    /**
     * @hide
     *
@@ -386,6 +392,7 @@ public class SubscriptionInfo implements Parcelable {
        this.mPortIndex = portIndex;
        this.mUsageSetting = usageSetting;
        this.mIsOnlyNonTerrestrialNetwork = false;
        this.mServiceCapabilities = 0;
    }

    /**
@@ -425,6 +432,7 @@ public class SubscriptionInfo implements Parcelable {
        this.mPortIndex = builder.mPortIndex;
        this.mUsageSetting = builder.mUsageSetting;
        this.mIsOnlyNonTerrestrialNetwork = builder.mIsOnlyNonTerrestrialNetwork;
        this.mServiceCapabilities = builder.mServiceCapabilities;
    }

    /**
@@ -882,6 +890,44 @@ public class SubscriptionInfo implements Parcelable {
        return mIsOnlyNonTerrestrialNetwork;
    }

    // TODO(b/316183370): replace @code with @link in javadoc after feature is released
    /**
     * Retrieves the service capabilities for the current subscription.
     *
     * <p>These capabilities are hint to system components and applications, allowing them to
     * enhance user experience. For instance, a Dialer application can inform the user that the
     * current subscription is incapable of making voice calls if the voice service is not
     * available.
     *
     * <p>Correct usage of these service capabilities must also consider the device's overall
     * service capabilities. For example, even if the subscription supports voice calls, a voice
     * call might not be feasible on a device that only supports data services. To determine the
     * device's capabilities for voice and SMS services, refer to
     * {@code TelephonyManager#isDeviceVoiceCapable()} and
     * {@code TelephonyManager#isDeviceSmsCapable()}.
     *
     * <p>Emergency service availability may not directly correlate with the subscription or
     * device's general service capabilities. In some cases, emergency calls might be possible
     * even if the subscription or device does not typically support voice services.
     *
     * @return A set of integer representing the subscription's service capabilities,
     * defined by {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE},
     * {@code SubscriptionManager#SERVICE_CAPABILITY_SMS}
     * and {@code SubscriptionManager#SERVICE_CAPABILITY_DATA}.
     *
     * @see TelephonyManager#isDeviceVoiceCapable()
     * @see TelephonyManager#isDeviceSmsCapable()
     * @see CarrierConfigManager#KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY
     * @see SubscriptionManager#SERVICE_CAPABILITY_VOICE
     * @see SubscriptionManager#SERVICE_CAPABILITY_SMS
     * @see SubscriptionManager#SERVICE_CAPABILITY_DATA
     */
    @NonNull
    @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
    public @SubscriptionManager.ServiceCapability Set<Integer> getServiceCapabilities() {
        return SubscriptionManager.getServiceCapabilitiesSet(mServiceCapabilities);
    }

    @NonNull
    public static final Parcelable.Creator<SubscriptionInfo> CREATOR =
            new Parcelable.Creator<SubscriptionInfo>() {
@@ -919,6 +965,8 @@ public class SubscriptionInfo implements Parcelable {
                    .setUiccApplicationsEnabled(source.readBoolean())
                    .setUsageSetting(source.readInt())
                    .setOnlyNonTerrestrialNetwork(source.readBoolean())
                    .setServiceCapabilities(
                            SubscriptionManager.getServiceCapabilitiesSet(source.readInt()))
                    .build();
        }

@@ -961,6 +1009,7 @@ public class SubscriptionInfo implements Parcelable {
        dest.writeBoolean(mAreUiccApplicationsEnabled);
        dest.writeInt(mUsageSetting);
        dest.writeBoolean(mIsOnlyNonTerrestrialNetwork);
        dest.writeInt(mServiceCapabilities);
    }

    @Override
@@ -1024,6 +1073,8 @@ public class SubscriptionInfo implements Parcelable {
                + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled
                + " usageSetting=" + SubscriptionManager.usageSettingToString(mUsageSetting)
                + " isOnlyNonTerrestrialNetwork=" + mIsOnlyNonTerrestrialNetwork
                + " serviceCapabilities=" + SubscriptionManager.getServiceCapabilitiesSet(
                mServiceCapabilities).toString()
                + "]";
    }

@@ -1049,7 +1100,8 @@ public class SubscriptionInfo implements Parcelable {
                that.mNativeAccessRules) && Arrays.equals(mCarrierConfigAccessRules,
                that.mCarrierConfigAccessRules) && Objects.equals(mGroupUuid, that.mGroupUuid)
                && mCountryIso.equals(that.mCountryIso) && mGroupOwner.equals(that.mGroupOwner)
                && mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork;
                && mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork
                && mServiceCapabilities == that.mServiceCapabilities;
    }

    @Override
@@ -1058,7 +1110,7 @@ public class SubscriptionInfo implements Parcelable {
                mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mIsEmbedded,
                mCardString, mIsOpportunistic, mGroupUuid, mCountryIso, mCarrierId, mProfileClass,
                mType, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting, mCardId,
                mIsGroupDisabled, mIsOnlyNonTerrestrialNetwork);
                mIsGroupDisabled, mIsOnlyNonTerrestrialNetwork, mServiceCapabilities);
        result = 31 * result + Arrays.hashCode(mEhplmns);
        result = 31 * result + Arrays.hashCode(mHplmns);
        result = 31 * result + Arrays.hashCode(mNativeAccessRules);
@@ -1262,6 +1314,11 @@ public class SubscriptionInfo implements Parcelable {
         */
        private boolean mIsOnlyNonTerrestrialNetwork = false;

        /**
         * Service capabilities bitmasks the subscription supports.
         */
        private int mServiceCapabilities = 0;

        /**
         * Default constructor.
         */
@@ -1305,6 +1362,7 @@ public class SubscriptionInfo implements Parcelable {
            mPortIndex = info.mPortIndex;
            mUsageSetting = info.mUsageSetting;
            mIsOnlyNonTerrestrialNetwork = info.mIsOnlyNonTerrestrialNetwork;
            mServiceCapabilities = info.mServiceCapabilities;
        }

        /**
@@ -1702,6 +1760,32 @@ public class SubscriptionInfo implements Parcelable {
            return this;
        }

        /**
         * Set the service capabilities that the subscription supports.
         *
         * @param capabilities Bitmask combination of SubscriptionManager
         *                     .SERVICE_CAPABILITY_XXX.
         * @return The builder.
         *
         * @throws IllegalArgumentException when any capability is not supported.
         */
        @NonNull
        @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
        public Builder setServiceCapabilities(
                @NonNull @SubscriptionManager.ServiceCapability Set<Integer> capabilities) {
            int combinedCapabilities = 0;
            for (int capability : capabilities) {
                if (capability < SubscriptionManager.SERVICE_CAPABILITY_VOICE
                        || capability > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
                    throw new IllegalArgumentException(
                            "Invalid service capability value: " + capability);
                }
                combinedCapabilities |= SubscriptionManager.serviceCapabilityToBitmask(capability);
            }
            mServiceCapabilities = combinedCapabilities;
            return this;
        }

        /**
         * Build the {@link SubscriptionInfo}.
         *
+124 −0
Original line number Diff line number Diff line
@@ -88,10 +88,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -1138,6 +1140,14 @@ public class SubscriptionManager {
     */
    public static final String IS_NTN = SimInfo.COLUMN_IS_NTN;

    /**
     * TelephonyProvider column name to identify service capabilities.
     * Disabled by default.
     * <P>Type: INTEGER (int)</P>
     * @hide
     */
    public static final String SERVICE_CAPABILITIES = SimInfo.COLUMN_SERVICE_CAPABILITIES;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"USAGE_SETTING_"},
@@ -1347,6 +1357,86 @@ public class SubscriptionManager {
            })
    public @interface PhoneNumberSource {}

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"SERVICE_CAPABILITY"},
            value = {
                    SERVICE_CAPABILITY_VOICE,
                    SERVICE_CAPABILITY_SMS,
                    SERVICE_CAPABILITY_DATA,
            })
    public @interface ServiceCapability {
    }

    /**
     * Represents a value indicating the voice calling capabilities of a subscription.
     *
     * <p>This value identifies whether the subscription supports various voice calling services.
     * These services can include circuit-switched (CS) calling, packet-switched (PS) IMS (IP
     * Multimedia Subsystem) calling, and over-the-top (OTT) calling options.
     *
     * <p>Note: The availability of emergency calling services is not solely dependent on this
     * voice capability. Emergency services may be accessible even if the subscription lacks
     * standard voice capabilities. However, the device's ability to support emergency calls
     * can be influenced by its inherent voice capabilities, as determined by
     * {@link TelephonyManager#isDeviceVoiceCapable()}.
     *
     * @see TelephonyManager#isDeviceVoiceCapable()
     */
    @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
    public static final int SERVICE_CAPABILITY_VOICE = 1;

    /**
     * Represents a value indicating the SMS capabilities of a subscription.
     *
     * <p>This value identifies whether the subscription supports various sms services.
     * These services can include circuit-switched (CS) SMS, packet-switched (PS) IMS (IP
     * Multimedia Subsystem) SMS, and over-the-top (OTT) SMS options.
     *
     * <p>Note: The availability of emergency SMS services is not solely dependent on this
     * sms capability. Emergency services may be accessible even if the subscription lacks
     * standard sms capabilities. However, the device's ability to support emergency sms
     * can be influenced by its inherent sms capabilities, as determined by
     * {@link TelephonyManager#isDeviceSmsCapable()}.
     *
     * @see TelephonyManager#isDeviceSmsCapable()
     */
    @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
    public static final int SERVICE_CAPABILITY_SMS = 2;

    /**
     * Represents a value indicating the data calling capabilities of a subscription.
     */
    @FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
    public static final int SERVICE_CAPABILITY_DATA = 3;

    /**
     * Maximum value of service capabilities supported so far.
     * @hide
     */
    public static final int SERVICE_CAPABILITY_MAX = SERVICE_CAPABILITY_DATA;

    /**
     * Bitmask for {@code SERVICE_CAPABILITY_VOICE}.
     * @hide
     */
    public static final int SERVICE_CAPABILITY_VOICE_BITMASK =
            serviceCapabilityToBitmask(SERVICE_CAPABILITY_VOICE);

    /**
     * Bitmask for {@code SERVICE_CAPABILITY_SMS}.
     * @hide
     */
    public static final int SERVICE_CAPABILITY_SMS_BITMASK =
            serviceCapabilityToBitmask(SERVICE_CAPABILITY_SMS);

    /**
     * Bitmask for {@code SERVICE_CAPABILITY_DATA}.
     * @hide
     */
    public static final int SERVICE_CAPABILITY_DATA_BITMASK =
            serviceCapabilityToBitmask(SERVICE_CAPABILITY_DATA);

    private final Context mContext;

    /**
@@ -4484,4 +4574,38 @@ public class SubscriptionManager {
        }
        return new ArrayList<>();
    }

    /**
     * @return the bitmasks combination of all service capabilities.
     * @hide
     */
    public static int getAllServiceCapabilityBitmasks() {
        return SERVICE_CAPABILITY_VOICE_BITMASK | SERVICE_CAPABILITY_SMS_BITMASK
                | SERVICE_CAPABILITY_DATA_BITMASK;
    }

    /**
     * @return The set of service capability from a bitmask combined one.
     * @hide
     */
    @NonNull
    @ServiceCapability
    public static Set<Integer> getServiceCapabilitiesSet(int combinedServiceCapabilities) {
        Set<Integer> capabilities = new HashSet<>();
        for (int i = SERVICE_CAPABILITY_VOICE; i <= SERVICE_CAPABILITY_MAX; i++) {
            final int capabilityBitmask = serviceCapabilityToBitmask(i);
            if ((combinedServiceCapabilities & capabilityBitmask) == capabilityBitmask) {
                capabilities.add(i);
            }
        }
        return Collections.unmodifiableSet(capabilities);
    }

    /**
     * @return The service capability bitmask from a {@link ServiceCapability} value.
     * @hide
     */
    public static int serviceCapabilityToBitmask(@ServiceCapability int capability) {
        return 1 << (capability - 1);
    }
}
Loading