diff --git a/api/current.txt b/api/current.txt index 22b8c456f6552..90c0eab439c42 100644 --- a/api/current.txt +++ b/api/current.txt @@ -46887,6 +46887,7 @@ package android.telephony { } public static final class CarrierConfigManager.Ims { + field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool"; field public static final String KEY_PREFIX = "ims."; field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int"; } diff --git a/api/system-current.txt b/api/system-current.txt index 6475d81067cde..11b2828e62472 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -11904,6 +11904,10 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public class ImsManager { + method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int); + } + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer) throws android.telephony.ims.ImsException; @@ -11939,10 +11943,13 @@ package android.telephony.ims { method public void disableIms(int); method public void enableIms(int); method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public long getImsServiceCapabilities(); method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); + field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L } public final class ImsSsData implements android.os.Parcelable { @@ -12188,6 +12195,10 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } + public class SipDelegateManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException; + } + } package android.telephony.ims.feature { @@ -12437,6 +12448,10 @@ package android.telephony.ims.stub { method public int updateColr(int); } + public class SipTransportImplBase { + ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); + } + } package android.telephony.mbms { diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index da3d0f7ff0599..e7306367daf51 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -45055,6 +45055,7 @@ package android.telephony { } public static final class CarrierConfigManager.Ims { + field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool"; field public static final String KEY_PREFIX = "ims."; field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int"; } diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 7d5d0a65d43ee..515d368db9e27 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -10786,6 +10786,10 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public class ImsManager { + method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int); + } + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer) throws android.telephony.ims.ImsException; @@ -10821,10 +10825,13 @@ package android.telephony.ims { method public void disableIms(int); method public void enableIms(int); method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public long getImsServiceCapabilities(); method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); + field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L } public final class ImsSsData implements android.os.Parcelable { @@ -11070,6 +11077,10 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } + public class SipDelegateManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException; + } + } package android.telephony.ims.feature { @@ -11319,6 +11330,10 @@ package android.telephony.ims.stub { method public int updateColr(int); } + public class SipTransportImplBase { + ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); + } + } package android.telephony.mbms { diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt index 5ad377273b90f..f4b7b509be56b 100644 --- a/telephony/api/system-current.txt +++ b/telephony/api/system-current.txt @@ -1361,6 +1361,10 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public class ImsManager { + method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int); + } + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer) throws android.telephony.ims.ImsException; @@ -1396,10 +1400,13 @@ package android.telephony.ims { method public void disableIms(int); method public void enableIms(int); method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public long getImsServiceCapabilities(); method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); + field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L } public final class ImsSsData implements android.os.Parcelable { @@ -1645,6 +1652,10 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } + public class SipDelegateManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException; + } + } package android.telephony.ims.feature { @@ -1894,6 +1905,10 @@ package android.telephony.ims.stub { method public int updateColr(int); } + public class SipTransportImplBase { + ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); + } + } package android.telephony.mbms { diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index a4f48af93a8d8..88a700e49a98a 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3785,11 +3785,26 @@ public class CarrierConfigManager { public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = KEY_PREFIX + "wifi_off_deferring_time_millis_int"; + /** + * A boolean flag specifying whether or not this carrier requires one IMS registration for + * all IMS services (MMTEL and RCS). + *

+ * If set to {@code true}, the IMS Service must use one IMS registration for all IMS + * services. If set to {@code false}, IMS services may use separate IMS registrations for + * MMTEL and RCS. + *

+ * The default value for this configuration is {@code false}. + * @see android.telephony.ims.SipDelegateManager + */ + public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = + KEY_PREFIX + "ims_single_registration_required_bool"; + private Ims() {} private static PersistableBundle getDefaults() { PersistableBundle defaults = new PersistableBundle(); defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000); + defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false); return defaults; } } diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java index 3984bd769edda..28feab27a794b 100644 --- a/telephony/java/android/telephony/ImsManager.java +++ b/telephony/java/android/telephony/ImsManager.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.telephony.SubscriptionManager; @@ -125,4 +126,24 @@ public class ImsManager { return new ImsMmTelManager(subscriptionId); } + + /** + * Create an instance of SipDelegateManager for the subscription id specified. + *

+ * Used for RCS single registration cases, where an IMS application needs to forward SIP + * traffic through the device's IMS service. + * @param subscriptionId The ID of the subscription that this SipDelegateManager will use. + * @throws IllegalArgumentException if the subscription is invalid. + * @return a SipDelegateManager instance for the specified subscription ID. + * @hide + */ + @SystemApi + @NonNull + public SipDelegateManager getSipDelegateManager(int subscriptionId) { + if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId); + } + + return new SipDelegateManager(mContext, subscriptionId); + } } diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 75aeb0419cff7..9ab5aeb9c34c8 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -17,6 +17,8 @@ package android.telephony.ims; import android.annotation.LongDef; +import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -29,12 +31,14 @@ import android.telephony.ims.aidl.IImsRcsFeature; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsServiceController; import android.telephony.ims.aidl.IImsServiceControllerListener; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsConfigImplBase; import android.telephony.ims.stub.ImsFeatureConfiguration; import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.telephony.ims.stub.SipTransportImplBase; import android.util.Log; import android.util.SparseArray; @@ -103,18 +107,46 @@ public class ImsService extends Service { /** * This ImsService supports the capability to place emergency calls over MMTEL. + *

+ * Note: This should never be set by {@link #getImsServiceCapabilities()}, as whether it is + * there or not depends on whether or not {@link ImsFeature#FEATURE_EMERGENCY_MMTEL} is defined + * for this ImsService. If it is set, it will be removed during sanitization before the final + * capabilities bitfield is sent back to the framework. * @hide This is encoded into the {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, but we will be * adding other capabilities in a central location, so track this capability here as well. */ public static final long CAPABILITY_EMERGENCY_OVER_MMTEL = 1 << 0; + /** + * This ImsService supports the capability to create SIP delegates for other IMS applications + * to use to proxy SIP messaging traffic through it. + *

+ * In order for the framework to report SipDelegate creation as being available for this + * ImsService implementation, this ImsService must report this capability flag in + * {@link #getImsServiceCapabilities()}, {@link #getSipTransport(int)} must not return null, and + * this ImsService MUST report the ability to create both {@link ImsFeature#FEATURE_MMTEL} and + * {@link ImsFeature#FEATURE_RCS} features. + */ + public static final long CAPABILITY_SIP_DELEGATE_CREATION = 1 << 1; + + /** + * Used for internal correctness checks of capabilities set by the ImsService implementation and + * tracks the index of the largest defined flag in the capabilities long. + * @hide + */ + public static final long CAPABILITY_MAX_INDEX = + Long.numberOfTrailingZeros(CAPABILITY_SIP_DELEGATE_CREATION); + /** * @hide */ @LongDef(flag = true, prefix = "CAPABILITY_", value = { - CAPABILITY_EMERGENCY_OVER_MMTEL + // CAPABILITY_EMERGENCY_OVER_MMTEL is not included here because it is managed by + // whether or not ImsFeature.FEATURE_EMERGENCY_MMTEL feature is set and should + // not be set by users of ImsService. + CAPABILITY_SIP_DELEGATE_CREATION }) @Retention(RetentionPolicy.SOURCE) public @interface ImsServiceCapability {} @@ -125,6 +157,7 @@ public class ImsService extends Service { */ private static final Map CAPABILITIES_LOG_MAP = new HashMap() {{ put(CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL"); + put(CAPABILITY_SIP_DELEGATE_CREATION, "SIP_DELEGATE_CREATION"); }}; /** @@ -198,6 +231,17 @@ public class ImsService extends Service { return ImsService.this.querySupportedImsFeatures(); } + @Override + public long getImsServiceCapabilities() { + long caps = ImsService.this.getImsServiceCapabilities(); + long sanitizedCaps = sanitizeCapabilities(caps); + if (caps != sanitizedCaps) { + Log.w(LOG_TAG, "removing invalid bits from field: 0x" + + Long.toHexString(caps ^ sanitizedCaps)); + } + return sanitizedCaps; + } + @Override public void notifyImsServiceReadyForFeatureCreation() { ImsService.this.readyForFeatureCreation(); @@ -215,6 +259,12 @@ public class ImsService extends Service { return r != null ? r.getBinder() : null; } + @Override + public ISipTransport getSipTransport(int slotId) { + SipTransportImplBase s = ImsService.this.getSipTransport(slotId); + return s != null ? s.getBinder() : null; + } + @Override public void enableIms(int slotId) { ImsService.this.enableIms(slotId); @@ -368,6 +418,20 @@ public class ImsService extends Service { mListener.onUpdateSupportedImsFeatures(c); } + /** + * The optional capabilities that this ImsService supports. + *

+ * This should be a static configuration and should not change at runtime. + * @return The optional static capabilities of this ImsService implementation. + */ + // ImsService follows a different convention, since it is a stub class. The on* methods are + // final and call back into the framework with a state update. + @SuppressLint("OnNameExpected") + public @ImsServiceCapability long getImsServiceCapabilities() { + // Stub implementation to be implemented by ImsService. + return 0L; + } + /** * The ImsService has been bound and is ready for ImsFeature creation based on the Features that * the ImsService has registered for with the framework, either in the manifest or via @@ -441,7 +505,40 @@ public class ImsService extends Service { } /** - * @return A string representation of the ImsService capabilties for logging. + * Return the {@link SipTransportImplBase} implementation associated with the provided slot. + *

+ * This is an optional interface used for devices that must support IMS single registration and + * proxy SIP traffic to remote IMS applications. If this is not supported for this IMS service, + * this method should return {@code null}. If this feature is supported, then this method must + * never be {@code null} and the optional ImsService capability flag + * {@link #CAPABILITY_SIP_DELEGATE_CREATION} must be set in + * {@link #getImsServiceCapabilities()}. Otherwise the framework will assume this feature is not + * supported for this ImsService. + * @param slotId The slot that is associated with the SipTransport implementation. + * @return the SipTransport implementation for the specified slot. + */ + // ImsService follows a different convention, since it is a stub class. The on* methods are + // final and call back into the framework with a state update. + @SuppressLint("OnNameExpected") + public @Nullable SipTransportImplBase getSipTransport(int slotId) { + // Stub implementation for ImsServices that do not support SipTransport. + return null; + } + + private static long sanitizeCapabilities(@ImsServiceCapability long caps) { + long filter = 0xFFFFFFFFFFFFFFFFL; + // pad the "allowed" set with zeros + filter <<= CAPABILITY_MAX_INDEX + 1; + // remove values above the allowed set. + caps &= ~filter; + // CAPABILITY_EMERGENCY_OVER_MMTEL should also not be set here, will be set by telephony + // internally. + caps &= ~CAPABILITY_EMERGENCY_OVER_MMTEL; + return caps; + } + + /** + * @return A string representation of the ImsService capabilities for logging. * @hide */ public static String getCapabilitiesString(@ImsServiceCapability long caps) { diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java new file mode 100644 index 0000000000000..82c8a9cd58f4b --- /dev/null +++ b/telephony/java/android/telephony/ims/SipDelegateManager.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.telephony.CarrierConfigManager; +import android.telephony.TelephonyFrameworkInitializer; +import android.telephony.ims.aidl.IImsRcsController; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Manages the creation and destruction of SipDelegates, which allow an IMS application to forward + * SIP messages for the purposes of providing a single IMS registration to the carrier's IMS network + * from multiple sources. + * @hide + */ +@SystemApi +public class SipDelegateManager { + + private final Context mContext; + private final int mSubId; + + /** + * Only visible for testing. To instantiate an instance of this class, please use + * {@link ImsManager#getSipDelegateManager(int)}. + * @hide + */ + @VisibleForTesting + public SipDelegateManager(Context context, int subId) { + mContext = context; + mSubId = subId; + } + + /** + * Determines if creating SIP delegates are supported for the subscription specified. + *

+ * If SIP delegates are not supported on this device or the carrier associated with this + * subscription, creating a SIP delegate will always fail, as this feature is not supported. + * @return true if this device supports creating a SIP delegate and the carrier associated with + * this subscription supports single registration, false if creating SIP delegates is not + * supported. + * @throws ImsException If the remote ImsService is not available for any reason or the + * subscription associated with this instance is no longer active. See + * {@link ImsException#getCode()} for more information. + * + * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isSupported() throws ImsException { + try { + IImsRcsController controller = getIImsRcsController(); + if (controller == null) { + throw new ImsException("Telephony server is down", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + return controller.isSipDelegateSupported(mSubId); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); + } catch (RemoteException e) { + throw new ImsException(e.getMessage(), + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + private IImsRcsController getIImsRcsController() { + IBinder binder = TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyImsServiceRegisterer() + .get(); + return IImsRcsController.Stub.asInterface(binder); + } +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index e01ea9179452b..6d25a09e079f4 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -53,6 +53,9 @@ interface IImsRcsController { void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c); void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c); + // SipDelegateManager + boolean isSipDelegateSupported(int subId); + // Internal commands that should not be made public void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback); void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback); diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl index c956cbcc816cc..c6966b3cf53e8 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl @@ -21,6 +21,7 @@ import android.telephony.ims.aidl.IImsRcsFeature; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsServiceControllerListener; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.stub.ImsFeatureConfiguration; import com.android.ims.internal.IImsFeatureStatusCallback; @@ -34,6 +35,7 @@ interface IImsServiceController { IImsMmTelFeature createMmTelFeature(int slotId); IImsRcsFeature createRcsFeature(int slotId); ImsFeatureConfiguration querySupportedImsFeatures(); + long getImsServiceCapabilities(); void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); // Synchronous call to ensure the ImsService is ready before continuing with feature creation. @@ -41,6 +43,7 @@ interface IImsServiceController { void removeImsFeature(int slotId, int featureType); IImsConfig getConfig(int slotId); IImsRegistration getRegistration(int slotId); + ISipTransport getSipTransport(int slotId); oneway void enableIms(int slotId); oneway void disableIms(int slotId); } diff --git a/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl new file mode 100644 index 0000000000000..fe233430ffad1 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +/** + * Interface for commands to the SIP Transport implementation. + * {@hide} + */ +interface ISipTransport { +} diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java new file mode 100644 index 0000000000000..b2b2914b3739a --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.stub; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.telephony.ims.aidl.ISipTransport; + +import java.util.concurrent.Executor; + +/** + * Manages the creation and destruction of SipDelegates in order to proxy SIP traffic to other + * IMS applications in order to support IMS single registration. + * @hide + */ +@SystemApi +public class SipTransportImplBase { + + private final Executor mBinderExecutor; + private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() { + + }; + + /** + * Create an implementation of SipTransportImplBase. + * + * @param executor The executor that remote calls from the framework should be called on. + */ + public SipTransportImplBase(@NonNull Executor executor) { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } + + mBinderExecutor = executor; + } + + /** + * @return The IInterface used by the framework. + * @hide + */ + public ISipTransport getBinder() { + return mSipTransportImpl; + } +} diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.java b/telephony/java/com/android/ims/ImsFeatureContainer.java index b259679ea1bf8..80c1d43480ccc 100644 --- a/telephony/java/com/android/ims/ImsFeatureContainer.java +++ b/telephony/java/com/android/ims/ImsFeatureContainer.java @@ -17,12 +17,14 @@ package com.android.ims; import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.telephony.ims.ImsService; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsRegistration; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.ImsFeature; import java.util.Objects; @@ -48,6 +50,11 @@ public final class ImsFeatureContainer implements Parcelable { */ public final IImsRegistration imsRegistration; + /** + * An optional interface containing the SIP transport implementation from the ImsService. + */ + public final ISipTransport sipTransport; + /** * State of the feature that is being tracked. */ @@ -66,10 +73,11 @@ public final class ImsFeatureContainer implements Parcelable { * @param initialCaps The initial capabilities that the ImsService supports. */ public ImsFeatureContainer(@NonNull IBinder iFace, @NonNull IImsConfig iConfig, - @NonNull IImsRegistration iReg, long initialCaps) { + @NonNull IImsRegistration iReg, @Nullable ISipTransport transport, long initialCaps) { imsFeature = iFace; imsConfig = iConfig; imsRegistration = iReg; + sipTransport = transport; mCapabilities = initialCaps; } @@ -80,6 +88,7 @@ public final class ImsFeatureContainer implements Parcelable { imsFeature = in.readStrongBinder(); imsConfig = IImsConfig.Stub.asInterface(in.readStrongBinder()); imsRegistration = IImsRegistration.Stub.asInterface(in.readStrongBinder()); + sipTransport = ISipTransport.Stub.asInterface(in.readStrongBinder()); mState = in.readInt(); mCapabilities = in.readLong(); } @@ -123,13 +132,15 @@ public final class ImsFeatureContainer implements Parcelable { return imsFeature.equals(that.imsFeature) && imsConfig.equals(that.imsConfig) && imsRegistration.equals(that.imsRegistration) && + sipTransport.equals(that.sipTransport) && mState == that.getState() && mCapabilities == that.getCapabilities(); } @Override public int hashCode() { - return Objects.hash(imsFeature, imsConfig, imsRegistration, mState, mCapabilities); + return Objects.hash(imsFeature, imsConfig, imsRegistration, sipTransport, mState, + mCapabilities); } @Override @@ -138,6 +149,7 @@ public final class ImsFeatureContainer implements Parcelable { "imsFeature=" + imsFeature + ", imsConfig=" + imsConfig + ", imsRegistration=" + imsRegistration + + ", sipTransport=" + sipTransport + ", state=" + ImsFeature.STATE_LOG_MAP.get(mState) + ", capabilities = " + ImsService.getCapabilitiesString(mCapabilities) + '}'; @@ -153,6 +165,7 @@ public final class ImsFeatureContainer implements Parcelable { dest.writeStrongBinder(imsFeature); dest.writeStrongInterface(imsConfig); dest.writeStrongInterface(imsRegistration); + dest.writeStrongInterface(sipTransport); dest.writeInt(mState); dest.writeLong(mCapabilities); }