diff options
Diffstat (limited to 'telephony/java')
38 files changed, 2050 insertions, 1840 deletions
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 4138e2950d93..96ed20b841bd 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -47,12 +47,13 @@ import android.service.carrier.CarrierIdentifier; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.VisualVoicemailService.VisualVoicemailTask; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.aidl.IImsMmTelFeature; +import android.telephony.ims.aidl.IImsRcsFeature; +import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.feature.ImsFeature; import android.util.Log; -import com.android.ims.internal.IImsMMTelFeature; -import com.android.ims.internal.IImsRcsFeature; -import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.ITelecomService; @@ -4889,57 +4890,60 @@ public class TelephonyManager { } } - /** @hide */ - @IntDef({ImsFeature.EMERGENCY_MMTEL, ImsFeature.MMTEL, ImsFeature.RCS}) - @Retention(RetentionPolicy.SOURCE) - public @interface Feature {} + /** + * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability + * status updates, if not already enabled. + * @hide + */ + public void enableIms(int slotId) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + telephony.enableIms(slotId); + } + } catch (RemoteException e) { + Rlog.e(TAG, "enableIms, RemoteException: " + + e.getMessage()); + } + } /** - * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel - * feature or {@link null} if the service is not available. If an MMTelFeature is available, the - * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates. - * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for. - * @param callback Listener that will send updates to ImsManager when there are updates to - * ImsServiceController. - * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if - * it is unavailable. + * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature + * status updates to disabled. * @hide */ - public @Nullable IImsMMTelFeature getImsMMTelFeatureAndListen(int slotIndex, - IImsServiceFeatureCallback callback) { + public void disableIms(int slotId) { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.getMMTelFeatureAndListen(slotIndex, callback); + telephony.disableIms(slotId); } } catch (RemoteException e) { - Rlog.e(TAG, "getImsMMTelFeatureAndListen, RemoteException: " + Rlog.e(TAG, "disableIms, RemoteException: " + e.getMessage()); } - return null; } /** - * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel - * feature for emergency calling or {@link null} if the service is not available. If an - * MMTelFeature is available, the {@link IImsServiceFeatureCallback} callback is registered as a - * listener for feature updates. - * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for. + * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id and MMTel + * feature or {@link null} if the service is not available. If an MMTelFeature is available, the + * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates. + * @param slotIndex The SIM slot that we are requesting the {@link IImsMmTelFeature} for. * @param callback Listener that will send updates to ImsManager when there are updates to * ImsServiceController. - * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if + * @return {@link IImsMmTelFeature} interface for the feature specified or {@code null} if * it is unavailable. * @hide */ - public @Nullable IImsMMTelFeature getImsEmergencyMMTelFeatureAndListen(int slotIndex, + public @Nullable IImsMmTelFeature getImsMmTelFeatureAndListen(int slotIndex, IImsServiceFeatureCallback callback) { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.getEmergencyMMTelFeatureAndListen(slotIndex, callback); + return telephony.getMmTelFeatureAndListen(slotIndex, callback); } } catch (RemoteException e) { - Rlog.e(TAG, "getImsEmergencyMMTelFeatureAndListen, RemoteException: " + Rlog.e(TAG, "getImsMmTelFeatureAndListen, RemoteException: " + e.getMessage()); } return null; @@ -4991,6 +4995,25 @@ public class TelephonyManager { } /** + * @return the {@IImsConfig} interface that corresponds with the slot index and feature. + * @param slotIndex The SIM slot corresponding to the ImsService ImsConfig is active for. + * @param feature An integer indicating the feature that we wish to get the ImsConfig for. + * Corresponds to features defined in ImsFeature. + * @hide + */ + public @Nullable IImsConfig getImsConfig(int slotIndex, int feature) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getImsConfig(slotIndex, feature); + } + } catch (RemoteException e) { + Rlog.e(TAG, "getImsRegistration, RemoteException: " + e.getMessage()); + } + return null; + } + + /** * Set IMS registration state * * @param Registration state diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index aaa0f08594d1..2f32bae88f03 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -16,25 +16,28 @@ package android.telephony.ims; -import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.telephony.CarrierConfigManager; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.aidl.IImsMmTelFeature; +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.feature.ImsFeature; -import android.telephony.ims.feature.MMTelFeature; +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.util.Log; import android.util.SparseArray; import com.android.ims.internal.IImsFeatureStatusCallback; -import com.android.ims.internal.IImsMMTelFeature; -import com.android.ims.internal.IImsRcsFeature; -import com.android.ims.internal.IImsRegistration; -import com.android.ims.internal.IImsServiceController; import com.android.internal.annotations.VisibleForTesting; import static android.Manifest.permission.MODIFY_PHONE_STATE; @@ -62,14 +65,11 @@ import static android.Manifest.permission.MODIFY_PHONE_STATE; * 1) Defined as the default ImsService for the device in the device overlay using * "config_ims_package". * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using - * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}. + * {@link CarrierConfigManager#KEY_CTONFIG_IMS_PACKAGE_OVERRIDE_STRING}. * * The features that are currently supported in an ImsService are: * - RCS_FEATURE: This ImsService implements the RcsFeature class. - * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class. - * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be - * available to place emergency calls at all times. This MUST be implemented by the default - * ImsService provided in the device overlay. + * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class. * @hide */ @SystemApi @@ -89,20 +89,36 @@ public class ImsService extends Service { // call ImsFeature#onFeatureRemoved. private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>(); + private IImsServiceControllerListener mListener; + + /** + * Listener that notifies the framework of ImsService changes. * @hide */ - protected final IBinder mImsServiceController = new IImsServiceController.Stub() { + public static class Listener extends IImsServiceControllerListener.Stub { + /** + * The IMS features that this ImsService supports has changed. + * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s + * that this ImsService supports. This may trigger the addition/removal of feature + * in this service. + */ + public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) { + } + } + /** + * @hide + */ + protected final IBinder mImsServiceController = new IImsServiceController.Stub() { @Override - public IImsMMTelFeature createEmergencyMMTelFeature(int slotId, - IImsFeatureStatusCallback c) { - return createEmergencyMMTelFeatureInternal(slotId, c); + public void setListener(IImsServiceControllerListener l) { + mListener = l; } @Override - public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) { - return createMMTelFeatureInternal(slotId, c); + public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) { + return createMmTelFeatureInternal(slotId, c); } @Override @@ -117,10 +133,42 @@ public class ImsService extends Service { } @Override + public ImsFeatureConfiguration querySupportedImsFeatures() { + return ImsService.this.querySupportedImsFeatures(); + } + + @Override + public void notifyImsServiceReadyForFeatureCreation() { + ImsService.this.readyForFeatureCreation(); + } + + @Override + public void notifyImsFeatureReady(int slotId, int featureType) + throws RemoteException { + ImsService.this.notifyImsFeatureReady(slotId, featureType); + } + + @Override + public IImsConfig getConfig(int slotId) throws RemoteException { + ImsConfigImplBase c = ImsService.this.getConfig(slotId); + return c != null ? c.getIImsConfig() : null; + } + + @Override public IImsRegistration getRegistration(int slotId) throws RemoteException { ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId); return r != null ? r.getBinder() : null; } + + @Override + public void enableIms(int slotId) { + ImsService.this.enableIms(slotId); + } + + @Override + public void disableIms(int slotId) { + ImsService.this.disableIms(slotId); + } }; /** @@ -143,47 +191,35 @@ public class ImsService extends Service { return mFeaturesBySlot.get(slotId); } - private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId, + private IImsMmTelFeature createMmTelFeatureInternal(int slotId, IImsFeatureStatusCallback c) { - MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId); + MmTelFeature f = createMmTelFeature(slotId); if (f != null) { - setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c); - return f.getBinder(); - } else { - return null; - } - } - - private IImsMMTelFeature createMMTelFeatureInternal(int slotId, - IImsFeatureStatusCallback c) { - MMTelFeature f = onCreateMMTelImsFeature(slotId); - if (f != null) { - setupFeature(f, slotId, ImsFeature.MMTEL, c); + setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c); return f.getBinder(); } else { + Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned."); return null; } } private IImsRcsFeature createRcsFeatureInternal(int slotId, IImsFeatureStatusCallback c) { - RcsFeature f = onCreateRcsFeature(slotId); + RcsFeature f = createRcsFeature(slotId); if (f != null) { - setupFeature(f, slotId, ImsFeature.RCS, c); + setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c); return f.getBinder(); } else { + Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned."); return null; } } private void setupFeature(ImsFeature f, int slotId, int featureType, IImsFeatureStatusCallback c) { - f.setContext(this); - f.setSlotId(slotId); f.addImsFeatureStatusCallback(c); + f.initialize(this, slotId); addImsFeature(slotId, featureType, f); - // TODO: Remove once new onFeatureReady AIDL is merged in. - f.onFeatureReady(); } private void addImsFeature(int slotId, int featureType, ImsFeature f) { @@ -221,33 +257,116 @@ public class ImsService extends Service { } } + private void notifyImsFeatureReady(int slotId, int featureType) { + synchronized (mFeaturesBySlot) { + // get ImsFeature associated with the slot/feature + SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); + if (features == null) { + Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " + + "slot " + slotId); + return; + } + ImsFeature f = features.get(featureType); + if (f == null) { + Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type " + + featureType + " exists on slot " + slotId); + return; + } + f.onFeatureReady(); + } + } + /** - * @return An implementation of MMTelFeature that will be used by the system for MMTel - * functionality. Must be able to handle emergency calls at any time as well. + * When called, provide the {@link ImsFeatureConfiguration} that this ImsService currently + * supports. This will trigger the framework to set up the {@link ImsFeature}s that correspond + * to the {@link ImsFeature.FeatureType}s configured here. + * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports, + * defined in {@link ImsFeature.FeatureType}. * @hide */ - public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) { - return null; + public ImsFeatureConfiguration querySupportedImsFeatures() { + // Return empty for base implementation + return new ImsFeatureConfiguration(); + } + + /** + * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated + * features, defined in {@link ImsFeature.FeatureType} that this ImsService supports. This may + * trigger the framework to add/remove new ImsFeatures, depending on the configuration. + * @hide + */ + public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) + throws RemoteException { + if (mListener == null) { + throw new IllegalStateException("Framework is not ready"); + } + mListener.onUpdateSupportedImsFeatures(c); + } + + /** + * 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 + * The ImsService should use this signal instead of onCreate/onBind or similar to perform + * feature initialization because the framework may bind to this service multiple times to + * query the ImsService's {@link ImsFeatureConfiguration} via + * {@link #querySupportedImsFeatures()}before creating features. + * @hide + */ + public void readyForFeatureCreation() { + } + + /** + * The framework has enabled IMS for the slot specified, the ImsService should register for IMS + * and perform all appropriate initialization to bring up all ImsFeatures. + * @hide + */ + public void enableIms(int slotId) { } /** - * @return An implementation of MMTelFeature that will be used by the system for MMTel - * functionality. + * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS + * and set capability status to false for all ImsFeatures. * @hide */ - public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) { + public void disableIms(int slotId) { + } + + /** + * When called, the framework is requesting that a new MmTelFeature is created for the specified + * slot. + * + * @param slotId The slot ID that the MMTel Feature is being created for. + * @return The newly created MmTelFeature associated with the slot or null if the feature is not + * supported. + * @hide + */ + public MmTelFeature createMmTelFeature(int slotId) { return null; } /** - * @return An implementation of RcsFeature that will be used by the system for RCS. + * When called, the framework is requesting that a new RcsFeature is created for the specified + * slot + * + * @param slotId The slot ID that the RCS Feature is being created for. + * @return The newly created RcsFeature associated with the slot or null if the feature is not + * supported. * @hide */ - public @Nullable RcsFeature onCreateRcsFeature(int slotId) { + public RcsFeature createRcsFeature(int slotId) { return null; } /** + * @param slotId The slot that the IMS configuration is associated with. + * @return ImsConfig implementation that is associated with the specified slot. + * @hide + */ + public ImsConfigImplBase getConfig(int slotId) { + return new ImsConfigImplBase(); + } + + /** * @param slotId The slot that is associated with the IMS Registration. * @return the ImsRegistration implementation associated with the slot. * @hide @@ -255,4 +374,4 @@ public class ImsService extends Service { public ImsRegistrationImplBase getRegistration(int slotId) { return new ImsRegistrationImplBase(); } -} +}
\ No newline at end of file diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl index fd2eb24610ec..c755703c042a 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; /** * See ImsFeature#CapabilityCallback for more information. diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl index 3d424a33012d..4433c1c03c1f 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl @@ -15,9 +15,9 @@ */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; -import android.telephony.ims.internal.aidl.IImsConfigCallback; +import android.telephony.ims.aidl.IImsConfigCallback; import com.android.ims.ImsConfigListener; diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl index 52efd2322c17..2b3f1ca7196a 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl @@ -15,7 +15,7 @@ */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; /** * Provides callback interface for ImsConfig when a value has changed. diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl index 18afc6a23a40..f9b15c0b1610 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl @@ -14,12 +14,13 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; import android.os.Message; -import android.telephony.ims.internal.aidl.IImsMmTelListener; -import android.telephony.ims.internal.aidl.IImsCapabilityCallback; -import android.telephony.ims.internal.feature.CapabilityChangeRequest; +import android.telephony.ims.aidl.IImsMmTelListener; +import android.telephony.ims.aidl.IImsSmsListener; +import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.feature.CapabilityChangeRequest; import com.android.ims.ImsCallProfile; import com.android.ims.internal.IImsCallSession; @@ -37,6 +38,7 @@ interface IImsMmTelFeature { int getFeatureState(); ImsCallProfile createCallProfile(int callSessionType, int callType); IImsCallSession createCallSession(in ImsCallProfile profile); + int shouldProcessCall(in String[] uris); IImsUt getUtInterface(); IImsEcbm getEcbmInterface(); void setUiTtyMode(int uiTtyMode, in Message onCompleteMessage); diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl index 43f5098af3ca..904e7cad9c14 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl @@ -14,7 +14,9 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; + +import android.os.Bundle; import com.android.ims.internal.IImsCallSession; @@ -23,6 +25,6 @@ import com.android.ims.internal.IImsCallSession; * {@hide} */ oneway interface IImsMmTelListener { - void onIncomingCall(IImsCallSession c); + void onIncomingCall(IImsCallSession c, in Bundle extras); void onVoiceMessageCountUpdate(int count); }
\ No newline at end of file diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl index f6005b66bd3c..691cfba9a28c 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; /** * See RcsFeature for more information. diff --git a/telephony/java/com/android/ims/internal/IImsRegistration.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl index 6de264ec90fb..4ae0a75ad027 100644 --- a/telephony/java/com/android/ims/internal/IImsRegistration.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl @@ -15,9 +15,9 @@ */ -package com.android.ims.internal; +package android.telephony.ims.aidl; -import com.android.ims.internal.IImsRegistrationCallback; +import android.telephony.ims.aidl.IImsRegistrationCallback; /** * See ImsRegistration for more information. diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl index 5f21167422dc..a745a3819f40 100644 --- a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl @@ -15,10 +15,10 @@ */ -package com.android.ims.internal; +package android.telephony.ims.aidl; import android.net.Uri; -import android.telephony.ims.internal.stub.ImsFeatureConfiguration; +import android.telephony.ims.stub.ImsFeatureConfiguration; import com.android.ims.ImsReasonInfo; diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl index 82a85254bbca..86f8606ac39f 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl @@ -14,16 +14,16 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; -import android.telephony.ims.internal.aidl.IImsMmTelFeature; -import android.telephony.ims.internal.aidl.IImsRcsFeature; -import android.telephony.ims.internal.aidl.IImsConfig; -import android.telephony.ims.internal.aidl.IImsServiceControllerListener; -import android.telephony.ims.internal.stub.ImsFeatureConfiguration; +import android.telephony.ims.aidl.IImsMmTelFeature; +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.stub.ImsFeatureConfiguration; import com.android.ims.internal.IImsFeatureStatusCallback; -import com.android.ims.internal.IImsRegistration; /** * See ImsService and MmTelFeature for more information. @@ -41,4 +41,6 @@ interface IImsServiceController { void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c); IImsConfig getConfig(int slotId); IImsRegistration getRegistration(int slotId); + oneway void enableIms(int slotId); + oneway void disableIms(int slotId); } diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl index 01cca2db0978..54f6120aa99c 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl @@ -14,9 +14,9 @@ * limitations under the License. */ -package android.telephony.ims.internal.aidl; +package android.telephony.ims.aidl; -import android.telephony.ims.internal.stub.ImsFeatureConfiguration; +import android.telephony.ims.stub.ImsFeatureConfiguration; /** * See ImsService#Listener for more information. diff --git a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl index 5a4b7e489025..606df15b1782 100644 --- a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.android.ims.internal; +package android.telephony.ims.aidl; /** * See SmsImplBase for more information. * {@hide} */ -interface IImsSmsListener { +oneway interface IImsSmsListener { void onSendSmsResult(int token, int messageRef, int status, int reason); void onSmsStatusReportReceived(int token, int messageRef, in String format, in byte[] pdu); diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java new file mode 100644 index 000000000000..cf1efb34bd0a --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/ImsService.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2018 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.compat; + +import android.annotation.Nullable; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.RemoteException; +import android.telephony.CarrierConfigManager; +import android.telephony.ims.compat.feature.ImsFeature; +import android.telephony.ims.compat.feature.MMTelFeature; +import android.telephony.ims.compat.feature.RcsFeature; +import android.util.Log; +import android.util.SparseArray; + +import com.android.ims.internal.IImsFeatureStatusCallback; +import com.android.ims.internal.IImsMMTelFeature; +import com.android.ims.internal.IImsRcsFeature; +import com.android.ims.internal.IImsServiceController; +import com.android.internal.annotations.VisibleForTesting; + +/** + * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend + * ImsService must register the service in their AndroidManifest to be detected by the framework. + * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE" + * permission. Then, the ImsService definition in the manifest must follow the following format: + * + * ... + * <service android:name=".EgImsService" + * android:permission="android.permission.BIND_IMS_SERVICE" > + * <!-- Apps must declare which features they support as metadata. The different categories are + * defined below. In this example, the RCS_FEATURE feature is supported. --> + * <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" /> + * <intent-filter> + * <action android:name="android.telephony.ims.compat.ImsService" /> + * </intent-filter> + * </service> + * ... + * + * The telephony framework will then bind to the ImsService you have defined in your manifest + * if you are either: + * 1) Defined as the default ImsService for the device in the device overlay using + * "config_ims_package". + * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using + * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}. + * + * The features that are currently supported in an ImsService are: + * - RCS_FEATURE: This ImsService implements the RcsFeature class. + * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class. + * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be + * available to place emergency calls at all times. This MUST be implemented by the default + * ImsService provided in the device overlay. + * @hide + */ +public class ImsService extends Service { + + private static final String LOG_TAG = "ImsService(Compat)"; + + /** + * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService. + * @hide + */ + public static final String SERVICE_INTERFACE = "android.telephony.ims.compat.ImsService"; + + // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that + // slot. + // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and + // call ImsFeature#onFeatureRemoved. + private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>(); + + /** + * @hide + */ + protected final IBinder mImsServiceController = new IImsServiceController.Stub() { + + @Override + public IImsMMTelFeature createEmergencyMMTelFeature(int slotId, + IImsFeatureStatusCallback c) { + return createEmergencyMMTelFeatureInternal(slotId, c); + } + + @Override + public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) { + return createMMTelFeatureInternal(slotId, c); + } + + @Override + public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) { + return createRcsFeatureInternal(slotId, c); + } + + @Override + public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c) + throws RemoteException { + ImsService.this.removeImsFeature(slotId, featureType, c); + } + }; + + /** + * @hide + */ + @Override + public IBinder onBind(Intent intent) { + if(SERVICE_INTERFACE.equals(intent.getAction())) { + Log.i(LOG_TAG, "ImsService(Compat) Bound."); + return mImsServiceController; + } + return null; + } + + /** + * @hide + */ + @VisibleForTesting + public SparseArray<ImsFeature> getFeatures(int slotId) { + return mFeaturesBySlot.get(slotId); + } + + private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId, + IImsFeatureStatusCallback c) { + MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId); + if (f != null) { + setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c); + return f.getBinder(); + } else { + return null; + } + } + + private IImsMMTelFeature createMMTelFeatureInternal(int slotId, + IImsFeatureStatusCallback c) { + MMTelFeature f = onCreateMMTelImsFeature(slotId); + if (f != null) { + setupFeature(f, slotId, ImsFeature.MMTEL, c); + return f.getBinder(); + } else { + return null; + } + } + + private IImsRcsFeature createRcsFeatureInternal(int slotId, + IImsFeatureStatusCallback c) { + RcsFeature f = onCreateRcsFeature(slotId); + if (f != null) { + setupFeature(f, slotId, ImsFeature.RCS, c); + return f.getBinder(); + } else { + return null; + } + } + + private void setupFeature(ImsFeature f, int slotId, int featureType, + IImsFeatureStatusCallback c) { + f.setContext(this); + f.setSlotId(slotId); + f.addImsFeatureStatusCallback(c); + addImsFeature(slotId, featureType, f); + // TODO: Remove once new onFeatureReady AIDL is merged in. + f.onFeatureReady(); + } + + private void addImsFeature(int slotId, int featureType, ImsFeature f) { + synchronized (mFeaturesBySlot) { + // Get SparseArray for Features, by querying slot Id + SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); + if (features == null) { + // Populate new SparseArray of features if it doesn't exist for this slot yet. + features = new SparseArray<>(); + mFeaturesBySlot.put(slotId, features); + } + features.put(featureType, f); + } + } + + private void removeImsFeature(int slotId, int featureType, + IImsFeatureStatusCallback c) { + synchronized (mFeaturesBySlot) { + // get ImsFeature associated with the slot/feature + SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); + if (features == null) { + Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot " + + slotId); + return; + } + ImsFeature f = features.get(featureType); + if (f == null) { + Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type " + + featureType + " exists on slot " + slotId); + return; + } + f.removeImsFeatureStatusCallback(c); + f.onFeatureRemoved(); + features.remove(featureType); + } + } + + /** + * @return An implementation of MMTelFeature that will be used by the system for MMTel + * functionality. Must be able to handle emergency calls at any time as well. + * @hide + */ + public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) { + return null; + } + + /** + * @return An implementation of MMTelFeature that will be used by the system for MMTel + * functionality. + * @hide + */ + public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) { + return null; + } + + /** + * @return An implementation of RcsFeature that will be used by the system for RCS. + * @hide + */ + public @Nullable RcsFeature onCreateRcsFeature(int slotId) { + return null; + } +} diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java new file mode 100644 index 000000000000..0a12cae26af4 --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2018 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.compat.feature; + +import android.annotation.IntDef; +import android.content.Context; +import android.content.Intent; +import android.os.IInterface; +import android.os.RemoteException; +import android.telephony.SubscriptionManager; +import android.util.Log; + +import com.android.ims.internal.IImsFeatureStatusCallback; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; +import java.util.WeakHashMap; + +/** + * Base class for all IMS features that are supported by the framework. + * @hide + */ +public abstract class ImsFeature { + + private static final String LOG_TAG = "ImsFeature"; + + /** + * Action to broadcast when ImsService is up. + * Internal use only. + * Only defined here separately compatibility purposes with the old ImsService. + * @hide + */ + public static final String ACTION_IMS_SERVICE_UP = + "com.android.ims.IMS_SERVICE_UP"; + + /** + * Action to broadcast when ImsService is down. + * Internal use only. + * Only defined here separately for compatibility purposes with the old ImsService. + * @hide + */ + public static final String ACTION_IMS_SERVICE_DOWN = + "com.android.ims.IMS_SERVICE_DOWN"; + + /** + * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents. + * A long value; the phone ID corresponding to the IMS service coming up or down. + * Only defined here separately for compatibility purposes with the old ImsService. + * @hide + */ + public static final String EXTRA_PHONE_ID = "android:phone_id"; + + // Invalid feature value + public static final int INVALID = -1; + // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously + // defined values in ImsServiceClass for compatibility purposes. + public static final int EMERGENCY_MMTEL = 0; + public static final int MMTEL = 1; + public static final int RCS = 2; + // Total number of features defined + public static final int MAX = 3; + + // Integer values defining the state of the ImsFeature at any time. + @IntDef(flag = true, + value = { + STATE_NOT_AVAILABLE, + STATE_INITIALIZING, + STATE_READY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ImsState {} + public static final int STATE_NOT_AVAILABLE = 0; + public static final int STATE_INITIALIZING = 1; + public static final int STATE_READY = 2; + + private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap( + new WeakHashMap<IImsFeatureStatusCallback, Boolean>()); + private @ImsState int mState = STATE_NOT_AVAILABLE; + private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; + protected Context mContext; + + public void setContext(Context context) { + mContext = context; + } + + public void setSlotId(int slotId) { + mSlotId = slotId; + } + + public int getFeatureState() { + return mState; + } + + protected final void setFeatureState(@ImsState int state) { + if (mState != state) { + mState = state; + notifyFeatureState(state); + } + } + + public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) { + if (c == null) { + return; + } + try { + // If we have just connected, send queued status. + c.notifyImsFeatureStatus(mState); + // Add the callback if the callback completes successfully without a RemoteException. + synchronized (mStatusCallbacks) { + mStatusCallbacks.add(c); + } + } catch (RemoteException e) { + Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); + } + } + + public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) { + if (c == null) { + return; + } + synchronized (mStatusCallbacks) { + mStatusCallbacks.remove(c); + } + } + + /** + * Internal method called by ImsFeature when setFeatureState has changed. + * @param state + */ + private void notifyFeatureState(@ImsState int state) { + synchronized (mStatusCallbacks) { + for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator(); + iter.hasNext(); ) { + IImsFeatureStatusCallback callback = iter.next(); + try { + Log.i(LOG_TAG, "notifying ImsFeatureState=" + state); + callback.notifyImsFeatureStatus(state); + } catch (RemoteException e) { + // remove if the callback is no longer alive. + iter.remove(); + Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); + } + } + } + sendImsServiceIntent(state); + } + + /** + * Provide backwards compatibility using deprecated service UP/DOWN intents. + */ + private void sendImsServiceIntent(@ImsState int state) { + if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + return; + } + Intent intent; + switch (state) { + case ImsFeature.STATE_NOT_AVAILABLE: + case ImsFeature.STATE_INITIALIZING: + intent = new Intent(ACTION_IMS_SERVICE_DOWN); + break; + case ImsFeature.STATE_READY: + intent = new Intent(ACTION_IMS_SERVICE_UP); + break; + default: + intent = new Intent(ACTION_IMS_SERVICE_DOWN); + } + intent.putExtra(EXTRA_PHONE_ID, mSlotId); + mContext.sendBroadcast(intent); + } + + /** + * Called when the feature is ready to use. + */ + public abstract void onFeatureReady(); + + /** + * Called when the feature is being removed and must be cleaned up. + */ + public abstract void onFeatureRemoved(); + + /** + * @return Binder instance + */ + public abstract IInterface getBinder(); +} diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java index 403bb60404cf..f5c5857b7ab3 100644 --- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java +++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java @@ -16,33 +16,342 @@ package android.telephony.ims.compat.feature; +import android.app.PendingIntent; +import android.os.Message; +import android.os.RemoteException; + import com.android.ims.ImsCallProfile; import com.android.ims.internal.IImsCallSession; -import com.android.ims.internal.IImsCallSessionListener; +import com.android.ims.internal.IImsConfig; +import com.android.ims.internal.IImsEcbm; +import com.android.ims.internal.IImsMMTelFeature; +import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsUt; import com.android.ims.internal.ImsCallSession; /** - * Compatability layer for older implementations of MMTelFeature. + * Base implementation for MMTel. + * Any class wishing to use MMTelFeature should extend this class and implement all methods that the + * service supports. * * @hide */ -public class MMTelFeature extends android.telephony.ims.feature.MMTelFeature { +public class MMTelFeature extends ImsFeature { + + // Lock for feature synchronization + private final Object mLock = new Object(); + + private final IImsMMTelFeature mImsMMTelBinder = new IImsMMTelFeature.Stub() { + + @Override + public int startSession(PendingIntent incomingCallIntent, + IImsRegistrationListener listener) throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.startSession(incomingCallIntent, listener); + } + } + + @Override + public void endSession(int sessionId) throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.endSession(sessionId); + } + } + + @Override + public boolean isConnected(int callSessionType, int callType) + throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.isConnected(callSessionType, callType); + } + } + + @Override + public boolean isOpened() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.isOpened(); + } + } + + @Override + public int getFeatureStatus() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getFeatureState(); + } + } + + @Override + public void addRegistrationListener(IImsRegistrationListener listener) + throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.addRegistrationListener(listener); + } + } + + @Override + public void removeRegistrationListener(IImsRegistrationListener listener) + throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.removeRegistrationListener(listener); + } + } + + @Override + public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType) + throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.createCallProfile(sessionId, callSessionType, callType); + } + } + + @Override + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) + throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.createCallSession(sessionId, profile); + } + } + + @Override + public IImsCallSession getPendingCallSession(int sessionId, String callId) + throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getPendingCallSession(sessionId, callId); + } + } + @Override + public IImsUt getUtInterface() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getUtInterface(); + } + } + + @Override + public IImsConfig getConfigInterface() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getConfigInterface(); + } + } + + @Override + public void turnOnIms() throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.turnOnIms(); + } + } + + @Override + public void turnOffIms() throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.turnOffIms(); + } + } + + @Override + public IImsEcbm getEcbmInterface() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getEcbmInterface(); + } + } + + @Override + public void setUiTTYMode(int uiTtyMode, Message onComplete) throws RemoteException { + synchronized (mLock) { + MMTelFeature.this.setUiTTYMode(uiTtyMode, onComplete); + } + } + + @Override + public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { + synchronized (mLock) { + return MMTelFeature.this.getMultiEndpointInterface(); + } + } + }; + + /** + * @hide + */ @Override - public final IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) { - return createCallSession(sessionId, profile, null /*listener*/); + public final IImsMMTelFeature getBinder() { + return mImsMMTelBinder; + } + + /** + * Notifies the MMTel feature that you would like to start a session. This should always be + * done before making/receiving IMS calls. The IMS service will register the device to the + * operator's network with the credentials (from ISIM) periodically in order to receive calls + * from the operator's network. When the IMS service receives a new call, it will send out an + * intent with the provided action string. The intent contains a call ID extra + * {@link IImsCallSession#getCallId} and it can be used to take a call. + * + * @param incomingCallIntent When an incoming call is received, the IMS service will call + * {@link PendingIntent#send} to send back the intent to the caller with + * ImsManager#INCOMING_CALL_RESULT_CODE as the result code and the intent to fill in the call + * ID; It cannot be null. + * @param listener To listen to IMS registration events; It cannot be null + * @return an integer (greater than 0) representing the session id associated with the session + * that has been started. + */ + public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) { + return 0; + } + + /** + * End a previously started session using the associated sessionId. + * @param sessionId an integer (greater than 0) representing the ongoing session. See + * {@link #startSession}. + */ + public void endSession(int sessionId) { + } + + /** + * Checks if the IMS service has successfully registered to the IMS network with the specified + * service & call type. + * + * @param callSessionType a service type that is specified in {@link ImsCallProfile} + * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} + * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} + * @param callType a call type that is specified in {@link ImsCallProfile} + * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO} + * {@link ImsCallProfile#CALL_TYPE_VOICE} + * {@link ImsCallProfile#CALL_TYPE_VT} + * {@link ImsCallProfile#CALL_TYPE_VS} + * @return true if the specified service id is connected to the IMS network; false otherwise + */ + public boolean isConnected(int callSessionType, int callType) { + return false; + } + + /** + * Checks if the specified IMS service is opened. + * + * @return true if the specified service id is opened; false otherwise + */ + public boolean isOpened() { + return false; + } + + /** + * Add a new registration listener for the client associated with the session Id. + * @param listener An implementation of IImsRegistrationListener. + */ + public void addRegistrationListener(IImsRegistrationListener listener) { + } + + /** + * Remove a previously registered listener using {@link #addRegistrationListener} for the client + * associated with the session Id. + * @param listener A previously registered IImsRegistrationListener + */ + public void removeRegistrationListener(IImsRegistrationListener listener) { + } + + /** + * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. + * + * @param sessionId a session id which is obtained from {@link #startSession} + * @param callSessionType a service type that is specified in {@link ImsCallProfile} + * {@link ImsCallProfile#SERVICE_TYPE_NONE} + * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} + * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} + * @param callType a call type that is specified in {@link ImsCallProfile} + * {@link ImsCallProfile#CALL_TYPE_VOICE} + * {@link ImsCallProfile#CALL_TYPE_VT} + * {@link ImsCallProfile#CALL_TYPE_VT_TX} + * {@link ImsCallProfile#CALL_TYPE_VT_RX} + * {@link ImsCallProfile#CALL_TYPE_VT_NODIR} + * {@link ImsCallProfile#CALL_TYPE_VS} + * {@link ImsCallProfile#CALL_TYPE_VS_TX} + * {@link ImsCallProfile#CALL_TYPE_VS_RX} + * @return a {@link ImsCallProfile} object + */ + public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType) { + return null; } /** * Creates an {@link ImsCallSession} with the specified call profile. + * Use other methods, if applicable, instead of interacting with + * {@link ImsCallSession} directly. * * @param sessionId a session id which is obtained from {@link #startSession} * @param profile a call profile to make the call - * @param listener An implementation of IImsCallSessionListener. */ - public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, - IImsCallSessionListener listener) { + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) { + return null; + } + + /** + * Retrieves the call session associated with a pending call. + * + * @param sessionId a session id which is obtained from {@link #startSession} + * @param callId a call id to make the call + */ + public IImsCallSession getPendingCallSession(int sessionId, String callId) { + return null; + } + + /** + * @return The Ut interface for the supplementary service configuration. + */ + public IImsUt getUtInterface() { + return null; + } + + /** + * @return The config interface for IMS Configuration + */ + public IImsConfig getConfigInterface() { + return null; + } + + /** + * Signal the MMTelFeature to turn on IMS when it has been turned off using {@link #turnOffIms} + */ + public void turnOnIms() { + } + + /** + * Signal the MMTelFeature to turn off IMS when it has been turned on using {@link #turnOnIms} + */ + public void turnOffIms() { + } + + /** + * @return The Emergency call-back mode interface for emergency VoLTE calls that support it. + */ + public IImsEcbm getEcbmInterface() { + return null; + } + + /** + * Sets the current UI TTY mode for the MMTelFeature. + * @param uiTtyMode An integer containing the new UI TTY Mode. + * @param onComplete A {@link Message} to be used when the mode has been set. + */ + public void setUiTTYMode(int uiTtyMode, Message onComplete) { + } + + /** + * @return MultiEndpoint interface for DEP notifications + */ + public IImsMultiEndpoint getMultiEndpointInterface() { return null; } + + @Override + public void onFeatureReady() { + + } + + /** + * {@inheritDoc} + */ + public void onFeatureRemoved() { + + } } diff --git a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java index 8d1bd9d27f7c..228b33045107 100644 --- a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -14,9 +14,10 @@ * limitations under the License */ -package android.telephony.ims.internal.feature; +package android.telephony.ims.compat.feature; -import android.telephony.ims.internal.aidl.IImsRcsFeature; + +import com.android.ims.internal.IImsRcsFeature; /** * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend @@ -36,19 +37,12 @@ public class RcsFeature extends ImsFeature { } @Override - public void changeEnabledCapabilities(CapabilityChangeRequest request, - CapabilityCallbackProxy c) { - // Do nothing for base implementation. - } - - @Override - public void onFeatureRemoved() { + public void onFeatureReady() { } - /**{@inheritDoc}*/ @Override - public void onFeatureReady() { + public void onFeatureRemoved() { } diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java new file mode 100644 index 000000000000..b5417e77c008 --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2018 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.compat.stub; + +import android.os.RemoteException; + +import com.android.ims.ImsConfig; +import com.android.ims.ImsConfigListener; +import com.android.ims.internal.IImsConfig; + +/** + * Base implementation of ImsConfig, which implements stub versions of the methods + * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports. + * + * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you + * will break other implementations of ImsConfig maintained by other ImsServices. + * + * Provides APIs to get/set the IMS service feature/capability/parameters. + * The config items include: + * 1) Items provisioned by the operator. + * 2) Items configured by user. Mainly service feature class. + * + * @hide + */ + +public class ImsConfigImplBase extends IImsConfig.Stub { + + /** + * Gets the value for ims service/capabilities parameters from the provisioned + * value storage. Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in Integer format. + */ + @Override + public int getProvisionedValue(int item) throws RemoteException { + return -1; + } + + /** + * Gets the value for ims service/capabilities parameters from the provisioned + * value storage. Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in String format. + */ + @Override + public String getProvisionedStringValue(int item) throws RemoteException { + return null; + } + + /** + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived. Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in Integer format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + */ + @Override + public int setProvisionedValue(int item, int value) throws RemoteException { + return ImsConfig.OperationStatusConstants.FAILED; + } + + /** + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived. Synchronous blocking call. + * + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in String format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + */ + @Override + public int setProvisionedStringValue(int item, String value) throws RemoteException { + return ImsConfig.OperationStatusConstants.FAILED; + } + + /** + * Gets the value of the specified IMS feature item for specified network type. + * This operation gets the feature config value from the master storage (i.e. final + * value). Asynchronous non-blocking call. + * + * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. + * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. + * @param listener feature value returned asynchronously through listener. + */ + @Override + public void getFeatureValue(int feature, int network, ImsConfigListener listener) + throws RemoteException { + } + + /** + * Sets the value for IMS feature item for specified network type. + * This operation stores the user setting in setting db from which master db + * is derived. + * + * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. + * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. + * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants. + * @param listener, provided if caller needs to be notified for set result. + */ + @Override + public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) + throws RemoteException { + } + + /** + * Gets the value for IMS VoLTE provisioned. + * This should be the same as the operator provisioned value if applies. + */ + @Override + public boolean getVolteProvisioned() throws RemoteException { + return false; + } + + /** + * Gets the value for IMS feature item video quality. + * + * @param listener Video quality value returned asynchronously through listener. + */ + @Override + public void getVideoQuality(ImsConfigListener listener) throws RemoteException { + } + + /** + * Sets the value for IMS feature item video quality. + * + * @param quality, defines the value of video quality. + * @param listener, provided if caller needs to be notified for set result. + */ + @Override + public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException { + } +} diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl index f4ec0eb38f34..e789bd5ac940 100644 --- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl @@ -14,6 +14,6 @@ * limitations under the License */ -package android.telephony.ims.internal.feature; +package android.telephony.ims.feature; parcelable CapabilityChangeRequest; diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 5dbf077ee7c5..efb6ffe99049 100644 --- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -14,7 +14,7 @@ * limitations under the License */ -package android.telephony.ims.internal.feature; +package android.telephony.ims.feature; import android.os.Parcel; import android.os.Parcelable; @@ -182,7 +182,8 @@ public class CapabilityChangeRequest implements Parcelable { if (this == o) return true; if (!(o instanceof CapabilityChangeRequest)) return false; - CapabilityChangeRequest that = (CapabilityChangeRequest) o; + CapabilityChangeRequest + that = (CapabilityChangeRequest) o; if (!mCapabilitiesToEnable.equals(that.mCapabilitiesToEnable)) return false; return mCapabilitiesToDisable.equals(that.mCapabilitiesToDisable); diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index d47cea3097f3..2cc0a8a22759 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -17,26 +17,29 @@ package android.telephony.ims.feature; import android.annotation.IntDef; +import android.annotation.NonNull; import android.content.Context; import android.content.Intent; import android.os.IInterface; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.SubscriptionManager; +import android.telephony.ims.aidl.IImsCapabilityCallback; import android.util.Log; import com.android.ims.internal.IImsFeatureStatusCallback; +import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.WeakHashMap; /** * Base class for all IMS features that are supported by the framework. + * * @hide */ public abstract class ImsFeature { @@ -46,7 +49,8 @@ public abstract class ImsFeature { /** * Action to broadcast when ImsService is up. * Internal use only. - * Only defined here separately compatibility purposes with the old ImsService. + * Only defined here separately for compatibility purposes with the old ImsService. + * * @hide */ public static final String ACTION_IMS_SERVICE_UP = @@ -56,6 +60,7 @@ public abstract class ImsFeature { * Action to broadcast when ImsService is down. * Internal use only. * Only defined here separately for compatibility purposes with the old ImsService. + * * @hide */ public static final String ACTION_IMS_SERVICE_DOWN = @@ -65,67 +70,259 @@ public abstract class ImsFeature { * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents. * A long value; the phone ID corresponding to the IMS service coming up or down. * Only defined here separately for compatibility purposes with the old ImsService. + * * @hide */ public static final String EXTRA_PHONE_ID = "android:phone_id"; // Invalid feature value - public static final int INVALID = -1; + public static final int FEATURE_INVALID = -1; // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously // defined values in ImsServiceClass for compatibility purposes. - public static final int EMERGENCY_MMTEL = 0; - public static final int MMTEL = 1; - public static final int RCS = 2; + public static final int FEATURE_EMERGENCY_MMTEL = 0; + public static final int FEATURE_MMTEL = 1; + public static final int FEATURE_RCS = 2; // Total number of features defined - public static final int MAX = 3; + public static final int FEATURE_MAX = 3; + + // Integer values defining IMS features that are supported in ImsFeature. + @IntDef(flag = true, + value = { + FEATURE_EMERGENCY_MMTEL, + FEATURE_MMTEL, + FEATURE_RCS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FeatureType {} // Integer values defining the state of the ImsFeature at any time. @IntDef(flag = true, value = { - STATE_NOT_AVAILABLE, + STATE_UNAVAILABLE, STATE_INITIALIZING, STATE_READY, }) @Retention(RetentionPolicy.SOURCE) public @interface ImsState {} - public static final int STATE_NOT_AVAILABLE = 0; + + public static final int STATE_UNAVAILABLE = 0; public static final int STATE_INITIALIZING = 1; public static final int STATE_READY = 2; + // Integer values defining the result codes that should be returned from + // {@link changeEnabledCapabilities} when the framework tries to set a feature's capability. + @IntDef(flag = true, + value = { + CAPABILITY_ERROR_GENERIC, + CAPABILITY_SUCCESS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ImsCapabilityError {} + + public static final int CAPABILITY_ERROR_GENERIC = -1; + public static final int CAPABILITY_SUCCESS = 0; + + + /** + * The framework implements this callback in order to register for Feature Capability status + * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability + * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error + * callbacks when the ImsService can not change the capability as requested, via + * {@link #onChangeCapabilityConfigurationError}. + */ + public static class CapabilityCallback extends IImsCapabilityCallback.Stub { + + @Override + public final void onCapabilitiesStatusChanged(int config) throws RemoteException { + onCapabilitiesStatusChanged(new Capabilities(config)); + } + + /** + * Returns the result of a query for the capability configuration of a requested capability. + * + * @param capability The capability that was requested. + * @param radioTech The IMS radio technology associated with the capability. + * @param isEnabled true if the capability is enabled, false otherwise. + */ + @Override + public void onQueryCapabilityConfiguration(int capability, int radioTech, + boolean isEnabled) { + + } + + /** + * Called when a change to the capability configuration has returned an error. + * + * @param capability The capability that was requested to be changed. + * @param radioTech The IMS radio technology associated with the capability. + * @param reason error associated with the failure to change configuration. + */ + @Override + public void onChangeCapabilityConfigurationError(int capability, int radioTech, + int reason) { + } + + /** + * The status of the feature's capabilities has changed to either available or unavailable. + * If unavailable, the feature is not able to support the unavailable capability at this + * time. + * + * @param config The new availability of the capabilities. + */ + public void onCapabilitiesStatusChanged(Capabilities config) { + } + } + + /** + * Used by the ImsFeature to call back to the CapabilityCallback that the framework has + * provided. + */ + protected static class CapabilityCallbackProxy { + private final IImsCapabilityCallback mCallback; + + public CapabilityCallbackProxy(IImsCapabilityCallback c) { + mCallback = c; + } + + /** + * This method notifies the provided framework callback that the request to change the + * indicated capability has failed and has not changed. + * + * @param capability The Capability that will be notified to the framework. + * @param radioTech The radio tech that this capability failed for. + * @param reason The reason this capability was unable to be changed. + */ + public void onChangeCapabilityConfigurationError(int capability, int radioTech, + @ImsCapabilityError int reason) { + if (mCallback == null) { + return; + } + try { + mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason); + } catch (RemoteException e) { + Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder."); + } + } + + public void onQueryCapabilityConfiguration(int capability, int radioTech, + boolean isEnabled) { + if (mCallback == null) { + return; + } + try { + mCallback.onQueryCapabilityConfiguration(capability, radioTech, isEnabled); + } catch (RemoteException e) { + Log.e(LOG_TAG, "onQueryCapabilityConfiguration called on dead binder."); + } + } + } + + /** + * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask. + */ + public static class Capabilities { + protected int mCapabilities = 0; + + public Capabilities() { + } + + protected Capabilities(int capabilities) { + mCapabilities = capabilities; + } + + /** + * @param capabilities Capabilities to be added to the configuration in the form of a + * bit mask. + */ + public void addCapabilities(int capabilities) { + mCapabilities |= capabilities; + } + + /** + * @param capabilities Capabilities to be removed to the configuration in the form of a + * bit mask. + */ + public void removeCapabilities(int capabilities) { + mCapabilities &= ~capabilities; + } + + /** + * @return true if all of the capabilities specified are capable. + */ + public boolean isCapable(int capabilities) { + return (mCapabilities & capabilities) == capabilities; + } + + public Capabilities copy() { + return new Capabilities(mCapabilities); + } + + /** + * @return a bitmask containing the capability flags directly. + */ + public int getMask() { + return mCapabilities; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Capabilities)) return false; + + Capabilities that = (Capabilities) o; + + return mCapabilities == that.mCapabilities; + } + + @Override + public int hashCode() { + return mCapabilities; + } + + @Override + public String toString() { + return "Capabilities: " + Integer.toBinaryString(mCapabilities); + } + } + private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap( new WeakHashMap<IImsFeatureStatusCallback, Boolean>()); - private @ImsState int mState = STATE_NOT_AVAILABLE; + private @ImsState int mState = STATE_UNAVAILABLE; private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; protected Context mContext; + private final Object mLock = new Object(); + private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks + = new RemoteCallbackList<>(); + private Capabilities mCapabilityStatus = new Capabilities(); - public void setContext(Context context) { + public final void initialize(Context context, int slotId) { mContext = context; - } - - public void setSlotId(int slotId) { mSlotId = slotId; } - public int getFeatureState() { - return mState; + public final int getFeatureState() { + synchronized (mLock) { + return mState; + } } protected final void setFeatureState(@ImsState int state) { - if (mState != state) { - mState = state; - notifyFeatureState(state); + synchronized (mLock) { + if (mState != state) { + mState = state; + notifyFeatureState(state); + } } } - public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) { - if (c == null) { - return; - } + // Not final for testing, but shouldn't be extended! + @VisibleForTesting + public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) { try { // If we have just connected, send queued status. - c.notifyImsFeatureStatus(mState); + c.notifyImsFeatureStatus(getFeatureState()); // Add the callback if the callback completes successfully without a RemoteException. - synchronized (mStatusCallbacks) { + synchronized (mLock) { mStatusCallbacks.add(c); } } catch (RemoteException e) { @@ -133,23 +330,21 @@ public abstract class ImsFeature { } } - public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) { - if (c == null) { - return; - } - synchronized (mStatusCallbacks) { + @VisibleForTesting + // Not final for testing, but should not be extended! + public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) { + synchronized (mLock) { mStatusCallbacks.remove(c); } } /** * Internal method called by ImsFeature when setFeatureState has changed. - * @param state */ private void notifyFeatureState(@ImsState int state) { - synchronized (mStatusCallbacks) { + synchronized (mLock) { for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator(); - iter.hasNext(); ) { + iter.hasNext(); ) { IImsFeatureStatusCallback callback = iter.next(); try { Log.i(LOG_TAG, "notifying ImsFeatureState=" + state); @@ -168,12 +363,12 @@ public abstract class ImsFeature { * Provide backwards compatibility using deprecated service UP/DOWN intents. */ private void sendImsServiceIntent(@ImsState int state) { - if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { return; } Intent intent; switch (state) { - case ImsFeature.STATE_NOT_AVAILABLE: + case ImsFeature.STATE_UNAVAILABLE: case ImsFeature.STATE_INITIALIZING: intent = new Intent(ACTION_IMS_SERVICE_DOWN); break; @@ -187,18 +382,92 @@ public abstract class ImsFeature { mContext.sendBroadcast(intent); } + public final void addCapabilityCallback(IImsCapabilityCallback c) { + mCapabilityCallbacks.register(c); + } + + public final void removeCapabilityCallback(IImsCapabilityCallback c) { + mCapabilityCallbacks.unregister(c); + } + /** - * Called when the feature is ready to use. + * @return the cached capabilities status for this feature. */ - public abstract void onFeatureReady(); + @VisibleForTesting + public Capabilities queryCapabilityStatus() { + synchronized (mLock) { + return mCapabilityStatus.copy(); + } + } + + // Called internally to request the change of enabled capabilities. + @VisibleForTesting + public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request, + IImsCapabilityCallback c) throws RemoteException { + if (request == null) { + throw new IllegalArgumentException( + "ImsFeature#requestChangeEnabledCapabilities called with invalid params."); + } + changeEnabledCapabilities(request, new CapabilityCallbackProxy(c)); + } + + /** + * Called by the ImsFeature when the capabilities status has changed. + * + * @param c A {@link Capabilities} containing the new Capabilities status. + */ + protected final void notifyCapabilitiesStatusChanged(Capabilities c) { + synchronized (mLock) { + mCapabilityStatus = c.copy(); + } + int count = mCapabilityCallbacks.beginBroadcast(); + try { + for (int i = 0; i < count; i++) { + try { + mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged( + c.mCapabilities); + } catch (RemoteException e) { + Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " + + "callback."); + } + } + } finally { + mCapabilityCallbacks.finishBroadcast(); + } + } /** - * Called when the feature is being removed and must be cleaned up. + * Features should override this method to receive Capability preference change requests from + * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities + * in the {@link CapabilityChangeRequest} are not able to be completed due to an error, + * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for + * each failed capability. + * + * @param request A {@link CapabilityChangeRequest} containing requested capabilities to + * enable/disable. + * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework + * setting a subset of these capabilities fail, using + * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}. + */ + public abstract void changeEnabledCapabilities(CapabilityChangeRequest request, + CapabilityCallbackProxy c); + + /** + * Called when the framework is removing this feature and it needs to be cleaned up. */ public abstract void onFeatureRemoved(); /** - * @return Binder instance + * Called when the feature has been initialized and communication with the framework is set up. + * Any attempt by this feature to access the framework before this method is called will return + * with an {@link IllegalStateException}. + * The IMS provider should use this method to trigger registration for this feature on the IMS + * network, if needed. + */ + public abstract void onFeatureReady(); + + /** + * @return Binder instance that the framework will use to communicate with this feature. */ - public abstract IInterface getBinder(); + protected abstract IInterface getBinder(); } diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java deleted file mode 100644 index 68d63dfbe32f..000000000000 --- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2017 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.feature; - -import android.app.PendingIntent; -import android.os.Message; -import android.os.RemoteException; -import android.telephony.ims.internal.stub.SmsImplBase; - -import com.android.ims.ImsCallProfile; -import com.android.ims.internal.IImsCallSession; -import com.android.ims.internal.IImsConfig; -import com.android.ims.internal.IImsEcbm; -import com.android.ims.internal.IImsMMTelFeature; -import com.android.ims.internal.IImsMultiEndpoint; -import com.android.ims.internal.IImsRegistrationListener; -import com.android.ims.internal.IImsSmsListener; -import com.android.ims.internal.IImsUt; -import com.android.ims.internal.ImsCallSession; - -/** - * Base implementation for MMTel. - * Any class wishing to use MMTelFeature should extend this class and implement all methods that the - * service supports. - * - * @hide - */ - -public class MMTelFeature extends ImsFeature { - - // Lock for feature synchronization - private final Object mLock = new Object(); - - private final IImsMMTelFeature mImsMMTelBinder = new IImsMMTelFeature.Stub() { - - @Override - public int startSession(PendingIntent incomingCallIntent, - IImsRegistrationListener listener) throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.startSession(incomingCallIntent, listener); - } - } - - @Override - public void endSession(int sessionId) throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.endSession(sessionId); - } - } - - @Override - public boolean isConnected(int callSessionType, int callType) - throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.isConnected(callSessionType, callType); - } - } - - @Override - public boolean isOpened() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.isOpened(); - } - } - - @Override - public int getFeatureStatus() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getFeatureState(); - } - } - - @Override - public void addRegistrationListener(IImsRegistrationListener listener) - throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.addRegistrationListener(listener); - } - } - - @Override - public void removeRegistrationListener(IImsRegistrationListener listener) - throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.removeRegistrationListener(listener); - } - } - - @Override - public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType) - throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.createCallProfile(sessionId, callSessionType, callType); - } - } - - @Override - public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) - throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.createCallSession(sessionId, profile); - } - } - - @Override - public IImsCallSession getPendingCallSession(int sessionId, String callId) - throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getPendingCallSession(sessionId, callId); - } - } - - @Override - public IImsUt getUtInterface() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getUtInterface(); - } - } - - @Override - public IImsConfig getConfigInterface() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getConfigInterface(); - } - } - - @Override - public void turnOnIms() throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.turnOnIms(); - } - } - - @Override - public void turnOffIms() throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.turnOffIms(); - } - } - - @Override - public IImsEcbm getEcbmInterface() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getEcbmInterface(); - } - } - - @Override - public void setUiTTYMode(int uiTtyMode, Message onComplete) throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.setUiTTYMode(uiTtyMode, onComplete); - } - } - - @Override - public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { - synchronized (mLock) { - return MMTelFeature.this.getMultiEndpointInterface(); - } - } - - @Override - public void setSmsListener(IImsSmsListener l) throws RemoteException { - synchronized (mLock) { - MMTelFeature.this.setSmsListener(l); - } - } - - @Override - public void sendSms(int token, int messageRef, String format, String smsc, boolean retry, - byte[] pdu) { - synchronized (mLock) { - MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu); - } - } - - @Override - public void acknowledgeSms(int token, int messageRef, int result) { - synchronized (mLock) { - MMTelFeature.this.acknowledgeSms(token, messageRef, result); - } - } - - @Override - public void acknowledgeSmsReport(int token, int messageRef, int result) { - synchronized (mLock) { - MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result); - } - } - - @Override - public String getSmsFormat() { - synchronized (mLock) { - return MMTelFeature.this.getSmsFormat(); - } - } - - @Override - public void onSmsReady() { - synchronized (mLock) { - MMTelFeature.this.onSmsReady(); - } - } - }; - - /** - * @hide - */ - @Override - public final IImsMMTelFeature getBinder() { - return mImsMMTelBinder; - } - - /** - * Notifies the MMTel feature that you would like to start a session. This should always be - * done before making/receiving IMS calls. The IMS service will register the device to the - * operator's network with the credentials (from ISIM) periodically in order to receive calls - * from the operator's network. When the IMS service receives a new call, it will send out an - * intent with the provided action string. The intent contains a call ID extra - * {@link IImsCallSession#getCallId} and it can be used to take a call. - * - * @param incomingCallIntent When an incoming call is received, the IMS service will call - * {@link PendingIntent#send} to send back the intent to the caller with - * ImsManager#INCOMING_CALL_RESULT_CODE as the result code and the intent to fill in the call - * ID; It cannot be null. - * @param listener To listen to IMS registration events; It cannot be null - * @return an integer (greater than 0) representing the session id associated with the session - * that has been started. - */ - public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) { - return 0; - } - - /** - * End a previously started session using the associated sessionId. - * @param sessionId an integer (greater than 0) representing the ongoing session. See - * {@link #startSession}. - */ - public void endSession(int sessionId) { - } - - /** - * Checks if the IMS service has successfully registered to the IMS network with the specified - * service & call type. - * - * @param callSessionType a service type that is specified in {@link ImsCallProfile} - * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} - * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} - * @param callType a call type that is specified in {@link ImsCallProfile} - * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO} - * {@link ImsCallProfile#CALL_TYPE_VOICE} - * {@link ImsCallProfile#CALL_TYPE_VT} - * {@link ImsCallProfile#CALL_TYPE_VS} - * @return true if the specified service id is connected to the IMS network; false otherwise - */ - public boolean isConnected(int callSessionType, int callType) { - return false; - } - - /** - * Checks if the specified IMS service is opened. - * - * @return true if the specified service id is opened; false otherwise - */ - public boolean isOpened() { - return false; - } - - /** - * Add a new registration listener for the client associated with the session Id. - * @param listener An implementation of IImsRegistrationListener. - */ - public void addRegistrationListener(IImsRegistrationListener listener) { - } - - /** - * Remove a previously registered listener using {@link #addRegistrationListener} for the client - * associated with the session Id. - * @param listener A previously registered IImsRegistrationListener - */ - public void removeRegistrationListener(IImsRegistrationListener listener) { - } - - /** - * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. - * - * @param sessionId a session id which is obtained from {@link #startSession} - * @param callSessionType a service type that is specified in {@link ImsCallProfile} - * {@link ImsCallProfile#SERVICE_TYPE_NONE} - * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} - * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} - * @param callType a call type that is specified in {@link ImsCallProfile} - * {@link ImsCallProfile#CALL_TYPE_VOICE} - * {@link ImsCallProfile#CALL_TYPE_VT} - * {@link ImsCallProfile#CALL_TYPE_VT_TX} - * {@link ImsCallProfile#CALL_TYPE_VT_RX} - * {@link ImsCallProfile#CALL_TYPE_VT_NODIR} - * {@link ImsCallProfile#CALL_TYPE_VS} - * {@link ImsCallProfile#CALL_TYPE_VS_TX} - * {@link ImsCallProfile#CALL_TYPE_VS_RX} - * @return a {@link ImsCallProfile} object - */ - public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType) { - return null; - } - - /** - * Creates an {@link ImsCallSession} with the specified call profile. - * Use other methods, if applicable, instead of interacting with - * {@link ImsCallSession} directly. - * - * @param sessionId a session id which is obtained from {@link #startSession} - * @param profile a call profile to make the call - */ - public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) { - return null; - } - - /** - * Retrieves the call session associated with a pending call. - * - * @param sessionId a session id which is obtained from {@link #startSession} - * @param callId a call id to make the call - */ - public IImsCallSession getPendingCallSession(int sessionId, String callId) { - return null; - } - - /** - * @return The Ut interface for the supplementary service configuration. - */ - public IImsUt getUtInterface() { - return null; - } - - /** - * @return The config interface for IMS Configuration - */ - public IImsConfig getConfigInterface() { - return null; - } - - /** - * Signal the MMTelFeature to turn on IMS when it has been turned off using {@link #turnOffIms} - */ - public void turnOnIms() { - } - - /** - * Signal the MMTelFeature to turn off IMS when it has been turned on using {@link #turnOnIms} - */ - public void turnOffIms() { - } - - /** - * @return The Emergency call-back mode interface for emergency VoLTE calls that support it. - */ - public IImsEcbm getEcbmInterface() { - return null; - } - - /** - * Sets the current UI TTY mode for the MMTelFeature. - * @param uiTtyMode An integer containing the new UI TTY Mode. - * @param onComplete A {@link Message} to be used when the mode has been set. - */ - public void setUiTTYMode(int uiTtyMode, Message onComplete) { - } - - /** - * @return MultiEndpoint interface for DEP notifications - */ - public IImsMultiEndpoint getMultiEndpointInterface() { - return null; - } - - private void setSmsListener(IImsSmsListener listener) { - getSmsImplementation().registerSmsListener(listener); - } - - private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, - byte[] pdu) { - getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu); - } - - private void acknowledgeSms(int token, int messageRef, - @SmsImplBase.DeliverStatusResult int result) { - getSmsImplementation().acknowledgeSms(token, messageRef, result); - } - - private void acknowledgeSmsReport(int token, int messageRef, - @SmsImplBase.StatusReportResult int result) { - getSmsImplementation().acknowledgeSmsReport(token, messageRef, result); - } - - private void onSmsReady() { - getSmsImplementation().onReady(); - } - - /** - * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default - * non-functional implementation is returned. - * - * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider. - */ - protected SmsImplBase getSmsImplementation() { - return new SmsImplBase(); - } - - public String getSmsFormat() { - return getSmsImplementation().getSmsFormat(); - } - - @Override - public void onFeatureReady() { - - } - - /** - * {@inheritDoc} - */ - public void onFeatureRemoved() { - - } -} diff --git a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 23e0302ab4f1..83214b32fc38 100644 --- a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -14,17 +14,20 @@ * limitations under the License */ -package android.telephony.ims.internal.feature; +package android.telephony.ims.feature; import android.annotation.IntDef; +import android.net.Uri; +import android.os.Bundle; import android.os.Message; import android.os.RemoteException; import android.telecom.TelecomManager; -import android.telephony.ims.internal.aidl.IImsCapabilityCallback; -import android.telephony.ims.internal.aidl.IImsMmTelFeature; -import android.telephony.ims.internal.aidl.IImsMmTelListener; -import android.telephony.ims.internal.stub.SmsImplBase; +import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IImsMmTelFeature; +import android.telephony.ims.aidl.IImsMmTelListener; +import android.telephony.ims.aidl.IImsSmsListener; import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.telephony.ims.stub.ImsSmsImplBase; import android.telephony.ims.stub.ImsEcbmImplBase; import android.telephony.ims.stub.ImsMultiEndpointImplBase; import android.telephony.ims.stub.ImsUtImplBase; @@ -34,7 +37,6 @@ import com.android.ims.ImsCallProfile; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; -import com.android.ims.internal.IImsSmsListener; import com.android.ims.internal.IImsUt; import com.android.ims.internal.ImsCallSession; import com.android.internal.annotations.VisibleForTesting; @@ -88,6 +90,13 @@ public class MmTelFeature extends ImsFeature { } @Override + public int shouldProcessCall(String[] numbers) { + synchronized (mLock) { + return MmTelFeature.this.shouldProcessCall(numbers); + } + } + + @Override public IImsUt getUtInterface() throws RemoteException { synchronized (mLock) { return MmTelFeature.this.getUt(); @@ -199,6 +208,10 @@ public class MmTelFeature extends ImsFeature { mCapabilities = c.mCapabilities; } + public MmTelCapabilities(int capabilities) { + mCapabilities = capabilities; + } + @IntDef(flag = true, value = { CAPABILITY_TYPE_VOICE, @@ -243,6 +256,21 @@ public class MmTelFeature extends ImsFeature { public final boolean isCapable(@MmTelCapability int capabilities) { return super.isCapable(capabilities); } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("MmTel Capabilities - ["); + builder.append("Voice: "); + builder.append(isCapable(CAPABILITY_TYPE_VOICE)); + builder.append(" Video: "); + builder.append(isCapable(CAPABILITY_TYPE_VIDEO)); + builder.append(" UT: "); + builder.append(isCapable(CAPABILITY_TYPE_UT)); + builder.append(" SMS: "); + builder.append(isCapable(CAPABILITY_TYPE_SMS)); + builder.append("]"); + return builder.toString(); + } } /** @@ -250,9 +278,13 @@ public class MmTelFeature extends ImsFeature { */ public static class Listener extends IImsMmTelListener.Stub { + /** + * Called when the IMS provider receives an incoming call. + * @param c The {@link ImsCallSession} associated with the new call. + */ @Override - public final void onIncomingCall(IImsCallSession c) { - onIncomingCall(new ImsCallSession(c)); + public void onIncomingCall(IImsCallSession c, Bundle extras) { + } /** @@ -263,15 +295,34 @@ public class MmTelFeature extends ImsFeature { public void onVoiceMessageCountUpdate(int count) { } - - /** - * Called when the IMS provider receives an incoming call. - * @param c The {@link ImsCallSession} associated with the new call. - */ - public void onIncomingCall(ImsCallSession c) { - } } + /** + * To be returned by {@link #shouldProcessCall(Uri[])} when the ImsService should process the + * outgoing call as IMS. + */ + public static final int PROCESS_CALL_IMS = 0; + /** + * To be returned by {@link #shouldProcessCall(Uri[])} when the telephony framework should not + * process the outgoing NON_EMERGENCY call as IMS and should instead use circuit switch. + */ + public static final int PROCESS_CALL_CSFB = 1; + /** + * To be returned by {@link #shouldProcessCall(Uri[])} when the telephony framework should not + * process the outgoing EMERGENCY call as IMS and should instead use circuit switch. + */ + public static final int PROCESS_CALL_EMERGENCY_CSFB = 2; + + @IntDef(flag = true, + value = { + PROCESS_CALL_IMS, + PROCESS_CALL_CSFB, + PROCESS_CALL_EMERGENCY_CSFB + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProcessCallResult {} + + // Lock for feature synchronization private final Object mLock = new Object(); private IImsMmTelListener mListener; @@ -284,6 +335,9 @@ public class MmTelFeature extends ImsFeature { synchronized (mLock) { mListener = listener; } + if (mListener != null) { + onFeatureReady(); + } } private void queryCapabilityConfigurationInternal(int capability, int radioTech, @@ -332,12 +386,13 @@ public class MmTelFeature extends ImsFeature { * @throws RemoteException if the connection to the framework is not available. If this happens, * the call should be no longer considered active and should be cleaned up. * */ - protected final void notifyIncomingCall(ImsCallSession c) throws RemoteException { + protected final void notifyIncomingCall(ImsCallSession c, Bundle extras) + throws RemoteException { synchronized (mLock) { if (mListener == null) { throw new IllegalStateException("Session is not available."); } - mListener.onIncomingCall(c.getSession()); + mListener.onIncomingCall(c.getSession(), extras); } } @@ -409,6 +464,19 @@ public class MmTelFeature extends ImsFeature { } /** + * Called by the framework to determine if the outgoing call, designated by the outgoing + * {@link Uri}s, should be processed as an IMS call or CSFB call. + * @param numbers An array of {@link String}s that will be used for placing the call. There can + * be multiple {@link Strings}s listed in the case when we want to place an outgoing + * call as a conference. + * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the + * call wil lbe placed over IMS or via CSFB. + */ + public @ProcessCallResult int shouldProcessCall(String[] numbers) { + return PROCESS_CALL_IMS; + } + + /** * @return The Ut interface for the supplementary service configuration. */ public ImsUtImplBase getUt() { @@ -445,22 +513,22 @@ public class MmTelFeature extends ImsFeature { // Base Implementation - Should be overridden } - public void setSmsListener(IImsSmsListener listener) { + private void setSmsListener(IImsSmsListener listener) { getSmsImplementation().registerSmsListener(listener); } - public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, + private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, byte[] pdu) { getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu); } - public void acknowledgeSms(int token, int messageRef, - @SmsImplBase.DeliverStatusResult int result) { + private void acknowledgeSms(int token, int messageRef, + @ImsSmsImplBase.DeliverStatusResult int result) { getSmsImplementation().acknowledgeSms(token, messageRef, result); } - public void acknowledgeSmsReport(int token, int messageRef, - @SmsImplBase.StatusReportResult int result) { + private void acknowledgeSmsReport(int token, int messageRef, + @ImsSmsImplBase.StatusReportResult int result) { getSmsImplementation().acknowledgeSmsReport(token, messageRef, result); } @@ -468,11 +536,11 @@ public class MmTelFeature extends ImsFeature { * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default * non-functional implementation is returned. * - * @return an instance of {@link SmsImplBase} which should be implemented by the IMS + * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS * Provider. */ - public SmsImplBase getSmsImplementation() { - return new SmsImplBase(); + protected ImsSmsImplBase getSmsImplementation() { + return new ImsSmsImplBase(); } private String getSmsFormat() { diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 40c5181d6bca..3b6f7e0f1a89 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -16,7 +16,7 @@ package android.telephony.ims.feature; -import com.android.ims.internal.IImsRcsFeature; +import android.telephony.ims.aidl.IImsRcsFeature; /** * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend @@ -36,8 +36,9 @@ public class RcsFeature extends ImsFeature { } @Override - public void onFeatureReady() { - + public void changeEnabledCapabilities(CapabilityChangeRequest request, + CapabilityCallbackProxy c) { + // Do nothing for base implementation. } @Override @@ -45,6 +46,12 @@ public class RcsFeature extends ImsFeature { } + /**{@inheritDoc}*/ + @Override + public void onFeatureReady() { + + } + @Override public final IImsRcsFeature getBinder() { return mImsRcsBinder; diff --git a/telephony/java/android/telephony/ims/internal/ImsService.java b/telephony/java/android/telephony/ims/internal/ImsService.java deleted file mode 100644 index afaf33294d8a..000000000000 --- a/telephony/java/android/telephony/ims/internal/ImsService.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2017 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.internal; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.os.RemoteException; -import android.telephony.CarrierConfigManager; -import android.telephony.ims.internal.aidl.IImsConfig; -import android.telephony.ims.internal.aidl.IImsMmTelFeature; -import android.telephony.ims.internal.aidl.IImsRcsFeature; -import android.telephony.ims.internal.aidl.IImsServiceController; -import android.telephony.ims.internal.aidl.IImsServiceControllerListener; -import android.telephony.ims.internal.feature.ImsFeature; -import android.telephony.ims.internal.feature.MmTelFeature; -import android.telephony.ims.internal.feature.RcsFeature; -import android.telephony.ims.internal.stub.ImsConfigImplBase; -import android.telephony.ims.internal.stub.ImsFeatureConfiguration; -import android.telephony.ims.stub.ImsRegistrationImplBase; -import android.util.Log; -import android.util.SparseArray; - -import com.android.ims.internal.IImsFeatureStatusCallback; -import com.android.ims.internal.IImsRegistration; -import com.android.internal.annotations.VisibleForTesting; - -/** - * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend - * ImsService must register the service in their AndroidManifest to be detected by the framework. - * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE" - * permission. Then, the ImsService definition in the manifest must follow the following format: - * - * ... - * <service android:name=".EgImsService" - * android:permission="android.permission.BIND_IMS_SERVICE" > - * <!-- Apps must declare which features they support as metadata. The different categories are - * defined below. In this example, the RCS_FEATURE feature is supported. --> - * <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" /> - * <intent-filter> - * <action android:name="android.telephony.ims.ImsService" /> - * </intent-filter> - * </service> - * ... - * - * The telephony framework will then bind to the ImsService you have defined in your manifest - * if you are either: - * 1) Defined as the default ImsService for the device in the device overlay using - * "config_ims_package". - * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using - * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}. - * - * The features that are currently supported in an ImsService are: - * - RCS_FEATURE: This ImsService implements the RcsFeature class. - * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class. - * @hide - */ -public class ImsService extends Service { - - private static final String LOG_TAG = "ImsService"; - - /** - * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService. - * @hide - */ - public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService"; - - // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that - // slot. - // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and - // call ImsFeature#onFeatureRemoved. - private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>(); - - private IImsServiceControllerListener mListener; - - - /** - * Listener that notifies the framework of ImsService changes. - */ - public static class Listener extends IImsServiceControllerListener.Stub { - /** - * The IMS features that this ImsService supports has changed. - * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s - * that this ImsService supports. This may trigger the addition/removal of feature - * in this service. - */ - public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) { - } - } - - /** - * @hide - */ - protected final IBinder mImsServiceController = new IImsServiceController.Stub() { - @Override - public void setListener(IImsServiceControllerListener l) { - mListener = l; - } - - @Override - public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) { - return createMmTelFeatureInternal(slotId, c); - } - - @Override - public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) { - return createRcsFeatureInternal(slotId, c); - } - - @Override - public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c) - throws RemoteException { - ImsService.this.removeImsFeature(slotId, featureType, c); - } - - @Override - public ImsFeatureConfiguration querySupportedImsFeatures() { - return ImsService.this.querySupportedImsFeatures(); - } - - @Override - public void notifyImsServiceReadyForFeatureCreation() { - ImsService.this.readyForFeatureCreation(); - } - - @Override - public void notifyImsFeatureReady(int slotId, int featureType) - throws RemoteException { - ImsService.this.notifyImsFeatureReady(slotId, featureType); - } - - @Override - public IImsConfig getConfig(int slotId) throws RemoteException { - ImsConfigImplBase c = ImsService.this.getConfig(slotId); - return c != null ? c.getBinder() : null; - } - - @Override - public IImsRegistration getRegistration(int slotId) throws RemoteException { - ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId); - return r != null ? r.getBinder() : null; - } - }; - - /** - * @hide - */ - @Override - public IBinder onBind(Intent intent) { - if(SERVICE_INTERFACE.equals(intent.getAction())) { - Log.i(LOG_TAG, "ImsService Bound."); - return mImsServiceController; - } - return null; - } - - /** - * @hide - */ - @VisibleForTesting - public SparseArray<ImsFeature> getFeatures(int slotId) { - return mFeaturesBySlot.get(slotId); - } - - private IImsMmTelFeature createMmTelFeatureInternal(int slotId, - IImsFeatureStatusCallback c) { - MmTelFeature f = createMmTelFeature(slotId); - if (f != null) { - setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c); - return f.getBinder(); - } else { - Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned."); - return null; - } - } - - private IImsRcsFeature createRcsFeatureInternal(int slotId, - IImsFeatureStatusCallback c) { - RcsFeature f = createRcsFeature(slotId); - if (f != null) { - setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c); - return f.getBinder(); - } else { - Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned."); - return null; - } - } - - private void setupFeature(ImsFeature f, int slotId, int featureType, - IImsFeatureStatusCallback c) { - f.addImsFeatureStatusCallback(c); - f.initialize(this, slotId); - addImsFeature(slotId, featureType, f); - } - - private void addImsFeature(int slotId, int featureType, ImsFeature f) { - synchronized (mFeaturesBySlot) { - // Get SparseArray for Features, by querying slot Id - SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); - if (features == null) { - // Populate new SparseArray of features if it doesn't exist for this slot yet. - features = new SparseArray<>(); - mFeaturesBySlot.put(slotId, features); - } - features.put(featureType, f); - } - } - - private void removeImsFeature(int slotId, int featureType, - IImsFeatureStatusCallback c) { - synchronized (mFeaturesBySlot) { - // get ImsFeature associated with the slot/feature - SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); - if (features == null) { - Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot " - + slotId); - return; - } - ImsFeature f = features.get(featureType); - if (f == null) { - Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type " - + featureType + " exists on slot " + slotId); - return; - } - f.removeImsFeatureStatusCallback(c); - f.onFeatureRemoved(); - features.remove(featureType); - } - } - - private void notifyImsFeatureReady(int slotId, int featureType) { - synchronized (mFeaturesBySlot) { - // get ImsFeature associated with the slot/feature - SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); - if (features == null) { - Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " + - "slot " + slotId); - return; - } - ImsFeature f = features.get(featureType); - if (f == null) { - Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type " - + featureType + " exists on slot " + slotId); - return; - } - f.onFeatureReady(); - } - } - - /** - * When called, provide the {@link ImsFeatureConfiguration} that this ImsService currently - * supports. This will trigger the framework to set up the {@link ImsFeature}s that correspond - * to the {@link ImsFeature.FeatureType}s configured here. - * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports, - * defined in {@link ImsFeature.FeatureType}. - */ - public ImsFeatureConfiguration querySupportedImsFeatures() { - // Return empty for base implementation - return new ImsFeatureConfiguration(); - } - - /** - * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated - * features, defined in {@link ImsFeature.FeatureType} that this ImsService supports. This may - * trigger the framework to add/remove new ImsFeatures, depending on the configuration. - */ - public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) - throws RemoteException { - if (mListener == null) { - throw new IllegalStateException("Framework is not ready"); - } - mListener.onUpdateSupportedImsFeatures(c); - } - - /** - * 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 - * The ImsService should use this signal instead of onCreate/onBind or similar to perform - * feature initialization because the framework may bind to this service multiple times to - * query the ImsService's {@link ImsFeatureConfiguration} via - * {@link #querySupportedImsFeatures()}before creating features. - */ - public void readyForFeatureCreation() { - } - - /** - * When called, the framework is requesting that a new MmTelFeature is created for the specified - * slot. - * - * @param slotId The slot ID that the MMTel Feature is being created for. - * @return The newly created MmTelFeature associated with the slot or null if the feature is not - * supported. - */ - public MmTelFeature createMmTelFeature(int slotId) { - return null; - } - - /** - * When called, the framework is requesting that a new RcsFeature is created for the specified - * slot - * - * @param slotId The slot ID that the RCS Feature is being created for. - * @return The newly created RcsFeature associated with the slot or null if the feature is not - * supported. - */ - public RcsFeature createRcsFeature(int slotId) { - return null; - } - - /** - * @param slotId The slot that the IMS configuration is associated with. - * @return ImsConfig implementation that is associated with the specified slot. - */ - public ImsConfigImplBase getConfig(int slotId) { - return new ImsConfigImplBase(); - } - - /** - * @param slotId The slot that is associated with the IMS Registration. - * @return the ImsRegistration implementation associated with the slot. - */ - public ImsRegistrationImplBase getRegistration(int slotId) { - return new ImsRegistrationImplBase(); - } -} diff --git a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java b/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java deleted file mode 100644 index 9f82ad241eaf..000000000000 --- a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (C) 2017 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.internal.feature; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.content.Context; -import android.content.Intent; -import android.os.IInterface; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.telephony.SubscriptionManager; -import android.telephony.ims.internal.aidl.IImsCapabilityCallback; -import android.util.Log; - -import com.android.ims.internal.IImsFeatureStatusCallback; -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; -import java.util.WeakHashMap; - -/** - * Base class for all IMS features that are supported by the framework. - * - * @hide - */ -public abstract class ImsFeature { - - private static final String LOG_TAG = "ImsFeature"; - - /** - * Action to broadcast when ImsService is up. - * Internal use only. - * Only defined here separately for compatibility purposes with the old ImsService. - * - * @hide - */ - public static final String ACTION_IMS_SERVICE_UP = - "com.android.ims.IMS_SERVICE_UP"; - - /** - * Action to broadcast when ImsService is down. - * Internal use only. - * Only defined here separately for compatibility purposes with the old ImsService. - * - * @hide - */ - public static final String ACTION_IMS_SERVICE_DOWN = - "com.android.ims.IMS_SERVICE_DOWN"; - - /** - * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents. - * A long value; the phone ID corresponding to the IMS service coming up or down. - * Only defined here separately for compatibility purposes with the old ImsService. - * - * @hide - */ - public static final String EXTRA_PHONE_ID = "android:phone_id"; - - // Invalid feature value - public static final int FEATURE_INVALID = -1; - // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously - // defined values in ImsServiceClass for compatibility purposes. - public static final int FEATURE_EMERGENCY_MMTEL = 0; - public static final int FEATURE_MMTEL = 1; - public static final int FEATURE_RCS = 2; - // Total number of features defined - public static final int FEATURE_MAX = 3; - - // Integer values defining IMS features that are supported in ImsFeature. - @IntDef(flag = true, - value = { - FEATURE_EMERGENCY_MMTEL, - FEATURE_MMTEL, - FEATURE_RCS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface FeatureType {} - - // Integer values defining the state of the ImsFeature at any time. - @IntDef(flag = true, - value = { - STATE_UNAVAILABLE, - STATE_INITIALIZING, - STATE_READY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ImsState {} - - public static final int STATE_UNAVAILABLE = 0; - public static final int STATE_INITIALIZING = 1; - public static final int STATE_READY = 2; - - // Integer values defining the result codes that should be returned from - // {@link changeEnabledCapabilities} when the framework tries to set a feature's capability. - @IntDef(flag = true, - value = { - CAPABILITY_ERROR_GENERIC, - CAPABILITY_SUCCESS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ImsCapabilityError {} - - public static final int CAPABILITY_ERROR_GENERIC = -1; - public static final int CAPABILITY_SUCCESS = 0; - - - /** - * The framework implements this callback in order to register for Feature Capability status - * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability - * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error - * callbacks when the ImsService can not change the capability as requested, via - * {@link #onChangeCapabilityConfigurationError}. - */ - public static class CapabilityCallback extends IImsCapabilityCallback.Stub { - - @Override - public final void onCapabilitiesStatusChanged(int config) throws RemoteException { - onCapabilitiesStatusChanged(new Capabilities(config)); - } - - /** - * Returns the result of a query for the capability configuration of a requested capability. - * - * @param capability The capability that was requested. - * @param radioTech The IMS radio technology associated with the capability. - * @param isEnabled true if the capability is enabled, false otherwise. - */ - @Override - public void onQueryCapabilityConfiguration(int capability, int radioTech, - boolean isEnabled) { - - } - - /** - * Called when a change to the capability configuration has returned an error. - * - * @param capability The capability that was requested to be changed. - * @param radioTech The IMS radio technology associated with the capability. - * @param reason error associated with the failure to change configuration. - */ - @Override - public void onChangeCapabilityConfigurationError(int capability, int radioTech, - int reason) { - } - - /** - * The status of the feature's capabilities has changed to either available or unavailable. - * If unavailable, the feature is not able to support the unavailable capability at this - * time. - * - * @param config The new availability of the capabilities. - */ - public void onCapabilitiesStatusChanged(Capabilities config) { - } - } - - /** - * Used by the ImsFeature to call back to the CapabilityCallback that the framework has - * provided. - */ - protected static class CapabilityCallbackProxy { - private final IImsCapabilityCallback mCallback; - - public CapabilityCallbackProxy(IImsCapabilityCallback c) { - mCallback = c; - } - - /** - * This method notifies the provided framework callback that the request to change the - * indicated capability has failed and has not changed. - * - * @param capability The Capability that will be notified to the framework. - * @param radioTech The radio tech that this capability failed for. - * @param reason The reason this capability was unable to be changed. - */ - public void onChangeCapabilityConfigurationError(int capability, int radioTech, - @ImsCapabilityError int reason) { - try { - mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason); - } catch (RemoteException e) { - Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder."); - } - } - - public void onQueryCapabilityConfiguration(int capability, int radioTech, - boolean isEnabled) { - try { - mCallback.onQueryCapabilityConfiguration(capability, radioTech, isEnabled); - } catch (RemoteException e) { - Log.e(LOG_TAG, "onQueryCapabilityConfiguration called on dead binder."); - } - } - } - - /** - * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask. - */ - public static class Capabilities { - protected int mCapabilities = 0; - - public Capabilities() { - } - - protected Capabilities(int capabilities) { - mCapabilities = capabilities; - } - - /** - * @param capabilities Capabilities to be added to the configuration in the form of a - * bit mask. - */ - public void addCapabilities(int capabilities) { - mCapabilities |= capabilities; - } - - /** - * @param capabilities Capabilities to be removed to the configuration in the form of a - * bit mask. - */ - public void removeCapabilities(int capabilities) { - mCapabilities &= ~capabilities; - } - - /** - * @return true if all of the capabilities specified are capable. - */ - public boolean isCapable(int capabilities) { - return (mCapabilities & capabilities) == capabilities; - } - - public Capabilities copy() { - return new Capabilities(mCapabilities); - } - - /** - * @return a bitmask containing the capability flags directly. - */ - public int getMask() { - return mCapabilities; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Capabilities)) return false; - - Capabilities that = (Capabilities) o; - - return mCapabilities == that.mCapabilities; - } - - @Override - public int hashCode() { - return mCapabilities; - } - } - - private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap( - new WeakHashMap<IImsFeatureStatusCallback, Boolean>()); - private @ImsState int mState = STATE_UNAVAILABLE; - private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; - private Context mContext; - private final Object mLock = new Object(); - private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks - = new RemoteCallbackList<>(); - private Capabilities mCapabilityStatus = new Capabilities(); - - public final void initialize(Context context, int slotId) { - mContext = context; - mSlotId = slotId; - } - - public final int getFeatureState() { - synchronized (mLock) { - return mState; - } - } - - protected final void setFeatureState(@ImsState int state) { - synchronized (mLock) { - if (mState != state) { - mState = state; - notifyFeatureState(state); - } - } - } - - // Not final for testing, but shouldn't be extended! - @VisibleForTesting - public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) { - try { - // If we have just connected, send queued status. - c.notifyImsFeatureStatus(getFeatureState()); - // Add the callback if the callback completes successfully without a RemoteException. - synchronized (mLock) { - mStatusCallbacks.add(c); - } - } catch (RemoteException e) { - Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); - } - } - - @VisibleForTesting - // Not final for testing, but should not be extended! - public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) { - synchronized (mLock) { - mStatusCallbacks.remove(c); - } - } - - /** - * Internal method called by ImsFeature when setFeatureState has changed. - */ - private void notifyFeatureState(@ImsState int state) { - synchronized (mLock) { - for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator(); - iter.hasNext(); ) { - IImsFeatureStatusCallback callback = iter.next(); - try { - Log.i(LOG_TAG, "notifying ImsFeatureState=" + state); - callback.notifyImsFeatureStatus(state); - } catch (RemoteException e) { - // remove if the callback is no longer alive. - iter.remove(); - Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); - } - } - } - sendImsServiceIntent(state); - } - - /** - * Provide backwards compatibility using deprecated service UP/DOWN intents. - */ - private void sendImsServiceIntent(@ImsState int state) { - if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { - return; - } - Intent intent; - switch (state) { - case ImsFeature.STATE_UNAVAILABLE: - case ImsFeature.STATE_INITIALIZING: - intent = new Intent(ACTION_IMS_SERVICE_DOWN); - break; - case ImsFeature.STATE_READY: - intent = new Intent(ACTION_IMS_SERVICE_UP); - break; - default: - intent = new Intent(ACTION_IMS_SERVICE_DOWN); - } - intent.putExtra(EXTRA_PHONE_ID, mSlotId); - mContext.sendBroadcast(intent); - } - - public final void addCapabilityCallback(IImsCapabilityCallback c) { - mCapabilityCallbacks.register(c); - } - - public final void removeCapabilityCallback(IImsCapabilityCallback c) { - mCapabilityCallbacks.unregister(c); - } - - /** - * @return the cached capabilities status for this feature. - */ - @VisibleForTesting - public Capabilities queryCapabilityStatus() { - synchronized (mLock) { - return mCapabilityStatus.copy(); - } - } - - // Called internally to request the change of enabled capabilities. - @VisibleForTesting - public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request, - IImsCapabilityCallback c) throws RemoteException { - if (request == null) { - throw new IllegalArgumentException( - "ImsFeature#requestChangeEnabledCapabilities called with invalid params."); - } - changeEnabledCapabilities(request, new CapabilityCallbackProxy(c)); - } - - /** - * Called by the ImsFeature when the capabilities status has changed. - * - * @param c A {@link Capabilities} containing the new Capabilities status. - */ - protected final void notifyCapabilitiesStatusChanged(Capabilities c) { - synchronized (mLock) { - mCapabilityStatus = c.copy(); - } - int count = mCapabilityCallbacks.beginBroadcast(); - try { - for (int i = 0; i < count; i++) { - try { - mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged( - c.mCapabilities); - } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " + - "callback."); - } - } - } finally { - mCapabilityCallbacks.finishBroadcast(); - } - } - - /** - * Features should override this method to receive Capability preference change requests from - * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities - * in the {@link CapabilityChangeRequest} are not able to be completed due to an error, - * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for - * each failed capability. - * - * @param request A {@link CapabilityChangeRequest} containing requested capabilities to - * enable/disable. - * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework - * setting a subset of these capabilities fail, using - * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}. - */ - public abstract void changeEnabledCapabilities(CapabilityChangeRequest request, - CapabilityCallbackProxy c); - - /** - * Called when the framework is removing this feature and it needs to be cleaned up. - */ - public abstract void onFeatureRemoved(); - - /** - * Called when the feature has been initialized and communication with the framework is set up. - * Any attempt by this feature to access the framework before this method is called will return - * with an {@link IllegalStateException}. - * The IMS provider should use this method to trigger registration for this feature on the IMS - * network, if needed. - */ - public abstract void onFeatureReady(); - - /** - * @return Binder instance that the framework will use to communicate with this feature. - */ - protected abstract IInterface getBinder(); -} diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java deleted file mode 100644 index 33aec5dfb8af..000000000000 --- a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2017 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.internal.stub; - -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.telephony.ims.internal.aidl.IImsConfig; -import android.telephony.ims.internal.aidl.IImsConfigCallback; - -import com.android.ims.ImsConfig; - -/** - * Controls the modification of IMS specific configurations. For more information on the supported - * IMS configuration constants, see {@link ImsConfig}. - * - * @hide - */ - -public class ImsConfigImplBase { - - //TODO: Implement the Binder logic to call base APIs. Need to finish other ImsService Config - // work first. - private final IImsConfig mBinder = new IImsConfig.Stub() { - - @Override - public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException { - ImsConfigImplBase.this.addImsConfigCallback(c); - } - - @Override - public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException { - ImsConfigImplBase.this.removeImsConfigCallback(c); - } - - @Override - public int getConfigInt(int item) throws RemoteException { - return Integer.MIN_VALUE; - } - - @Override - public String getConfigString(int item) throws RemoteException { - return null; - } - - @Override - public int setConfigInt(int item, int value) throws RemoteException { - return Integer.MIN_VALUE; - } - - @Override - public int setConfigString(int item, String value) throws RemoteException { - return Integer.MIN_VALUE; - } - }; - - public class Callback extends IImsConfigCallback.Stub { - - @Override - public final void onIntConfigChanged(int item, int value) throws RemoteException { - onConfigChanged(item, value); - } - - @Override - public final void onStringConfigChanged(int item, String value) throws RemoteException { - onConfigChanged(item, value); - } - - /** - * Called when the IMS configuration has changed. - * @param item the IMS configuration key constant, as defined in ImsConfig. - * @param value the new integer value of the IMS configuration constant. - */ - public void onConfigChanged(int item, int value) { - // Base Implementation - } - - /** - * Called when the IMS configuration has changed. - * @param item the IMS configuration key constant, as defined in ImsConfig. - * @param value the new String value of the IMS configuration constant. - */ - public void onConfigChanged(int item, String value) { - // Base Implementation - } - } - - private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>(); - - /** - * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration - * changes. - * @param c callback to add. - */ - private void addImsConfigCallback(IImsConfigCallback c) { - mCallbacks.register(c); - } - /** - * Removes a {@link Callback} to the list of callbacks notified when a value in the - * configuration changes. - * - * @param c callback to remove. - */ - private void removeImsConfigCallback(IImsConfigCallback c) { - mCallbacks.unregister(c); - } - - public final IImsConfig getBinder() { - return mBinder; - } - - /** - * Sets the value for IMS service/capabilities parameters by the operator device - * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. - * - * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. - * @param value in Integer format. - * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. - */ - public int setConfig(int item, int value) { - // Base Implementation - To be overridden. - return ImsConfig.OperationStatusConstants.FAILED; - } - - /** - * Sets the value for IMS service/capabilities parameters by the operator device - * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. - * - * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. - * @param value in String format. - * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. - */ - public int setConfig(int item, String value) { - return ImsConfig.OperationStatusConstants.FAILED; - } - - /** - * Gets the value for ims service/capabilities parameters from the provisioned - * value storage. - * - * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. - * @return value in Integer format. - */ - public int getConfigInt(int item) { - return ImsConfig.OperationStatusConstants.FAILED; - } - - /** - * Gets the value for ims service/capabilities parameters from the provisioned - * value storage. - * - * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. - * @return value in String format. - */ - public String getConfigString(int item) { - return null; - } -} diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 5a4db99ee0d0..ab249dac50f8 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -16,135 +16,370 @@ package android.telephony.ims.stub; +import android.content.Context; +import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.aidl.IImsConfigCallback; +import android.util.Log; import com.android.ims.ImsConfig; -import com.android.ims.ImsConfigListener; -import com.android.ims.internal.IImsConfig; +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.ref.WeakReference; +import java.util.HashMap; /** - * Base implementation of ImsConfig, which implements stub versions of the methods - * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports. - * - * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you - * will break other implementations of ImsConfig maintained by other ImsServices. - * - * Provides APIs to get/set the IMS service feature/capability/parameters. - * The config items include: - * 1) Items provisioned by the operator. - * 2) Items configured by user. Mainly service feature class. + * Controls the modification of IMS specific configurations. For more information on the supported + * IMS configuration constants, see {@link ImsConfig}. * + * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface. + * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes. + * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in + * during initialization, or times when a lot of configuration parameters are being set/get + * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed + * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be + * performed every time. * @hide */ -public class ImsConfigImplBase extends IImsConfig.Stub { +public class ImsConfigImplBase { + + static final private String TAG = "ImsConfigImplBase"; /** - * Gets the value for ims service/capabilities parameters from the provisioned - * value storage. Synchronous blocking call. + * Implements the IImsConfig AIDL interface, which is called by potentially many processes + * in order to get/set configuration parameters. * - * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. - * @return value in Integer format. + * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl + * with actual implementations from vendors. This class caches provisioned values from + * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in, + * it first checks cache layer. If missed, it will call the vendor implementation of + * ImsConfigImplBase API. + * and cache the return value if the set succeeds. + * + * Provides APIs to get/set the IMS service feature/capability/parameters. + * The config items include: + * 1) Items provisioned by the operator. + * 2) Items configured by user. Mainly service feature class. + * + * @hide */ - @Override - public int getProvisionedValue(int item) throws RemoteException { - return -1; + @VisibleForTesting + static public class ImsConfigStub extends IImsConfig.Stub { + WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference; + private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>(); + private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>(); + + @VisibleForTesting + public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) { + mImsConfigImplBaseWeakReference = + new WeakReference<ImsConfigImplBase>(imsConfigImplBase); + } + + @Override + public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException { + getImsConfigImpl().addImsConfigCallback(c); + } + + @Override + public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException { + getImsConfigImpl().removeImsConfigCallback(c); + } + + /** + * Gets the value for ims service/capabilities parameters. It first checks its local cache, + * if missed, it will call ImsConfigImplBase.getProvisionedValue. + * Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in Integer format. + */ + @Override + public synchronized int getConfigInt(int item) throws RemoteException { + if (mProvisionedIntValue.containsKey(item)) { + return mProvisionedIntValue.get(item); + } else { + int retVal = getImsConfigImpl().getConfigInt(item); + if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) { + updateCachedValue(item, retVal, false); + } + return retVal; + } + } + + /** + * Gets the value for ims service/capabilities parameters. It first checks its local cache, + * if missed, it will call #ImsConfigImplBase.getProvisionedValue. + * Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in String format. + */ + @Override + public synchronized String getConfigString(int item) throws RemoteException { + if (mProvisionedIntValue.containsKey(item)) { + return mProvisionedStringValue.get(item); + } else { + String retVal = getImsConfigImpl().getConfigString(item); + if (retVal != null) { + updateCachedValue(item, retVal, false); + } + return retVal; + } + } + + /** + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived, and write it into local cache. + * Synchronous blocking call. + * + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in Integer format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + */ + @Override + public synchronized int setConfigInt(int item, int value) throws RemoteException { + mProvisionedIntValue.remove(item); + int retVal = getImsConfigImpl().setConfig(item, value); + if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { + updateCachedValue(item, retVal, true); + } else { + Log.d(TAG, "Set provision value of " + item + + " to " + value + " failed with error code " + retVal); + } + + return retVal; + } + + /** + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived, and write it into local cache. + * Synchronous blocking call. + * + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in String format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + */ + @Override + public synchronized int setConfigString(int item, String value) + throws RemoteException { + mProvisionedStringValue.remove(item); + int retVal = getImsConfigImpl().setConfig(item, value); + if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { + updateCachedValue(item, retVal, true); + } + + return retVal; + } + + private ImsConfigImplBase getImsConfigImpl() throws RemoteException { + ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get(); + if (ref == null) { + throw new RemoteException("Fail to get ImsConfigImpl"); + } else { + return ref; + } + } + + private void notifyImsConfigChanged(int item, int value) throws RemoteException { + getImsConfigImpl().notifyConfigChanged(item, value); + } + + private void notifyImsConfigChanged(int item, String value) throws RemoteException { + getImsConfigImpl().notifyConfigChanged(item, value); + } + + protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) + throws RemoteException { + mProvisionedIntValue.put(item, value); + if (notifyChange) { + notifyImsConfigChanged(item, value); + } + } + + protected synchronized void updateCachedValue(int item, String value, + boolean notifyChange) throws RemoteException { + mProvisionedStringValue.put(item, value); + if (notifyChange) { + notifyImsConfigChanged(item, value); + } + } } /** - * Gets the value for ims service/capabilities parameters from the provisioned - * value storage. Synchronous blocking call. - * - * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. - * @return value in String format. + * Callback that the framework uses for receiving Configuration change updates. + * {@hide} */ - @Override - public String getProvisionedStringValue(int item) throws RemoteException { - return null; + public static class Callback extends IImsConfigCallback.Stub { + + @Override + public final void onIntConfigChanged(int item, int value) throws RemoteException { + onConfigChanged(item, value); + } + + @Override + public final void onStringConfigChanged(int item, String value) throws RemoteException { + onConfigChanged(item, value); + } + + /** + * Called when the IMS configuration has changed. + * @param item the IMS configuration key constant, as defined in ImsConfig. + * @param value the new integer value of the IMS configuration constant. + */ + public void onConfigChanged(int item, int value) { + // Base Implementation + } + + /** + * Called when the IMS configuration has changed. + * @param item the IMS configuration key constant, as defined in ImsConfig. + * @param value the new String value of the IMS configuration constant. + */ + public void onConfigChanged(int item, String value) { + // Base Implementation + } + } + + private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>(); + ImsConfigStub mImsConfigStub; + + public ImsConfigImplBase(Context context) { + mImsConfigStub = new ImsConfigStub(this); + } + public ImsConfigImplBase() { + mImsConfigStub = new ImsConfigStub(this); } /** - * Sets the value for IMS service/capabilities parameters by the operator device - * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration + * changes. + * @param c callback to add. + */ + private void addImsConfigCallback(IImsConfigCallback c) { + mCallbacks.register(c); + } + /** + * Removes a {@link Callback} to the list of callbacks notified when a value in the + * configuration changes. * - * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. - * @param value in Integer format. - * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @param c callback to remove. */ - @Override - public int setProvisionedValue(int item, int value) throws RemoteException { - return ImsConfig.OperationStatusConstants.FAILED; + private void removeImsConfigCallback(IImsConfigCallback c) { + mCallbacks.unregister(c); + } + + void notifyConfigChanged(int item, int value) { + // can be null in testing + if (mCallbacks == null) { + return; + } + mCallbacks.broadcast(c -> { + try { + c.onIntConfigChanged(item, value); + } catch (RemoteException e) { + Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping."); + } + }); + } + + private void notifyConfigChanged(int item, String value) { + // can be null in testing + if (mCallbacks == null) { + return; + } + mCallbacks.broadcast(c -> { + try { + c.onStringConfigChanged(item, value); + } catch (RemoteException e) { + Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping."); + } + }); } + public IImsConfig getIImsConfig() { return mImsConfigStub; } + /** - * Sets the value for IMS service/capabilities parameters by the operator device - * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * Updates provisioning value and notifies the framework of the change. + * Doesn't call #setProvisionedValue and assumes the result succeeded. + * This should only be used by modem when they implicitly changed provisioned values. * - * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. - * @param value in String format. - * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in Integer format. */ - @Override - public int setProvisionedStringValue(int item, String value) throws RemoteException { - return ImsConfig.OperationStatusConstants.FAILED; + public final void notifyProvisionedValueChanged(int item, int value) { + try { + mImsConfigStub.updateCachedValue(item, value, true); + } catch (RemoteException e) { + Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead."); + } } /** - * Gets the value of the specified IMS feature item for specified network type. - * This operation gets the feature config value from the master storage (i.e. final - * value). Asynchronous non-blocking call. + * Updates provisioning value and notifies the framework of the change. + * Doesn't call #setProvisionedValue and assumes the result succeeded. + * This should only be used by modem when they implicitly changed provisioned values. * - * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. - * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. - * @param listener feature value returned asynchronously through listener. + * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in String format. */ - @Override - public void getFeatureValue(int feature, int network, ImsConfigListener listener) - throws RemoteException { + public final void notifyProvisionedValueChanged(int item, String value) { + try { + mImsConfigStub.updateCachedValue(item, value, true); + } catch (RemoteException e) { + Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead."); + } } /** - * Sets the value for IMS feature item for specified network type. - * This operation stores the user setting in setting db from which master db - * is derived. + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived. * - * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. - * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. - * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants. - * @param listener, provided if caller needs to be notified for set result. + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in Integer format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. */ - @Override - public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) - throws RemoteException { + public int setConfig(int item, int value) { + // Base Implementation - To be overridden. + return ImsConfig.OperationStatusConstants.FAILED; } /** - * Gets the value for IMS VoLTE provisioned. - * This should be the same as the operator provisioned value if applies. + * Sets the value for IMS service/capabilities parameters by the operator device + * management entity. It sets the config item value in the provisioned storage + * from which the master value is derived. + * + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @param value in String format. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. */ - @Override - public boolean getVolteProvisioned() throws RemoteException { - return false; + public int setConfig(int item, String value) { + return ImsConfig.OperationStatusConstants.FAILED; } /** - * Gets the value for IMS feature item video quality. + * Gets the value for ims service/capabilities parameters from the provisioned + * value storage. * - * @param listener Video quality value returned asynchronously through listener. + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in Integer format. */ - @Override - public void getVideoQuality(ImsConfigListener listener) throws RemoteException { + public int getConfigInt(int item) { + return ImsConfig.OperationStatusConstants.FAILED; } /** - * Sets the value for IMS feature item video quality. + * Gets the value for ims service/capabilities parameters from the provisioned + * value storage. * - * @param quality, defines the value of video quality. - * @param listener, provided if caller needs to be notified for set result. + * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. + * @return value in String format. */ - @Override - public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException { + public String getConfigString(int item) { + return null; } -} +}
\ No newline at end of file diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl index e890cf8756f3..e2ae0e8f6775 100644 --- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl +++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl @@ -14,6 +14,6 @@ * limitations under the License */ -package android.telephony.ims.internal.stub; +package android.telephony.ims.stub; parcelable ImsFeatureConfiguration; diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java index 244c9578f6b4..c8989e059ee5 100644 --- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java +++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -14,14 +14,13 @@ * limitations under the License */ -package android.telephony.ims.internal.stub; +package android.telephony.ims.stub; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.ims.internal.feature.ImsFeature; +import android.telephony.ims.feature.ImsFeature; import android.util.ArraySet; -import java.util.Arrays; import java.util.Set; /** @@ -135,7 +134,8 @@ public class ImsFeatureConfiguration implements Parcelable { if (this == o) return true; if (!(o instanceof ImsFeatureConfiguration)) return false; - ImsFeatureConfiguration that = (ImsFeatureConfiguration) o; + ImsFeatureConfiguration + that = (ImsFeatureConfiguration) o; return mFeatures.equals(that.mFeatures); } diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 42af08365f61..dfb9b63f7b14 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -18,14 +18,13 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.net.Uri; -import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.telephony.ims.aidl.IImsRegistration; +import android.telephony.ims.aidl.IImsRegistrationCallback; import android.util.Log; import com.android.ims.ImsReasonInfo; -import com.android.ims.internal.IImsRegistration; -import com.android.ims.internal.IImsRegistrationCallback; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java index 57df526b4a4e..9b9301193f1b 100644 --- a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java @@ -14,17 +14,16 @@ * limitations under the License */ -package android.telephony.ims.internal.stub; +package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.RemoteException; import android.telephony.SmsManager; import android.telephony.SmsMessage; +import android.telephony.ims.aidl.IImsSmsListener; import android.util.Log; -import com.android.ims.internal.IImsSmsListener; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -37,7 +36,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi -public class SmsImplBase { +public class ImsSmsImplBase { private static final String LOG_TAG = "SmsImplBase"; /** @hide */ diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index cf4c47bf541f..f8e8b48fbd5d 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -19,8 +19,8 @@ package com.android.ims; import android.content.Context; import android.os.RemoteException; import android.telephony.Rlog; - -import com.android.ims.internal.IImsConfig; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.stub.ImsConfigImplBase; /** * Provides APIs to get/set the IMS service feature/capability/parameters. @@ -46,7 +46,7 @@ public class ImsConfig { /** * Broadcast action: the configuration was changed - * + * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead. * @hide */ public static final String ACTION_IMS_CONFIG_CHANGED = @@ -70,6 +70,8 @@ public class ImsConfig { /** * Defines IMS service/capability feature constants. + * @deprecated Use + * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability} instead. */ public static class FeatureConstants { public static final int FEATURE_TYPE_UNKNOWN = -1; @@ -539,162 +541,164 @@ public class ImsConfig { } public ImsConfig(IImsConfig iconfig, Context context) { - if (DBG) Rlog.d(TAG, "ImsConfig creates"); + if (DBG) Rlog.d(TAG, "ImsConfig created"); miConfig = iconfig; mContext = context; } /** - * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack. - * This function should not be called from the mainthread as it could block the - * mainthread. + * @deprecated see {@link #getInt(int)} instead. + */ + public int getProvisionedValue(int item) throws ImsException { + return getConfigInt(item); + } + + /** + * Gets the configuration value for IMS service/capabilities parameters used by IMS stack. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @return the value in Integer format. - * - * @throws ImsException if calling the IMS service results in an error. + * @throws ImsException if the ImsService is unavailable. */ - public int getProvisionedValue(int item) throws ImsException { + public int getConfigInt(int item) throws ImsException { int ret = 0; try { - ret = miConfig.getProvisionedValue(item); + ret = miConfig.getConfigInt(item); } catch (RemoteException e) { - throw new ImsException("getValue()", e, + throw new ImsException("getInt()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } - if (DBG) Rlog.d(TAG, "getProvisionedValue(): item = " + item + ", ret =" + ret); + if (DBG) Rlog.d(TAG, "getInt(): item = " + item + ", ret =" + ret); return ret; } /** - * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack. - * This function should not be called from the mainthread as it could block the - * mainthread. + * @deprecated see {@link #getConfigString(int)} instead + */ + public String getProvisionedStringValue(int item) throws ImsException { + return getConfigString(item); + } + + /** + * Gets the configuration value for IMS service/capabilities parameters used by IMS stack. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @return value in String format. * - * @throws ImsException if calling the IMS service results in an error. + * @throws ImsException if the ImsService is unavailable. */ - public String getProvisionedStringValue(int item) throws ImsException { + public String getConfigString(int item) throws ImsException { String ret = "Unknown"; try { - ret = miConfig.getProvisionedStringValue(item); + ret = miConfig.getConfigString(item); } catch (RemoteException e) { - throw new ImsException("getProvisionedStringValue()", e, + throw new ImsException("getConfigString()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } - if (DBG) Rlog.d(TAG, "getProvisionedStringValue(): item = " + item + ", ret =" + ret); + if (DBG) Rlog.d(TAG, "getConfigString(): item = " + item + ", ret =" + ret); return ret; } /** - * Sets the value for IMS service/capabilities parameters by - * the operator device management entity. - * This function should not be called from main thread as it could block - * mainthread. + * @deprecated see {@link #setConfig(int, int)} instead. + */ + public int setProvisionedValue(int item, int value) throws ImsException { + return setConfig(item, value); + } + + /** + * @deprecated see {@link #setConfig(int, String)} instead. + */ + public int setProvisionedStringValue(int item, String value) throws ImsException { + return setConfig(item, value); + } + + /** + * Sets the value for ImsService configuration item. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in Integer format. * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants * - * @throws ImsException if calling the IMS service results in an error. + * @throws ImsException if the ImsService is unavailable. */ - public int setProvisionedValue(int item, int value) - throws ImsException { + public int setConfig(int item, int value) throws ImsException { int ret = OperationStatusConstants.UNKNOWN; if (DBG) { - Rlog.d(TAG, "setProvisionedValue(): item = " + item + + Rlog.d(TAG, "setConfig(): item = " + item + "value = " + value); } try { - ret = miConfig.setProvisionedValue(item, value); + ret = miConfig.setConfigInt(item, value); } catch (RemoteException e) { - throw new ImsException("setProvisionedValue()", e, + throw new ImsException("setConfig()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } if (DBG) { - Rlog.d(TAG, "setProvisionedValue(): item = " + item + + Rlog.d(TAG, "setConfig(): item = " + item + " value = " + value + " ret = " + ret); } return ret; + } /** - * Sets the value for IMS service/capabilities parameters by - * the operator device management entity. - * This function should not be called from main thread as it could block - * mainthread. + * Sets the value for ImsService configuration item. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. - * @param value in String format. + * @param value in Integer format. * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants * - * @throws ImsException if calling the IMS service results in an error. + * @throws ImsException if the ImsService is unavailable. */ - public int setProvisionedStringValue(int item, String value) - throws ImsException { + public int setConfig(int item, String value) throws ImsException { int ret = OperationStatusConstants.UNKNOWN; + if (DBG) { + Rlog.d(TAG, "setConfig(): item = " + item + + "value = " + value); + } try { - ret = miConfig.setProvisionedStringValue(item, value); + ret = miConfig.setConfigString(item, value); } catch (RemoteException e) { - throw new ImsException("setProvisionedStringValue()", e, + throw new ImsException("setConfig()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } if (DBG) { - Rlog.d(TAG, "setProvisionedStringValue(): item = " + item + - ", value =" + value); + Rlog.d(TAG, "setConfig(): item = " + item + + " value = " + value + " ret = " + ret); } return ret; } /** - * Gets the value for IMS feature item for specified network type. + * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration + * item has changed. * - * @param feature, defined as in FeatureConstants. - * @param network, defined as in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. - * @param listener, provided to be notified for the feature on/off status. - * @return void - * - * @throws ImsException if calling the IMS service results in an error. + * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished + * using this callback. */ - public void getFeatureValue(int feature, int network, - ImsConfigListener listener) throws ImsException { - if (DBG) { - Rlog.d(TAG, "getFeatureValue: feature = " + feature + ", network =" + network + - ", listener =" + listener); - } + public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException { + if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback); try { - miConfig.getFeatureValue(feature, network, listener); - } catch (RemoteException e) { - throw new ImsException("getFeatureValue()", e, + miConfig.addImsConfigCallback(callback); + } catch (RemoteException e) { + throw new ImsException("addConfigCallback()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } } /** - * Sets the value for IMS feature item for specified network type. - * - * @param feature, as defined in FeatureConstants. - * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. - * @param value, as defined in FeatureValueConstants. - * @param listener, provided if caller needs to be notified for set result. - * @return void - * - * @throws ImsException if calling the IMS service results in an error. + * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added + * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}. */ - public void setFeatureValue(int feature, int network, int value, - ImsConfigListener listener) throws ImsException { - if (DBG) { - Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network + - ", value =" + value + ", listener =" + listener); - } + public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException { + if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback); try { - miConfig.setFeatureValue(feature, network, value, listener); - } catch (RemoteException e) { - throw new ImsException("setFeatureValue()", e, + miConfig.removeImsConfigCallback(callback); + } catch (RemoteException e) { + throw new ImsException("removeConfigCallback()", e, ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } } diff --git a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl deleted file mode 100644 index 41b1042e9a86..000000000000 --- a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2017 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 com.android.ims.internal; - -/** -* Interface from ImsFeature in the ImsService to ImsServiceController. - * {@hide} - */ -oneway interface IImsFeatureStatusCallback { - void notifyImsFeatureStatus(int featureStatus); -}
\ No newline at end of file diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl index 290a68240251..d43077bf10bc 100644 --- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl +++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl @@ -24,7 +24,6 @@ import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsRegistrationListener; -import com.android.ims.internal.IImsSmsListener; import com.android.ims.internal.IImsUt; import android.os.Message; @@ -52,12 +51,4 @@ interface IImsMMTelFeature { IImsEcbm getEcbmInterface(); void setUiTTYMode(int uiTtyMode, in Message onComplete); IImsMultiEndpoint getMultiEndpointInterface(); - // SMS APIs - void setSmsListener(IImsSmsListener l); - oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry, - in byte[] pdu); - oneway void acknowledgeSms(int token, int messageRef, int result); - oneway void acknowledgeSmsReport(int token, int messageRef, int result); - String getSmsFormat(); - oneway void onSmsReady(); } diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl index 7ac25ac13fbe..857089fac33a 100644 --- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl +++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl @@ -18,7 +18,6 @@ package com.android.ims.internal; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsMMTelFeature; -import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsRcsFeature; /** @@ -30,5 +29,4 @@ interface IImsServiceController { IImsMMTelFeature createMMTelFeature(int slotId, in IImsFeatureStatusCallback c); IImsRcsFeature createRcsFeature(int slotId, in IImsFeatureStatusCallback c); void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c); - IImsRegistration getRegistration(int slotId); } diff --git a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java index 80958c077d6a..f323a0cc6201 100644 --- a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java +++ b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.os.Handler; import android.os.Looper; +import com.android.internal.annotations.VisibleForTesting; + /** The implementation of exponential backoff with jitter applied. */ public class ExponentialBackoff { private int mRetryCounter; @@ -27,8 +29,31 @@ public class ExponentialBackoff { private long mMaximumDelayMs; private long mCurrentDelayMs; private int mMultiplier; - private Runnable mRunnable; - private Handler mHandler; + private final Runnable mRunnable; + private final Handler mHandler; + + /** + * Implementation of Handler methods, Adapter for testing (can't spy on final methods). + */ + private HandlerAdapter mHandlerAdapter = new HandlerAdapter() { + @Override + public boolean postDelayed(Runnable runnable, long delayMillis) { + return mHandler.postDelayed(runnable, delayMillis); + } + + @Override + public void removeCallbacks(Runnable runnable) { + mHandler.removeCallbacks(runnable); + } + }; + + /** + * Need to spy final methods for testing. + */ + public interface HandlerAdapter { + boolean postDelayed(Runnable runnable, long delayMillis); + void removeCallbacks(Runnable runnable); + } public ExponentialBackoff( long initialDelayMs, @@ -57,14 +82,14 @@ public class ExponentialBackoff { public void start() { mRetryCounter = 0; mCurrentDelayMs = mStartDelayMs; - mHandler.removeCallbacks(mRunnable); - mHandler.postDelayed(mRunnable, mCurrentDelayMs); + mHandlerAdapter.removeCallbacks(mRunnable); + mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs); } /** Stops the backoff, all pending messages will be removed from the message queue. */ public void stop() { mRetryCounter = 0; - mHandler.removeCallbacks(mRunnable); + mHandlerAdapter.removeCallbacks(mRunnable); } /** Should call when the retry action has failed and we want to retry after a longer delay. */ @@ -73,12 +98,17 @@ public class ExponentialBackoff { long temp = Math.min( mMaximumDelayMs, (long) (mStartDelayMs * Math.pow(mMultiplier, mRetryCounter))); mCurrentDelayMs = (long) (((1 + Math.random()) / 2) * temp); - mHandler.removeCallbacks(mRunnable); - mHandler.postDelayed(mRunnable, mCurrentDelayMs); + mHandlerAdapter.removeCallbacks(mRunnable); + mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs); } /** Returns the delay for the most recently posted message. */ public long getCurrentDelay() { return mCurrentDelayMs; } + + @VisibleForTesting + public void setHandlerAdapter(HandlerAdapter a) { + mHandlerAdapter = a; + } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 797805b52368..2b4c059cf69f 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -38,9 +38,10 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyHistogram; import android.telephony.VisualVoicemailSmsFilterSettings; -import com.android.ims.internal.IImsMMTelFeature; -import com.android.ims.internal.IImsRcsFeature; -import com.android.ims.internal.IImsRegistration; +import android.telephony.ims.aidl.IImsConfig; +import android.telephony.ims.aidl.IImsMmTelFeature; +import android.telephony.ims.aidl.IImsRcsFeature; +import android.telephony.ims.aidl.IImsRegistration; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.OperatorInfo; @@ -788,20 +789,21 @@ interface ITelephony { int getTetherApnRequired(); /** - * Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature - * as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback - * interface. - */ - IImsMMTelFeature getMMTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback); + * Enables framework IMS and triggers IMS Registration. + */ + void enableIms(int slotId); /** - * Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature - * as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback + * Disables framework IMS and triggers IMS deregistration. + */ + void disableIms(int slotId); + + /** + * Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature + * as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback * interface. - * Used for emergency calling only. */ - IImsMMTelFeature getEmergencyMMTelFeatureAndListen(int slotId, - in IImsServiceFeatureCallback callback); + IImsMmTelFeature getMmTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback); /** * Get IImsRcsFeature binder from ImsResolver that corresponds to the subId and RCS feature @@ -816,6 +818,11 @@ interface ITelephony { IImsRegistration getImsRegistration(int slotId, int feature); /** + * Returns the IImsConfig associated with the slot and feature specified. + */ + IImsConfig getImsConfig(int slotId, int feature); + + /** * Set the network selection mode to automatic. * * @param subId the id of the subscription to update. |