Merge "Adds @hide ImsService APIs"
diff --git a/Android.mk b/Android.mk
index 7a8b1b7..e766e60 100644
--- a/Android.mk
+++ b/Android.mk
@@ -473,6 +473,7 @@
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 0000000..0f865a8
--- /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:
+ *
+ * ...
+ * <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 {@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<SparseArray<ImsFeature>> 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<ImsFeature> 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<ImsFeature> 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<ImsFeature> 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<ImsFeature> 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 extends ImsFeature> T resolveImsFeature(SparseArray<ImsFeature> set, int featureType,
+ Class<T> 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<ImsFeature> getImsFeatureMap(int slotId) {
+ return mFeatures.get(slotId);
+ }
+
+ @VisibleForTesting
+ // Be sure to lock on mFeatures before accessing this method
+ public ImsFeature getImsFeatureFromType(SparseArray<ImsFeature> 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 0b50eca..0878db8 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 0000000..b2cdba2
--- /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 0000000..ff53858
--- /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 0000000..e180843
--- /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 0000000..e28e1b3
--- /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 0509d60..8d7d260 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<INotifyFeatureRemoved> 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 0000000..570cd65
--- /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 0000000..9cddc1b
--- /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 0000000..41b1042
--- /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 fa86a43..b700f49 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 0a36b6b..82a13dc 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