Android 6.0 and higher include a capability for privileged apps to provide carrier-specific configuration to the platform. This functionality, based on the UICC Carrier Privileges introduced in Android 5.1 (Lollipop MR1), allows carrier configuration to be moved away from the static configuration overlays and gives carriers and OEMs the ability to dynamically provide carrier configuration to the platform through a defined interface.
A properly signed carrier app can either be preloaded in the system image, installed automatically, or manually installed through an app store. The app is queried by the platform to provide configuration for settings including:
- Roaming/nonroaming networks
- Visual voicemail
- SMS/MMS network settings
- VoLTE/IMS configurations
The determination of what values to return is entirely up to the carrier app and can be dynamic based on detailed information passed to the app through the platform.
The key benefits of this approach are:
- Dynamic configuration - Support for concepts like non-MCCMNC derived configuration, for example, mobile virtual network operators (MVNOs) or customer opt in to extra services.
- Support for devices sold through any channel - For example, an open market phone can be automatically configured with the right settings by downloading an app from an app store.
- Security - Privilege to provide this configuration is given only to apps signed by the carrier.
- Defined API - Previously this configuration was stored mostly in internal XML overlays within the framework and not through a public API. The carrier config API in Android 6.0 is public and well defined.
How it works
Load the config
The carrier configuration supplied by this feature is a set of key-value pairs that change various telephony-related behaviors in the platform.
The set of values for a particular device is determined by querying the following components in order:
- The carrier app (this is optional, but it's the recommended location for additional configuration beyond what exists in the Android Open Source Project (AOSP))
- The platform config app bundled with the system image
- Default values, hardcoded into the framework (equivalent to the behavior prior to Android 6.0)
The platform config app
A generic platform config app is bundled with the system image. This app can supply
values for any variables that the regular carrier app doesn't. The platform config
app can be found (in Android 6.0) in: packages/apps/CarrierConfig
This app’s purpose is to provide some per-network configuration when a carrier app isn't installed, and carriers/OEMs should make only minimal changes to it in their own images. Instead carriers should provide the separate carrier app for carrier customization, allowing updates to be distributed through avenues such as app stores.
How privilege is granted to a carrier app
The carrier app in question must be signed with the same certificate found on the SIM card, as documented in UICC Carrier Privileges.
What information is passed to the carrier app
The carrier app is supplied with the following values, enabling it to make a dynamic decision as to what values to return:
- MCC
- MNC
- SPN
- IMSI
- GID1
- GID2
- Carrier ID
For more information on integrating carrier IDs, see Integrating carrier IDs with CarrierConfig.
When loading the carrier config occurs
The building of the list of key value pairs occurs:
- When the SIM is loaded (boot, or SIM hot swap)
- When the carrier app manually triggers a reload
- When the carrier app gets updated
See the
android.service.carrier.CarrierService#onLoadConfig()
reference for more details.
Use the config
When the configuration is built, the values contained within it are used to set various values of system configuration, including:
- Internal framework telephony settings
- SDK-returned configuration values, for example, in SmsManager
- App settings like VVM connection values in the Dialer
Configuration keys
The list of keys is defined as part of the public SDK in android.telephony.CarrierConfigManager
and can't change within the same API level. See the table below for a summary of keys.
Build the app
Create the app
Your app must target the Android 6.0 API level (23).
Declare a class that overrides android.service.carrier.CarrierService
- Override
onLoadConfig
to return the values you wish to supply based on theservice.carrier.CarrierIdentifier
object passed. - Add logic to call
notifyConfigChangedForSubId
in scenarios where the carrier configuration may change over time (for example, when the user adds extra services to their account).
An example is below:
public class SampleCarrierConfigService extends CarrierService { private static final String TAG = "SampleCarrierConfigService"; public SampleCarrierConfigService() { Log.d(TAG, "Service created"); } @Override public PersistableBundle onLoadConfig(CarrierIdentifier id) { Log.d(TAG, "Config being fetched"); PersistableBundle config = new PersistableBundle(); config.putBoolean( CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL, true); config.putBoolean( CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false); config.putInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT, 6); // Check CarrierIdentifier and add more config if needed… return config; } }
For more details, see the
android.service.carrier.CarrierService
reference.
Name the class in the manifest
An example is below:
<service android:name=".SampleCarrierConfigService" android:label="@string/service_name" android:permission="android.permission.BIND_CARRIER_SERVICES"> <intent-filter> <action android:name="android.service.carrier.CarrierService"/></intent-filter> </service>
Sign the app with the same certificate on SIM
See UICC Carrier Privileges for the requirements.
Add APNs with a carrier app
To add APNs programmatically from a carrier app (for example, during SIM
activation), use
ContentResolver
APIs to add APN items to a content provider
identified by the URI
android.provider.Telephony.Carriers.CONTENT_URI
.
For more information about the table structure for the content URI, see
Telephony.Carriers
.
For more information, see APN and CarrierConfig.
Test the app
When you've built your configuration app, you can test your code with:
- A SIM containing a valid certificate signature
- A device running Android 6.0 and later, for example an Android device
Set carrier service capabilities
In Android, carrier service capabilities describe whether voice, messaging, and data services are supported on a device. Carriers can specify the carrier service capabilities for a device at the device level and at the subscription level (Android 15 or higher).
Device-level service capabilities
Device-level service capabilities are configured when a device is manufactured (can't be changed after manufacturing). Carriers can specify device-level capabilities through the following system resource overrides:
Apps can query the device-level service capabilities through the following APIs:
Subscription-level service capabilities
For devices running Android 15 or higher, carriers can specify the
service capabilities of the device at the subscription level. To specify subscription-level service
capabilities, use the
CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY
API. For example, to specify that a subscription is data only, set the value to
SubscriptionManager#SERVICE_CAPABILITY_DATA
.
Apps (preloaded system apps and third-party apps) can query the carrier
service capabilities for a specified subscription through the
SubscriptionInfo.getServiceCapabilities()
method. This lets app developers customize the user experience of apps based on
the available capabilities for the subscription. For example, app developers can
ensure that the dialer app doesn't allow making calls if the user is on a
data-only subscription.
Deprecated service capabilities APIs
Starting in Android 15, Android provides both device-level and subscription-level service capabilities. Because of this change, the existing device-level capabilities APIs were renamed for better readability. The following table lists the deprecated APIs and the renamed APIs introduced in Android 15:
Deprecated (Android 14 or lower) | Equivalent (Android 15 or higher) |
---|---|
TelephonyManager.isVoiceCapable() |
TelephonyManager.isDeviceVoiceCapable() |
TelephonyManager.isSmsCapable() |
TelephonyManager.isDeviceSmsCapable() |