From 1639c21be6e7cd7699db4080fcf2ccc5cb2006e6 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Wed, 25 Jan 2017 14:26:41 -0800 Subject: [PATCH] Adds @hide ImsService APIs Adds @hide ImsService API implementations to be used for the new dynamic ImsResolver. 1) ImsService - The main class that all vendor ImsServices will implement. ImsServices that implement this method must return their implementations of MMTelFeature when onCreateMMTelFeature is called. The base ImsService class also relays all method calls through itself as a proxy. So, when Telephony calls a method, the ImsService figures out which MMTelFeature should be called (by slot) and then calls that feature's method implementation. 2) MMTelFeature/RcsFeature - Implements the I*Feature interfaces, which are used on both sides of the interface. The vendor implemented ImsService must implement all methods provided in the I*Feature interface in their implementation of *Feature that they return to the ImsService. 3) ImsServiceProxy[Compat] - The Proxy interface in telephony that will be called in ImsManager. When a method in this class is called, it will call the respective AIDL function: Telephony -> IImsServiceController AIDL -> vendor ImsService -> vendor ImsFeature implementation. ImsServiceProxyCompat is there to provide backwards compatibility with older ImsServices that do not use the new ImsService implementations. It implements all of the methods that are defined in the new I*Feature interfaces and translates them to the old ImsService AIDL calls. Test: Adds Unit Tests (see frameworks/opt/telephony) Merged-In: Id3466c178384158c788ab1d708ab108bb95866fc Change-Id: Id3466c178384158c788ab1d708ab108bb95866fc --- Android.mk | 1 + .../android/telephony/ims/ImsService.java | 430 ++++++++++++++++++ .../android/telephony/ims/ImsServiceBase.java | 4 +- .../telephony/ims/ImsServiceProxy.java | 316 +++++++++++++ .../telephony/ims/ImsServiceProxyCompat.java | 182 ++++++++ .../telephony/ims/feature/IMMTelFeature.java | 192 ++++++++ .../telephony/ims/feature/IRcsFeature.java | 26 ++ .../telephony/ims/feature/ImsFeature.java | 98 +++- .../telephony/ims/feature/MMTelFeature.java | 122 +++++ .../telephony/ims/feature/RcsFeature.java | 35 ++ .../internal/IImsFeatureStatusCallback.aidl | 25 + .../ims/internal/IImsServiceController.aidl | 42 +- .../internal/IImsServiceFeatureListener.aidl | 2 + 13 files changed, 1471 insertions(+), 4 deletions(-) create mode 100644 telephony/java/android/telephony/ims/ImsService.java create mode 100644 telephony/java/android/telephony/ims/ImsServiceProxy.java create mode 100644 telephony/java/android/telephony/ims/ImsServiceProxyCompat.java create mode 100644 telephony/java/android/telephony/ims/feature/IMMTelFeature.java create mode 100644 telephony/java/android/telephony/ims/feature/IRcsFeature.java create mode 100644 telephony/java/android/telephony/ims/feature/MMTelFeature.java create mode 100644 telephony/java/android/telephony/ims/feature/RcsFeature.java create mode 100644 telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl diff --git a/Android.mk b/Android.mk index a798a311e0411..e727ff4b2eeb4 100644 --- a/Android.mk +++ b/Android.mk @@ -435,6 +435,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/ims/internal/IImsEcbm.aidl \ telephony/java/com/android/ims/internal/IImsEcbmListener.aidl \ telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl \ + telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl \ telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl \ telephony/java/com/android/ims/internal/IImsService.aidl \ telephony/java/com/android/ims/internal/IImsServiceController.aidl \ diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java new file mode 100644 index 0000000000000..0f865a8437579 --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -0,0 +1,430 @@ +/* + * 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; + +import android.app.PendingIntent; +import android.content.Intent; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.CarrierConfigManager; +import android.telephony.ims.feature.ImsFeature; +import android.telephony.ims.feature.MMTelFeature; +import android.telephony.ims.feature.RcsFeature; +import android.util.Log; +import android.util.SparseArray; + +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.IImsFeatureStatusCallback; +import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsServiceController; +import com.android.ims.internal.IImsServiceFeatureListener; +import com.android.ims.internal.IImsUt; +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: + * + * ... + * + * + * + * + * + * + * + * ... + * + * 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 {@link RcsFeature} class. + * - MMTEL_FEATURE: This ImsService implements the {@link MMTelFeature} class. + * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the {@link 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 abstract class ImsService extends ImsServiceBase { + + private static final String LOG_TAG = "ImsService"; + + /** + * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService. + */ + public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService"; + + // A map of slot Id -> Set of features corresponding to that slot. + private final SparseArray> mFeatures = new SparseArray<>(); + + // Implements all supported features as a flat interface. + protected final IBinder mImsServiceController = new IImsServiceController.Stub() { + + @Override + public void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c) + throws RemoteException { + synchronized (mFeatures) { + onCreateImsFeatureInternal(slotId, feature, c); + } + } + + @Override + public void removeImsFeature(int slotId, int feature) throws RemoteException { + synchronized (mFeatures) { + onRemoveImsFeatureInternal(slotId, feature); + } + } + + @Override + public int startSession(int slotId, int featureType, PendingIntent incomingCallIntent, + IImsRegistrationListener listener) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.startSession(incomingCallIntent, listener); + } + } + return 0; + } + + @Override + public void endSession(int slotId, int featureType, int sessionId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.endSession(sessionId); + } + } + } + + @Override + public boolean isConnected(int slotId, int featureType, int sessionId, int callSessionType, + int callType) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.isConnected(sessionId, callSessionType, callType); + } + } + return false; + } + + @Override + public boolean isOpened(int slotId, int featureType, int sessionId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.isOpened(sessionId); + } + } + return false; + } + + @Override + public int getFeatureStatus(int slotId, int featureType) throws RemoteException { + int status = ImsFeature.STATE_NOT_AVAILABLE; + synchronized (mFeatures) { + SparseArray featureMap = mFeatures.get(slotId); + if (featureMap != null) { + ImsFeature feature = getImsFeatureFromType(featureMap, featureType); + if (feature != null) { + status = feature.getFeatureState(); + } + } + } + return status; + } + + @Override + public void addRegistrationListener(int slotId, int featureType, int sessionId, + IImsRegistrationListener listener) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.addRegistrationListener(sessionId, listener); + } + } + } + + @Override + public void removeRegistrationListener(int slotId, int featureType, int sessionId, + IImsRegistrationListener listener) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.removeRegistrationListener(sessionId, listener); + } + } + } + + @Override + public ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId, + int callSessionType, int callType) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.createCallProfile(sessionId, callSessionType, callType); + } + } + return null; + } + + @Override + public IImsCallSession createCallSession(int slotId, int featureType, int sessionId, + ImsCallProfile profile, IImsCallSessionListener listener) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.createCallSession(sessionId, profile, listener); + } + } + return null; + } + + @Override + public IImsCallSession getPendingCallSession(int slotId, int featureType, int sessionId, + String callId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.getPendingCallSession(sessionId, callId); + } + } + return null; + } + + @Override + public IImsUt getUtInterface(int slotId, int featureType, int sessionId) + throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.getUtInterface(sessionId); + } + } + return null; + } + + @Override + public IImsConfig getConfigInterface(int slotId, int featureType, int sessionId) + throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.getConfigInterface(sessionId); + } + } + return null; + } + + @Override + public void turnOnIms(int slotId, int featureType, int sessionId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.turnOnIms(sessionId); + } + } + } + + @Override + public void turnOffIms(int slotId, int featureType, int sessionId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.turnOffIms(sessionId); + } + } + } + + @Override + public IImsEcbm getEcbmInterface(int slotId, int featureType, int sessionId) + throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.getEcbmInterface(sessionId); + } + } + return null; + } + + @Override + public void setUiTTYMode(int slotId, int featureType, int sessionId, int uiTtyMode, + Message onComplete) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + feature.setUiTTYMode(sessionId, uiTtyMode, onComplete); + } + } + } + + @Override + public IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType, + int sessionId) throws RemoteException { + synchronized (mFeatures) { + MMTelFeature feature = resolveMMTelFeature(slotId, featureType); + if (feature != null) { + return feature.getMultiEndpointInterface(sessionId); + } + } + return null; + } + + }; + + @Override + public IBinder onBind(Intent intent) { + if(SERVICE_INTERFACE.equals(intent.getAction())) { + return mImsServiceController; + } + return null; + } + + /** + * Called from the ImsResolver to create the requested ImsFeature, as defined by the slot and + * featureType + * @param slotId An integer representing which SIM slot the ImsFeature is assigned to. + * @param featureType An integer representing the type of ImsFeature being created. This is + * defined in {@link ImsFeature}. + */ + // Be sure to lock on mFeatures before accessing this method + private void onCreateImsFeatureInternal(int slotId, int featureType, + IImsFeatureStatusCallback c) { + SparseArray featureMap = mFeatures.get(slotId); + if (featureMap == null) { + featureMap = new SparseArray<>(); + mFeatures.put(slotId, featureMap); + } + ImsFeature f = makeImsFeature(slotId, featureType); + if (f != null) { + f.setImsFeatureStatusCallback(c); + featureMap.put(featureType, f); + } + + } + /** + * Called from the ImsResolver to remove an existing ImsFeature, as defined by the slot and + * featureType. + * @param slotId An integer representing which SIM slot the ImsFeature is assigned to. + * @param featureType An integer representing the type of ImsFeature being removed. This is + * defined in {@link ImsFeature}. + */ + // Be sure to lock on mFeatures before accessing this method + private void onRemoveImsFeatureInternal(int slotId, int featureType) { + SparseArray featureMap = mFeatures.get(slotId); + if (featureMap == null) { + return; + } + + ImsFeature featureToRemove = getImsFeatureFromType(featureMap, featureType); + if (featureToRemove != null) { + featureMap.remove(featureType); + featureToRemove.notifyFeatureRemoved(slotId); + // Remove reference to Binder + featureToRemove.setImsFeatureStatusCallback(null); + } + } + + // Be sure to lock on mFeatures before accessing this method + private MMTelFeature resolveMMTelFeature(int slotId, int featureType) { + SparseArray features = getImsFeatureMap(slotId); + MMTelFeature feature = null; + if (features != null) { + feature = resolveImsFeature(features, featureType, MMTelFeature.class); + } + return feature; + } + + // Be sure to lock on mFeatures before accessing this method + private T resolveImsFeature(SparseArray set, int featureType, + Class className) { + ImsFeature feature = getImsFeatureFromType(set, featureType); + if (feature == null) { + return null; + } + try { + return className.cast(feature); + } catch (ClassCastException e) + { + Log.e(LOG_TAG, "Can not cast ImsFeature! Exception: " + e.getMessage()); + } + return null; + } + + @VisibleForTesting + // Be sure to lock on mFeatures before accessing this method + public SparseArray getImsFeatureMap(int slotId) { + return mFeatures.get(slotId); + } + + @VisibleForTesting + // Be sure to lock on mFeatures before accessing this method + public ImsFeature getImsFeatureFromType(SparseArray set, int featureType) { + return set.get(featureType); + } + + private ImsFeature makeImsFeature(int slotId, int feature) { + switch (feature) { + case ImsFeature.EMERGENCY_MMTEL: { + return onCreateEmergencyMMTelImsFeature(slotId); + } + case ImsFeature.MMTEL: { + return onCreateMMTelImsFeature(slotId); + } + case ImsFeature.RCS: { + return onCreateRcsFeature(slotId); + } + } + // Tried to create feature that is not defined. + return null; + } + + /** + * @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. + */ + public abstract MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId); + + /** + * @return An implementation of MMTelFeature that will be used by the system for MMTel + * functionality. + */ + public abstract MMTelFeature onCreateMMTelImsFeature(int slotId); + + /** + * @return An implementation of RcsFeature that will be used by the system for RCS. + */ + public abstract RcsFeature onCreateRcsFeature(int slotId); +} diff --git a/telephony/java/android/telephony/ims/ImsServiceBase.java b/telephony/java/android/telephony/ims/ImsServiceBase.java index 0b50ecaeb1ca9..0878db8453478 100644 --- a/telephony/java/android/telephony/ims/ImsServiceBase.java +++ b/telephony/java/android/telephony/ims/ImsServiceBase.java @@ -22,7 +22,9 @@ import android.os.IBinder; /** - * Base ImsService Implementation, which is used by the ImsResolver to bind. + * Base ImsService Implementation, which is used by the ImsResolver to bind. ImsServices that do not + * need to provide an ImsService implementation but still wish to be managed by the ImsResolver + * lifecycle may implement this class directly. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/ims/ImsServiceProxy.java b/telephony/java/android/telephony/ims/ImsServiceProxy.java new file mode 100644 index 0000000000000..b2cdba213771e --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsServiceProxy.java @@ -0,0 +1,316 @@ +/* + * 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; + +import android.app.PendingIntent; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.ims.feature.IRcsFeature; +import android.telephony.ims.feature.ImsFeature; +import android.util.Log; + +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.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsServiceController; +import com.android.ims.internal.IImsServiceFeatureListener; +import com.android.ims.internal.IImsUt; + +/** + * A container of the IImsServiceController binder, which implements all of the ImsFeatures that + * the platform currently supports: MMTel and RCS. + * @hide + */ + +public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeature { + + protected String LOG_TAG = "ImsServiceProxy"; + private final int mSupportedFeature; + + // Start by assuming the proxy is available for usage. + private boolean mIsAvailable = true; + // ImsFeature Status from the ImsService. Cached. + private Integer mFeatureStatusCached = null; + private ImsServiceProxy.INotifyStatusChanged mStatusCallback; + private final Object mLock = new Object(); + + public interface INotifyStatusChanged { + void notifyStatusChanged(); + } + + private final IImsServiceFeatureListener mListenerBinder = + new IImsServiceFeatureListener.Stub() { + + @Override + public void imsFeatureCreated(int slotId, int feature) throws RemoteException { + // The feature has been re-enabled. This may happen when the service crashes. + synchronized (mLock) { + if (!mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { + Log.i(LOG_TAG, "Feature enabled on slotId: " + slotId + " for feature: " + + feature); + mIsAvailable = true; + } + } + } + + @Override + public void imsFeatureRemoved(int slotId, int feature) throws RemoteException { + synchronized (mLock) { + if (mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { + Log.i(LOG_TAG, "Feature disabled on slotId: " + slotId + " for feature: " + + feature); + mIsAvailable = false; + } + } + } + + @Override + public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException { + synchronized (mLock) { + Log.i(LOG_TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature + + " status: " + status); + if (mSlotId == slotId && feature == mSupportedFeature) { + mFeatureStatusCached = status; + } + } + if (mStatusCallback != null) { + mStatusCallback.notifyStatusChanged(); + } + } + }; + + public ImsServiceProxy(int slotId, IBinder binder, int featureType) { + super(slotId, binder); + mSupportedFeature = featureType; + } + + public ImsServiceProxy(int slotId, int featureType) { + super(slotId, null /*IBinder*/); + mSupportedFeature = featureType; + } + + public IImsServiceFeatureListener getListener() { + return mListenerBinder; + } + + public void setBinder(IBinder binder) { + mBinder = binder; + } + + @Override + public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).startSession(mSlotId, mSupportedFeature, + incomingCallIntent, listener); + } + } + + @Override + public void endSession(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).endSession(mSlotId, mSupportedFeature, sessionId); + } + } + + @Override + public boolean isConnected(int sessionId, int callServiceType, int callType) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature, sessionId, + callServiceType, callType); + } + } + + @Override + public boolean isOpened(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature, sessionId); + } + } + + @Override + public void addRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature, + sessionId, listener); + } + } + + @Override + public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature, + sessionId, listener); + } + } + + @Override + public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).createCallProfile(mSlotId, mSupportedFeature, + sessionId, callServiceType, callType); + } + } + + @Override + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, + IImsCallSessionListener listener) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).createCallSession(mSlotId, mSupportedFeature, + sessionId, profile, listener); + } + } + + @Override + public IImsCallSession getPendingCallSession(int sessionId, String callId) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).getPendingCallSession(mSlotId, mSupportedFeature, + sessionId, callId); + } + } + + @Override + public IImsUt getUtInterface(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature, + sessionId); + } + } + + @Override + public IImsConfig getConfigInterface(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature, + sessionId); + } + } + + @Override + public void turnOnIms(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature, sessionId); + } + } + + @Override + public void turnOffIms(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature, sessionId); + } + } + + @Override + public IImsEcbm getEcbmInterface(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature, + sessionId); + } + } + + @Override + public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) + throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, sessionId, + uiTtyMode, onComplete); + } + } + + @Override + public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException { + synchronized (mLock) { + checkBinderConnection(); + return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId, + mSupportedFeature, sessionId); + } + } + + @Override + public int getFeatureStatus() { + synchronized (mLock) { + if (mFeatureStatusCached != null) { + return mFeatureStatusCached; + } + } + // Don't synchronize on Binder call. + Integer status = retrieveFeatureStatus(); + synchronized (mLock) { + if (status == null) { + return ImsFeature.STATE_NOT_AVAILABLE; + } + // Cache only non-null value for feature status. + mFeatureStatusCached = status; + } + return status; + } + + /** + * Internal method used to retrieve the feature status from the corresponding ImsService. + */ + private Integer retrieveFeatureStatus() { + if (mBinder != null) { + try { + return getServiceInterface(mBinder).getFeatureStatus(mSlotId, mSupportedFeature); + } catch (RemoteException e) { + // Status check failed, don't update cache + } + } + return null; + } + + /** + * @param c Callback that will fire when the feature status has changed. + */ + public void setStatusCallback(INotifyStatusChanged c) { + mStatusCallback = c; + } + + @Override + public boolean isBinderAlive() { + return mIsAvailable && getFeatureStatus() == ImsFeature.STATE_READY && mBinder != null && + mBinder.isBinderAlive(); + } + + private IImsServiceController getServiceInterface(IBinder b) { + return IImsServiceController.Stub.asInterface(b); + } +} diff --git a/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java new file mode 100644 index 0000000000000..ff538584de45f --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java @@ -0,0 +1,182 @@ +/* + * 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; + +import android.app.PendingIntent; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.ims.feature.IMMTelFeature; +import android.telephony.ims.feature.ImsFeature; + +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.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsService; +import com.android.ims.internal.IImsUt; + +/** + * Compatibility class that implements the new ImsService IMMTelFeature interface, but + * uses the old IImsService interface to support older devices that implement the deprecated + * opt/net/ims interface. + * @hide + */ + +public class ImsServiceProxyCompat implements IMMTelFeature { + + protected final int mSlotId; + protected IBinder mBinder; + + public ImsServiceProxyCompat(int slotId, IBinder binder) { + mSlotId = slotId; + mBinder = binder; + } + + @Override + public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) + throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).open(mSlotId, ImsFeature.MMTEL, incomingCallIntent, + listener); + } + + @Override + public void endSession(int sessionId) throws RemoteException { + checkBinderConnection(); + getServiceInterface(mBinder).close(sessionId); + } + + @Override + public boolean isConnected(int sessionId, int callServiceType, int callType) + throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).isConnected(sessionId, callServiceType, callType); + } + + @Override + public boolean isOpened(int sessionId) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).isOpened(sessionId); + } + + @Override + public void addRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException { + checkBinderConnection(); + getServiceInterface(mBinder).addRegistrationListener(mSlotId, ImsFeature.MMTEL, listener); + } + + @Override + public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException { + checkBinderConnection(); + // Not Implemented in old ImsService. If the registration listener becomes invalid, the + // ImsService will remove. + } + + @Override + public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType) + throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).createCallProfile(sessionId, callServiceType, callType); + } + + @Override + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, + IImsCallSessionListener listener) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).createCallSession(sessionId, profile, listener); + } + + @Override + public IImsCallSession getPendingCallSession(int sessionId, String callId) + throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).getPendingCallSession(sessionId, callId); + } + + @Override + public IImsUt getUtInterface(int sessionId) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).getUtInterface(sessionId); + } + + @Override + public IImsConfig getConfigInterface(int sessionId) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).getConfigInterface(mSlotId); + } + + @Override + public void turnOnIms(int sessionId) throws RemoteException { + checkBinderConnection(); + getServiceInterface(mBinder).turnOnIms(mSlotId); + } + + @Override + public void turnOffIms(int sessionId) throws RemoteException { + checkBinderConnection(); + getServiceInterface(mBinder).turnOffIms(mSlotId); + } + + @Override + public IImsEcbm getEcbmInterface(int sessionId) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).getEcbmInterface(sessionId); + } + + @Override + public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) + throws RemoteException { + checkBinderConnection(); + getServiceInterface(mBinder).setUiTTYMode(sessionId, uiTtyMode, onComplete); + } + + @Override + public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException { + checkBinderConnection(); + return getServiceInterface(mBinder).getMultiEndpointInterface(sessionId); + } + + /** + * Base implementation, always returns READY for compatibility with old ImsService. + */ + public int getFeatureStatus() { + return ImsFeature.STATE_READY; + } + + /** + * @return false if the binder connection is no longer alive. + */ + public boolean isBinderAlive() { + return mBinder != null && mBinder.isBinderAlive(); + } + + private IImsService getServiceInterface(IBinder b) { + return IImsService.Stub.asInterface(b); + } + + protected void checkBinderConnection() throws RemoteException { + if (!isBinderAlive()) { + throw new RemoteException("ImsServiceProxy is not available for that feature."); + } + } +} diff --git a/telephony/java/android/telephony/ims/feature/IMMTelFeature.java b/telephony/java/android/telephony/ims/feature/IMMTelFeature.java new file mode 100644 index 0000000000000..e180843c8fa1a --- /dev/null +++ b/telephony/java/android/telephony/ims/feature/IMMTelFeature.java @@ -0,0 +1,192 @@ +/* + * 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 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.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsUt; + +/** + * MMTel interface for an ImsService. When updating this interface, ensure that base implementations + * of your changes are also present in MMTelFeature for compatibility with older versions of the + * MMTel feature. + * @hide + */ + +public interface IMMTelFeature { + + /** + * 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 + * {@link #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. + */ + int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) + throws RemoteException; + + /** + * End a previously started session using the associated sessionId. + * @param sessionId an integer (greater than 0) representing the ongoing session. See + * {@link #startSession}. + */ + void endSession(int sessionId) throws RemoteException; + + /** + * Checks if the IMS service has successfully registered to the IMS network with the specified + * service & call type. + * + * @param sessionId a session id which is obtained from {@link #startSession} + * @param callServiceType 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 + * @throws RemoteException + */ + boolean isConnected(int sessionId, int callServiceType, int callType) throws RemoteException; + + /** + * Checks if the specified IMS service is opened. + * + * @param sessionId a service id which is obtained from {@link #startSession} + * @return true if the specified service id is opened; false otherwise + */ + boolean isOpened(int sessionId) throws RemoteException; + + /** + * Add a new registration listener for the client associated with the session Id. + * @param sessionId a session id which is obtained from {@link #startSession} + * @param listener An implementation of IImsRegistrationListener. + */ + void addRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException; + + /** + * Remove a previously registered listener using {@link #addRegistrationListener} for the client + * associated with the session Id. + * @param sessionId a session id which is obtained from {@link #startSession} + * @param listener A previously registered IImsRegistrationListener + */ + void removeRegistrationListener(int sessionId, IImsRegistrationListener listener) + throws RemoteException; + + /** + * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. + * + * @param sessionId a session id which is obtained from {@link #startSession} + * @param callServiceType 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 + */ + ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType) + throws RemoteException; + + /** + * Creates a {@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. + */ + IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, + IImsCallSessionListener listener) throws RemoteException; + + /** + * 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 + */ + IImsCallSession getPendingCallSession(int sessionId, String callId) throws RemoteException; + + /** + * @return The Ut interface for the supplementary service configuration. + */ + IImsUt getUtInterface(int sessionId) throws RemoteException; + + /** + * @return The config interface for IMS Configuration + */ + IImsConfig getConfigInterface(int sessionId) throws RemoteException; + + /** + * Signal the MMTelFeature to turn on IMS when it has been turned off using {@link #turnOffIms} + * @param sessionId a session id which is obtained from {@link #startSession} + */ + void turnOnIms(int sessionId) throws RemoteException; + + /** + * Signal the MMTelFeature to turn off IMS when it has been turned on using {@link #turnOnIms} + * @param sessionId a session id which is obtained from {@link #startSession} + */ + void turnOffIms(int sessionId) throws RemoteException; + + /** + * @return The Emergency call-back mode interface for emergency VoLTE calls that support it. + */ + IImsEcbm getEcbmInterface(int sessionId) throws RemoteException; + + /** + * Sets the current UI TTY mode for the MMTelFeature. + * @param sessionId a session id which is obtained from {@link #startSession} + * @param uiTtyMode An integer containing the new UI TTY Mode. + * @param onComplete A {@link Message} to be used when the mode has been set. + * @throws RemoteException + */ + void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) throws RemoteException; + + /** + * @return MultiEndpoint interface for DEP notifications + */ + IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException; +} diff --git a/telephony/java/android/telephony/ims/feature/IRcsFeature.java b/telephony/java/android/telephony/ims/feature/IRcsFeature.java new file mode 100644 index 0000000000000..e28e1b38dfcd3 --- /dev/null +++ b/telephony/java/android/telephony/ims/feature/IRcsFeature.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * Feature interface that provides access to RCS APIs. Currently empty until RCS support is added + * in the framework. + * @hide + */ + +public interface IRcsFeature { +} diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 0509d604e688b..8d7d260104e28 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -16,18 +16,112 @@ package android.telephony.ims.feature; +import android.annotation.IntDef; +import android.os.RemoteException; +import android.util.Log; + +import com.android.ims.internal.IImsFeatureStatusCallback; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + /** * Base class for all IMS features that are supported by the framework. * @hide */ -public class ImsFeature { +public abstract class ImsFeature { + + private static final String LOG_TAG = "ImsFeature"; // Invalid feature value public static final int INVALID = -1; - // ImsFeatures that are defined in the Manifests + // 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 List mRemovedListeners = new ArrayList<>(); + private IImsFeatureStatusCallback mStatusCallback; + private @ImsState int mState = STATE_NOT_AVAILABLE; + + public interface INotifyFeatureRemoved { + void onFeatureRemoved(int slotId); + } + + public void addFeatureRemovedListener(INotifyFeatureRemoved listener) { + synchronized (mRemovedListeners) { + mRemovedListeners.add(listener); + } + } + + public void removeFeatureRemovedListener(INotifyFeatureRemoved listener) { + synchronized (mRemovedListeners) { + mRemovedListeners.remove(listener); + } + } + + // Not final for testing. + public void notifyFeatureRemoved(int slotId) { + synchronized (mRemovedListeners) { + mRemovedListeners.forEach(l -> l.onFeatureRemoved(slotId)); + onFeatureRemoved(); + } + } + + public int getFeatureState() { + return mState; + } + + protected final void setFeatureState(@ImsState int state) { + if (mState != state) { + mState = state; + notifyFeatureState(state); + } + } + + // Not final for testing. + public void setImsFeatureStatusCallback(IImsFeatureStatusCallback c) { + mStatusCallback = c; + // If we have just connected, send queued status. + notifyFeatureState(mState); + } + + /** + * Internal method called by ImsFeature when setFeatureState has changed. + * @param state + */ + private void notifyFeatureState(@ImsState int state) { + if (mStatusCallback != null) { + try { + Log.i(LOG_TAG, "notifying ImsFeatureState"); + mStatusCallback.notifyImsFeatureStatus(state); + } catch (RemoteException e) { + mStatusCallback = null; + Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); + } + } + } + + /** + * Called when the feature is being removed and must be cleaned up. + */ + public abstract void onFeatureRemoved(); } diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java new file mode 100644 index 0000000000000..570cd65b0e0bf --- /dev/null +++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java @@ -0,0 +1,122 @@ +/* + * 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 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.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsUt; + +import java.util.ArrayList; +import java.util.List; + +/** + * Base implementation, which implements all methods in IMMTelFeature. Any class wishing to use + * MMTelFeature should extend this class and implement all methods that the service supports. + * + * @hide + */ + +public class MMTelFeature extends ImsFeature implements IMMTelFeature { + + @Override + public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener) { + return 0; + } + + @Override + public void endSession(int sessionId) { + } + + @Override + public boolean isConnected(int sessionId, int callSessionType, int callType) { + return false; + } + + @Override + public boolean isOpened(int sessionId) { + return false; + } + + @Override + public void addRegistrationListener(int sessionId, IImsRegistrationListener listener) { + } + + @Override + public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener) { + } + + @Override + public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType) { + return null; + } + + @Override + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, + IImsCallSessionListener listener) { + return null; + } + + @Override + public IImsCallSession getPendingCallSession(int sessionId, String callId) { + return null; + } + + @Override + public IImsUt getUtInterface(int sessionId) { + return null; + } + + @Override + public IImsConfig getConfigInterface(int sessionId) { + return null; + } + + @Override + public void turnOnIms(int sessionId) { + } + + @Override + public void turnOffIms(int sessionId) { + } + + @Override + public IImsEcbm getEcbmInterface(int sessionId) { + return null; + } + + @Override + public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) { + } + + @Override + public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) { + return null; + } + + @Override + public void onFeatureRemoved() { + + } +} diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java new file mode 100644 index 0000000000000..9cddc1b934dbf --- /dev/null +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -0,0 +1,35 @@ +/* + * 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; + +/** + * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend + * this class and provide implementations of the IRcsFeature methods that they support. + * @hide + */ + +public class RcsFeature extends ImsFeature implements IRcsFeature { + + public RcsFeature() { + super(); + } + + @Override + public void onFeatureRemoved() { + + } +} diff --git a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl new file mode 100644 index 0000000000000..41b1042e9a867 --- /dev/null +++ b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl @@ -0,0 +1,25 @@ +/* + * 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/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl index fa86a43c79d3f..b700f497d0373 100644 --- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl +++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl @@ -16,10 +16,50 @@ package com.android.ims.internal; +import android.app.PendingIntent; + +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.IImsFeatureStatusCallback; +import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; +import com.android.ims.internal.IImsUt; + +import android.os.Message; + /** + * See ImsService and IMMTelFeature for more information. * {@hide} */ interface IImsServiceController { - void createImsFeature(int slotId, int feature); + // ImsService Control + void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c); void removeImsFeature(int slotId, int feature); + // MMTel Feature + int startSession(int slotId, int featureType, in PendingIntent incomingCallIntent, + in IImsRegistrationListener listener); + void endSession(int slotId, int featureType, int sessionId); + boolean isConnected(int slotId, int featureType, int sessionId, int callSessionType, int callType); + boolean isOpened(int slotId, int featureType, int sessionId); + int getFeatureStatus(int slotId, int featureType); + void addRegistrationListener(int slotId, int featureType, int sessionId, + in IImsRegistrationListener listener); + void removeRegistrationListener(int slotId, int featureType, int sessionId, + in IImsRegistrationListener listener); + ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId, int callSessionType, int callType); + IImsCallSession createCallSession(int slotId, int featureType, int sessionId, + in ImsCallProfile profile, IImsCallSessionListener listener); + IImsCallSession getPendingCallSession(int slotId, int featureType, int sessionId, + String callId); + IImsUt getUtInterface(int slotId, int featureType, int sessionId); + IImsConfig getConfigInterface(int slotId, int featureType, int sessionId); + void turnOnIms(int slotId, int featureType, int sessionId); + void turnOffIms(int slotId, int featureType, int sessionId); + IImsEcbm getEcbmInterface(int slotId, int featureType, int sessionId); + void setUiTTYMode(int slotId, int featureType, int sessionId, int uiTtyMode, + in Message onComplete); + IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType, int sessionId); } diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl index 0a36b6bec6a2f..82a13dcb537c8 100644 --- a/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl +++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl @@ -17,9 +17,11 @@ package com.android.ims.internal; /** +* Interface from ImsResolver to ImsServiceProxy in ImsManager. * {@hide} */ oneway interface IImsServiceFeatureListener { void imsFeatureCreated(int slotId, int feature); void imsFeatureRemoved(int slotId, int feature); + void imsStatusChanged(int slotId, int feature, int status); } \ No newline at end of file