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.
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 theandroid.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 bytelephony
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 theBIND_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.
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:
- 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
config_ims_mmtel_package_override_string
CarrierConfig key for ImsServices implementing MMTEL features.config_ims_rcs_package_override_string
for ImsServices implementing RCS features.
- 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:
config_ims_mmtel_package
: Implements MMTEL featuresconfig_ims_rcs_package
: Implements RCS features
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:
- The ImsService package name defined by the CarrierConfig value
config_ims_[mmtel/rcs]_package_override_string
when there is a SIM card inserted. - The ImsService package name defined in the device overlay value for
config_ims_[mmtel/rcs]_package
including 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
.