Implement IMS

Android 9 introduces a new SystemApi interface called ImsService to help you implement IP Multimedia Subsystem (IMS). The ImsService API is a well-defined interface between the Android platform and a vendor or carrier-provided IMS implementation.

ImsService overview

Figure 1. ImsService overview

By using the ImsService interface, the IMS implementer can provide important signaling information to the platform, such as IMS registration information, SMS over IMS integration, and MmTel feature integration to provide voice and video calling. The ImsService API is an Android System API as well, meaning it can be built against the Android SDK directly instead of against the source. An IMS app that has been preinstalled on the device can also be configured to be Play Store updatable.

Examples and source

Android provides an app on AOSP that implements portions of the ImsService API for testing and development purposes. You can find the app at /testapps/ImsTestService.

You can find the documentation for the ImsService API in ImsService and in the other classes in the API.

Implementation

The ImsService API is a high level API that lets you implement IMS in many ways, depending on the hardware available. For example, the implementation changes depending on whether the IMS implementation is fully on the app processor or if it is partially or fully offloaded to the modem. Android does not provide a public HAL for offloading to the baseband processor, so any offloading must occur using your HAL extension to the modem.

Compatibility with older IMS implementations

Although Android 9 includes the ImsService API, devices using an older implementation for IMS are not able to support the API. For these devices, the older AIDL interfaces and wrapper classes have been moved to the android.telephony.ims.compat namespace. When upgrading to Android 9, older devices must do the following to continue the support of the older API.

  • Change the namespace of the ImsService implementation to extend from the android.telephony.ims.compat namespace API.
  • Modify the ImsService service definition in AndroidManifest.xml to use the android.telephony.ims.compat.ImsService intent-filter action, instead of the android.telephony.ims.ImsService action.

The framework will then bind to the ImsService using the compatibility layer provided in Android 9 to work with the legacy ImsService implementation.

ImsService registration with the framework

The ImsService API is implemented as a service, which the Android framework binds to in order to communicate with the IMS implementation. Three steps are necessary to register an app that implements an ImsService with the framework. First, the ImsService implementation must register itself with the platform using the AndroidManifest.xml of the app; second, it must define which IMS features the implementation supports (MmTel or RCS); and third, it must be verified as the trusted IMS implementation either in the carrier configuration or device overlay.

Service definition

The IMS app registers an ImsService with the framework by adding a service entry into the manifest using the following format:

<service
    android:name="com.egcorp.ims.EgImsService"
    android:directBootAware="true"
    Android:persistent="true"
    ...
    android:permission="android.permission.BIND_IMS_SERVICE" >
    ...
    <intent-filter>
        <action android:name="android.telephony.ims.ImsService" />
    </intent-filter>
</service>

The service definition in AndroidManifest.xml defines the following attributes, which are necessary for correct operation:

  • directBootAware="true": Allows the service to be discovered and run by telephony before the user unlocks the device. The service can't access device encrypted storage before the user unlocks the device. For more information, see Support Direct Boot mode and File-Based Encryption.
  • persistent="true": Allows this service to be run persistently and not be killed by the system to reclaim memory. This attribute ONLY works if the app is built as a system app.
  • permission="android.permission.BIND_IMS_SERVICE": Ensures that only a process that has had the BIND_IMS_SERVICE permission granted to it can bind to the app. This prevents a rogue app from binding to the service, since only system apps can be granted the permission by the framework.

The service must also specify the intent-filter element with the action android.telephony.ims.ImsService. This allows the framework to find the ImsService.

IMS feature specification

After the ImsService has been defined as an Android service in AndroidManifest.xml, the ImsService must define which IMS features it supports. Android currently supports the MmTel and RCS features, however only MmTel is integrated into the framework. Although there are no RCS APIs integrated into the framework, there are still advantages to declaring it as a feature of the ImsService.

Below are the valid features defined in android.telephony.ims.ImsFeature that an ImsService can provide and an explanation and example as to why an IMS app would want to implement one or all of these features. After each feature is defined, this page outlines how the ImsService declares the set of features that it defines for each SIM slot.

FEATURE_MMTEL

The ImsService implements the IMS MMTEL feature, which contains support for all IMS media (IR.92 and IR.94 specifications) except emergency attach to the IMS PDN for emergency calling. Any implementation of ImsService that wishes to support the MMTEL features should extend the android.telephony.ims.MmTelFeature base class and return a custom MmTelFeature implementation in ImsService#createMmTelFeature.

FEATURE_EMERGENCY_MMTEL

Declaring this feature only signals to the platform that emergency attach to the IMS PDN for emergency services is possible. If this feature is not declared for your ImsService, the platform will always default to Circuit Switch Fallback for emergency services. The FEATURE_MMTEL feature must be defined for this feature to be defined.

FEATURE_RCS

The ImsService API does not implement any IMS RCS features, but the android.telephony.ims.RcsFeature base class can still be useful. The framework automatically binds to the ImsService and calls ImsService#createRcsFeature when it detects that the package should provide RCS. If the SIM card associated with the RCS service is removed, the framework automatically calls RcsFeature#onFeatureRemoved and then cleans up the ImsService associated with the RCS feature. This functionality can remove some of the custom detection or binding logic that an RCS feature would otherwise have to provide.

Registration of supported features

The telephony framework first binds to the ImsService to query the features that it supports using the ImsService#querySupportedImsFeatures API. After the framework calculates which features the ImsService will support, it will call ImsService#create[...]Feature for each feature that the ImsService will be responsible for. If the features that the IMS app supports changes, you can use ImsService#onUpdateSupportedImsFeatures to signal the framework to recalculate supported features. See the following diagram for more information on the initialization and binding of the ImsService.

ImsService initializing and binding

Figure 2: ImsService initialization and binding

Framework detection and verification of an ImsService implementation

Once the ImsService has been defined correctly in AndroidManifest.xml, the platform must be configured to (securely) bind to the ImsService when appropriate. There are two types of ImsServices that the framework binds to:

  1. Carrier "override" ImsService: These ImsServices are preloaded onto the device but are attached to one or more cellular carriers and will only be bound when a matching SIM card is inserted. This is configured using the
  2. Device "default" ImsService: This is the default ImsService that is loaded onto the device by an OEM and should be designed to provide IMS services in all situations when a carrier ImsService is not available and is useful in situations where the device has no SIM card inserted or the SIM card inserted does not have a carrier ImsService installed with it. This is defined in the device overlay using the following configurations:

Android does not support apps with third-party downloadable ImsService implementations, so any ImsService implementations defined here are required to be System apps and must reside in the /system/priv-app/ or /product/priv-app/ folder to grant the appropriate permissions (namely phone, microphone, location, camera, and contacts permissions). By verifying whether the package name of the IMS implementation matches the CarrierConfig or device overlay values defined above, only trusted, pre-installed apps are bound.

Customization

Apps implementing an ImsService are only bound on devices where they are configured as the carrier "override" ImsService or device "default" ImsService configurations for MMTEL or RCS functionality. The ImsService also allows the IMS features that it supports (MMTEL and RCS) to be enabled or disabled dynamically using updates using the ImsService#onUpdateSupportedImsFeatures method. This triggers the framework to recalculate which ImsServices are bound and which features they support. If the IMS app updates the framework with no features supported, the ImsService will be unbound until the phone is rebooted or a new SIM card is inserted that matches the IMS app.

Binding priority for multiple ImsService

The framework cannot support binding to all of the possible ImsServices that are preloaded onto the device and will bind to up to two ImsServices per SIM slot (one ImsService for each feature) in the following order on a per-feature basis:

  1. The ImsService package name defined by the CarrierConfig value config_ims_[mmtel/rcs]_package_override_string when there is a SIM card inserted.
  2. The ImsService package name defined in the device overlay value for config_ims_[mmtel/rcs]_packageincluding the case where there is no SIM card inserted. This ImsService MUST support the Emergency MmTel feature.

You must either have the package name of your ImsService defined in the CarrierConfig for each of the carriers that will use that package or in the device overlay if your ImsService will be the default, as defined above.

Let's break this down for each feature. For a device (single or multi-SIM) with a single SIM card loaded, two IMS features are possible: MMTel and RCS. The framework will try to bind in the order defined above for each feature and if the feature is not available for the ImsService defined in the Carrier Configuration override, the framework will fallback to your default ImsService. So, for example, the table below describes which IMS feature the framework will use given three IMS apps implementing ImsServices installed on a system with the following features:

  • Carrier A ImsService supports RCS
  • Carrier B ImsService supports RCS and MMTel
  • OEM ImsService supports RCS and MMTel
SIM Card Inserted RCS Feature MMTel Feature
Carrier A Carrier A OEM
Carrier B Carrier B Carrier B
No SIM OEM OEM

Validation

Tools for verifying the IMS implementation itself are not included since the IMS specifications are extremely large and use special verification equipment. The tests can only verify that the telephony framework properly responds to the ImsService API.

Develop an IMS app

When developing an IMS app that interfaces with the Android telephony stack, we recommend specifying that the app can listen to or modify the state of the ImsService instance that is attached for a specific carrier subscription.

To listen to or modify the state of ImsService for MMTEL and RCS features, use the ImsManager class to get an instance of the ImsMmTelManager, ImsRcsManager, or IMS-specific ProvisioningManager class. The app can then listen to IMS-specific service and provisioning states such as:

  • MMTEL or RCS features that are enabled and available
  • Updates when the IMS registration state changes
  • Provisioning status of IMS features
  • IMS features the user has enabled

Use ImsStateCallback

Although ImsService is a persistently bound service, the service that's bound might change when a new SIM card or embedded subscription becomes active or when a carrier configuration changes. Because ImsService isn't part of the telephony process, an app might experience unanticipated exceptions when trying to access IMS APIs if ImsService invisibly crashes or is unbound because of a subscription or configuration change.

On devices running Android 13 or higher, to monitor whether the ImsService instance for an associated subscription is available or unavailable, an app can use the ImsStateCallback class. When getting an instance of ImsMmTelManager or ImsRcsManager, we recommend that the app first register for an IMS state callback using ImsMmTelManager#registerImsStateCallback or ImsRcsManager#registerImsStateCallback. To continue receiving callback updates for specific subscriptions when ImsService becomes available again, the app must unregister or discard existing callbacks registered through ImsMmTelManager, ImsRcsManager, or ProvisioningManager; and register new callbacks.

If there's a subscription that doesn't support IMS, the framework calls ImsStateCallback#onUnavailable with the reason REASON_NO_IMS_SERVICE_CONFIGURED. This means that ImsService and the IMS-related APIs aren't available for the subscription.

In the unlikely event that the telephony process crashes, the app receives ImsStateCallback#onError and no longer receives updates on the registered ImsStateCallback instance. To recover from this condition, reregister the ImsStateCallback instance for the associated subscription by calling ImsMmTelManager#registerImsStateCallback or ImsRcsManager#registerImsStateCallback.