Integrate new ImsCallSessionListener am: 8409c97036 am: 4567efc2fc
am: 5f8a3671b1 -s ours
Change-Id: Ifa1216ae54e8a1977cff5022b0b43ac0a897391e
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java
index 6200a07..e32103e 100644
--- a/src/java/com/android/ims/ImsCall.java
+++ b/src/java/com/android/ims/ImsCall.java
@@ -36,10 +36,15 @@
import java.util.concurrent.atomic.AtomicInteger;
import android.telephony.ServiceState;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsConferenceState;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsSuppServiceNotification;
import android.util.Log;
import com.android.ims.internal.ICall;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallSession;
import com.android.ims.internal.ImsStreamMediaSession;
import com.android.internal.annotations.VisibleForTesting;
@@ -1623,6 +1628,7 @@
// Make a copy of the current ImsCallProfile and modify it to enable RTT
Parcel p = Parcel.obtain();
mCallProfile.writeToParcel(p, 0);
+ p.setDataPosition(0);
ImsCallProfile requestedProfile = new ImsCallProfile(p);
requestedProfile.mMediaProfile.setRttMode(ImsStreamMediaProfile.RTT_MODE_FULL);
@@ -3072,6 +3078,7 @@
public void callSessionRttModifyRequestReceived(ImsCallSession session,
ImsCallProfile callProfile) {
ImsCall.Listener listener;
+ logi("callSessionRttModifyRequestReceived");
synchronized(ImsCall.this) {
listener = mListener;
@@ -3096,6 +3103,7 @@
public void callSessionRttModifyResponseReceived(int status) {
ImsCall.Listener listener;
+ logi("callSessionRttModifyResponseReceived");
synchronized(ImsCall.this) {
listener = mListener;
}
diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java
index 216bc41..d5fb633 100644
--- a/src/java/com/android/ims/ImsConnectionStateListener.java
+++ b/src/java/com/android/ims/ImsConnectionStateListener.java
@@ -17,8 +17,13 @@
package com.android.ims;
import android.net.Uri;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import java.util.Arrays;
+
/**
* Listener for receiving notifications about changes to the IMS connection.
* It provides a state of IMS registration between UE and IMS network, the service
@@ -53,6 +58,69 @@
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
registrationAssociatedUriChanged(uris);
}
+
+ /**
+ * Used to convert from the new capabilities structure to the old features structure for
+ * backwards compatibility.
+ * @param imsRadioTech The registration that will be used to convert to the old feature
+ * structure. Can be either {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
+ * @param c Capabilities that will be turned into old feature array.
+ */
+ public void onFeatureCapabilityChangedAdapter(
+ @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech,
+ ImsFeature.Capabilities c) {
+ // Size of ImsConfig.FeatureConstants
+ int[] enabledCapabilities = new int[6];
+ // UNKNOWN means disabled.
+ Arrays.fill(enabledCapabilities, ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN);
+ // Size of ImsConfig.FeatureConstants
+ int[] disabledCapabilities = new int[6];
+ Arrays.fill(disabledCapabilities, ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN);
+ // populate enabledCapabilities
+ switch (imsRadioTech) {
+ case ImsRegistrationImplBase.REGISTRATION_TECH_LTE: {
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)) {
+ // enabled means equal to its own integer value.
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
+ }
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO)) {
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE;
+ }
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT)) {
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE;
+ }
+ break;
+ }
+ case ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN: {
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)) {
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI;
+ }
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO)) {
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI;
+ }
+ if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT)) {
+ enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI] =
+ ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI;
+ }
+ break;
+ }
+ }
+ // make disabledCapabilities the opposite of enabledCapabilities. Since the disabled
+ // capabilities array was defaulted to -1 it is UNKNOWN if not disabled.
+ for (int i = 0; i < enabledCapabilities.length; i++) {
+ if (enabledCapabilities[i] != i) {
+ disabledCapabilities[i] = i;
+ }
+ }
+ onFeatureCapabilityChanged(ImsServiceClass.MMTEL, enabledCapabilities,
+ disabledCapabilities);
+ }
/**
* Called when the device is connected to the IMS network with {@param imsRadioTech}.
*/
diff --git a/src/java/com/android/ims/ImsEcbm.java b/src/java/com/android/ims/ImsEcbm.java
index 53549bf..99d99f1 100644
--- a/src/java/com/android/ims/ImsEcbm.java
+++ b/src/java/com/android/ims/ImsEcbm.java
@@ -29,18 +29,12 @@
package com.android.ims;
-import java.util.HashMap;
-import java.util.Map;
-
-import android.os.AsyncResult;
-import android.os.Bundle;
-import android.os.Message;
import android.os.RemoteException;
import android.telephony.Rlog;
+import android.telephony.ims.ImsReasonInfo;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsEcbmListener;
-import com.android.ims.ImsEcbmStateListener;
/**
* Provides APIs for the supplementary service settings using IMS (Ut interface).
diff --git a/src/java/com/android/ims/ImsExternalCallStateListener.java b/src/java/com/android/ims/ImsExternalCallStateListener.java
index 3f4f163..aae4c9b 100644
--- a/src/java/com/android/ims/ImsExternalCallStateListener.java
+++ b/src/java/com/android/ims/ImsExternalCallStateListener.java
@@ -16,6 +16,8 @@
package com.android.ims;
+import android.telephony.ims.ImsExternalCallState;
+
import java.util.List;
/**
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index eaf973d..0a0eb24 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -16,51 +16,44 @@
package com.android.ims;
+import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Handler;
+import android.os.Bundle;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.provider.Settings;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
-import android.telephony.ims.internal.feature.ImsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.Rlog;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.feature.MmTelFeature;
import android.util.Log;
import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsConfig;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsRegistrationCallback;
-import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsServiceController;
-import com.android.ims.internal.IImsSmsListener;
import com.android.ims.internal.IImsUt;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallSession;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.ExponentialBackoff;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArraySet;
/**
@@ -87,13 +80,13 @@
/**
* The result code to be sent back with the incoming call {@link PendingIntent}.
- * @see #open(PendingIntent, ImsConnectionStateListener)
+ * @see #open(MmTelFeature.Listener)
*/
public static final int INCOMING_CALL_RESULT_CODE = 101;
/**
* Key to retrieve the call ID from an incoming call intent.
- * @see #open(PendingIntent, ImsConnectionStateListener)
+ * @see #open(MmTelFeature.Listener)
*/
public static final String EXTRA_CALL_ID = "android:imsCallID";
@@ -168,6 +161,11 @@
*/
public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
+ private static final int SYSTEM_PROPERTY_NOT_SET = -1;
+
+ // -1 indicates a subscriptionProperty value that is never set.
+ private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
+
private static final String TAG = "ImsManager";
private static final boolean DBG = true;
@@ -178,7 +176,7 @@
private CarrierConfigManager mConfigManager;
private int mPhoneId;
private final boolean mConfigDynamicBind;
- private ImsServiceProxy mImsServiceProxy = null;
+ private @Nullable MmTelFeatureConnection mMmTelFeatureConnection = null;
private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
// Ut interface for the supplementary service configuration
private ImsUt mUt = null;
@@ -193,33 +191,8 @@
private ImsMultiEndpoint mMultiEndpoint = null;
- private Set<ImsServiceProxy.IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
-
- // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
- // remove them from the ImsService.
- private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>();
-
-
- // Used for compatibility with the old Registration method
- // TODO: Remove once the compat layer is in place
- private final ImsRegistrationListenerProxy mImsRegistrationListenerProxy =
- new ImsRegistrationListenerProxy();
- // New API for registration to the ImsService.
- private final ImsRegistrationCallback mRegistrationCallback = new ImsRegistrationCallback();
-
-
- // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do
- // it again.
- private boolean mHasRegisteredForProxy = false;
- private final Object mHasRegisteredLock = new Object();
-
- // SystemProperties used as cache
- private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
- private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
- private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
- // Flag indicating data enabled or not. This flag should be in sync with
- // DcTracker.isDataEnabled(). The flag will be set later during boot up.
- private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
+ private Set<MmTelFeatureConnection.IFeatureUpdate> mStatusCallbacks =
+ new CopyOnWriteArraySet<>();
public static final String TRUE = "true";
public static final String FALSE = "false";
@@ -229,19 +202,6 @@
private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
new ConcurrentLinkedDeque<>();
- // Exponential backoff for provisioning cache update. May be null for instances of ImsManager
- // that are not on a thread supporting a looper.
- private ExponentialBackoff mProvisionBackoff;
- // Initial Provisioning check delay in ms
- private static final long BACKOFF_INITIAL_DELAY_MS = 500;
- // Max Provisioning check delay in ms (5 Minutes)
- private static final long BACKOFF_MAX_DELAY_MS = 300000;
- // Multiplier for exponential delay
- private static final int BACKOFF_MULTIPLIER = 2;
- // -1 indicates a subscriptionProperty value that is never set.
- private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
-
-
/**
* Gets a manager instance.
*
@@ -285,9 +245,12 @@
/**
* Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
- * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false),
- * this method will return default value specified by
+ * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
+ * the setting is not initialized, this method will return default value specified by
* {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
+ *
+ * Note that even if the setting was set, it may no longer be editable. If this is the case we
+ * return the default value.
*/
public boolean isEnhanced4gLteModeSettingEnabledByUser() {
int setting = SubscriptionManager.getIntegerSubscriptionProperty(
@@ -407,8 +370,13 @@
* basis.
*/
public boolean isVolteEnabledByPlatform() {
- if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
- PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
+ // We first read the per slot value. If doesn't exist, we read the general value. If still
+ // doesn't exist, we use the hardcoded default value.
+ if (SystemProperties.getInt(
+ PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
+ SYSTEM_PROPERTY_NOT_SET) == 1 ||
+ SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
+ SYSTEM_PROPERTY_NOT_SET) == 1) {
return true;
}
@@ -541,8 +509,12 @@
* which must be done correctly).
*/
public boolean isVtEnabledByPlatform() {
- if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
- PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
+ // We first read the per slot value. If doesn't exist, we read the general value. If still
+ // doesn't exist, we use the hardcoded default value.
+ if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
+ Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
+ SystemProperties.getInt(
+ PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
return true;
}
@@ -577,7 +549,8 @@
SUB_PROPERTY_NOT_INITIALIZED, mContext);
// If it's never set, by default we return true.
- return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1);
+ return (setting == SUB_PROPERTY_NOT_INITIALIZED
+ || setting == ImsConfig.FeatureValueConstants.ON);
}
/**
@@ -598,16 +571,12 @@
* Change persistent VT enabled setting for slot.
*/
public void setVtSetting(boolean enabled) {
- SubscriptionManager.setSubscriptionProperty(getSubId(),
- SubscriptionManager.VT_IMS_ENABLED,
+ SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.VT_IMS_ENABLED,
booleanToPropertyString(enabled));
+
try {
- ImsConfig config = getConfigInterface();
- config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
- TelephonyManager.NETWORK_TYPE_LTE,
- enabled ? ImsConfig.FeatureValueConstants.ON
- : ImsConfig.FeatureValueConstants.OFF,
- mImsConfigListener);
+ changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE, enabled);
if (enabled) {
log("setVtSetting(b) : turnOnIms");
@@ -618,7 +587,10 @@
log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
turnOffIms();
}
- } catch (ImsException e) {
+ } catch (ImsException | RemoteException e) {
+ // The ImsService is down. Since the SubscriptionManager already recorded the user's
+ // preference, it will be resent in updateImsServiceConfig when the ImsPhoneCallTracker
+ // reconnects.
loge("setVtSetting(b): ", e);
}
}
@@ -645,10 +617,15 @@
* The platform property may override the carrier config.
*/
private boolean isTurnOffImsAllowedByPlatform() {
- if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
- PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
+ // We first read the per slot value. If doesn't exist, we read the general value. If still
+ // doesn't exist, we use the hardcoded default value.
+ if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
+ Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
+ SystemProperties.getInt(
+ PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
return true;
}
+
return getBooleanCarrierConfig(
CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
}
@@ -683,7 +660,7 @@
return getBooleanCarrierConfig(
CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
} else {
- return setting == 1;
+ return setting == ImsConfig.FeatureValueConstants.ON;
}
}
@@ -717,18 +694,13 @@
* @param wfcMode The WFC preference if WFC is enabled
*/
public void setWfcNonPersistent(boolean enabled, int wfcMode) {
- int imsFeatureValue =
- enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
// Force IMS to register over LTE when turning off WFC
int imsWfcModeFeatureValue =
enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
try {
- ImsConfig config = getConfigInterface();
- config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
- TelephonyManager.NETWORK_TYPE_IWLAN,
- imsFeatureValue,
- mImsConfigListener);
+ changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, enabled);
if (enabled) {
log("setWfcSetting() : turnOnIms");
@@ -741,7 +713,7 @@
}
setWfcModeInternal(imsWfcModeFeatureValue);
- } catch (ImsException e) {
+ } catch (ImsException | RemoteException e) {
loge("setWfcSetting(): ", e);
}
}
@@ -915,7 +887,7 @@
Thread thread = new Thread(new Runnable() {
public void run() {
try {
- imsManager.getConfigInterface().setProvisionedValue(
+ imsManager.getConfigInterface().setConfig(
ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
value);
} catch (ImsException e) {
@@ -931,7 +903,7 @@
final int value = wfcMode;
Thread thread = new Thread(() -> {
try {
- getConfigInterface().setProvisionedValue(
+ getConfigInterface().setConfig(
ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
} catch (ImsException e) {
// do nothing
@@ -968,7 +940,7 @@
return getBooleanCarrierConfig(
CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
} else {
- return (setting == 1);
+ return setting == ImsConfig.FeatureValueConstants.ON;
}
}
@@ -1001,7 +973,7 @@
: ImsConfig.FeatureValueConstants.OFF;
Thread thread = new Thread(() -> {
try {
- getConfigInterface().setProvisionedValue(
+ getConfigInterface().setConfig(
ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
} catch (ImsException e) {
// do nothing
@@ -1034,8 +1006,12 @@
* configuration settings which must be done correctly).
*/
public boolean isWfcEnabledByPlatform() {
- if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
- PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
+ // We first read the per slot value. If doesn't exist, we read the general value. If still
+ // doesn't exist, we use the hardcoded default value.
+ if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
+ Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
+ SystemProperties.getInt(
+ PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
return true;
}
@@ -1070,116 +1046,28 @@
}
/**
- * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
- *
- * We cannot register receiver in ImsManager because this would lead to resource leak.
- * ImsManager can be created in different processes and it is not notified when that process
- * is about to be terminated.
- *
- * @hide
- * */
- public static void onProvisionedValueChanged(Context context, int item, String value) {
- if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
- ImsManager mgr = ImsManager.getInstance(context,
- SubscriptionManager.getDefaultVoicePhoneId());
-
- switch (item) {
- case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
- mgr.setVolteProvisionedProperty(value.equals("1"));
- if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
- break;
-
- case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
- mgr.setWfcProvisionedProperty(value.equals("1"));
- if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
- break;
-
- case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
- mgr.setVtProvisionedProperty(value.equals("1"));
- if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
- break;
-
+ * Will return with config value or throw an ImsException if we receive an error from
+ * ImsConfig for that value.
+ */
+ private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
+ int value = config.getProvisionedValue(item);
+ if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
+ throw new ImsException("getProvisionedBool failed with error for item: " + item,
+ ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
}
- }
-
- private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Boolean> {
- @Override
- protected Boolean doInBackground(Void... params) {
- // disable on any error
- setVolteProvisionedProperty(false);
- setWfcProvisionedProperty(false);
- setVtProvisionedProperty(false);
-
- try {
- ImsConfig config = getConfigInterface();
- if (config != null) {
- setVolteProvisionedProperty(getProvisionedBool(config,
- ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
- if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
-
- setWfcProvisionedProperty(getProvisionedBool(config,
- ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
- if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
-
- setVtProvisionedProperty(getProvisionedBool(config,
- ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
- if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
-
- }
- } catch (ImsException ie) {
- Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
- return false;
- }
-
- return true;
- }
-
- @Override
- protected void onPostExecute(Boolean completed) {
- if (mProvisionBackoff == null) {
- return;
- }
- if (!completed) {
- mProvisionBackoff.notifyFailed();
- } else {
- mProvisionBackoff.stop();
- }
- }
-
- /**
- * Will return with config value or throw an ImsException if we receive an error from
- * ImsConfig for that value.
- */
- private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
- int value = config.getProvisionedValue(item);
- if (value == ImsConfig.FeatureValueConstants.ERROR) {
- throw new ImsException("getProvisionedBool failed with error for item: " + item,
- ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
- }
- return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
- }
- }
-
- // used internally only, use #updateProvisionedValues instead.
- private void handleUpdateProvisionedValues() {
- if (getBooleanCarrierConfig(
- CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
-
- new AsyncUpdateProvisionedValues().execute();
- }
+ return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
}
/**
- * Asynchronously get VoLTE, WFC, VT provisioning statuses. If ImsConfig is not available, we
- * will retry with exponential backoff.
+ * Will return with config value or return false if we receive an error from
+ * ImsConfig for that value.
*/
- private void updateProvisionedValues() {
- // Start trying to receive provisioning status after BACKOFF_INITIAL_DELAY_MS.
- if (mProvisionBackoff != null) {
- mProvisionBackoff.start();
- } else {
- // bypass and launch async thread once without backoff.
- handleUpdateProvisionedValues();
+ private boolean getProvisionedBoolNoException(int item) {
+ try {
+ ImsConfig config = getConfigInterface();
+ return getProvisionedBool(config, item);
+ } catch (ImsException ex) {
+ return false;
}
}
@@ -1204,8 +1092,6 @@
/**
* Sync carrier config and user settings with ImsConfig.
*
- * @param context for the manager object
- * @param phoneId phone id
* @param force update
*/
public void updateImsServiceConfig(boolean force) {
@@ -1220,13 +1106,11 @@
if (!mConfigUpdated || force) {
try {
- updateProvisionedValues();
-
// TODO: Extend ImsConfig API and set all feature values in single function call.
// Note: currently the order of updates is set to produce different order of
- // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
- // differentiate this code path from vendor code perspective.
+ // changeEnabledCapabilities() function calls from setAdvanced4GMode(). This is done
+ // to differentiate this code path from vendor code perspective.
boolean isImsUsed = updateVolteFeatureValue();
isImsUsed |= updateWfcFeatureAndProvisionedValues();
isImsUsed |= updateVideoCallFeatureValue();
@@ -1245,7 +1129,7 @@
}
mConfigUpdated = true;
- } catch (ImsException e) {
+ } catch (ImsException | RemoteException e) {
loge("updateImsServiceConfig: ", e);
mConfigUpdated = false;
}
@@ -1257,7 +1141,7 @@
* @return whether feature is On
* @throws ImsException
*/
- private boolean updateVolteFeatureValue() throws ImsException {
+ private boolean updateVolteFeatureValue() throws RemoteException {
boolean available = isVolteEnabledByPlatform();
boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
@@ -1267,13 +1151,8 @@
+ ", enabled = " + enabled
+ ", nonTTY = " + isNonTty);
- getConfigInterface().setFeatureValue(
- ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
- TelephonyManager.NETWORK_TYPE_LTE,
- isFeatureOn ?
- ImsConfig.FeatureValueConstants.ON :
- ImsConfig.FeatureValueConstants.OFF,
- mImsConfigListener);
+ changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
return isFeatureOn;
}
@@ -1283,7 +1162,7 @@
* @return whether feature is On
* @throws ImsException
*/
- private boolean updateVideoCallFeatureValue() throws ImsException {
+ private boolean updateVideoCallFeatureValue() throws RemoteException {
boolean available = isVtEnabledByPlatform();
boolean enabled = isVtEnabledByUser();
boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
@@ -1299,13 +1178,8 @@
+ ", nonTTY = " + isNonTty
+ ", data enabled = " + isDataEnabled);
- getConfigInterface().setFeatureValue(
- ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
- TelephonyManager.NETWORK_TYPE_LTE,
- isFeatureOn ?
- ImsConfig.FeatureValueConstants.ON :
- ImsConfig.FeatureValueConstants.OFF,
- mImsConfigListener);
+ changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
return isFeatureOn;
}
@@ -1315,7 +1189,7 @@
* @return whether feature is On
* @throws ImsException
*/
- private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
+ private boolean updateWfcFeatureAndProvisionedValues() throws RemoteException {
TelephonyManager tm = new TelephonyManager(mContext, getSubId());
boolean isNetworkRoaming = tm.isNetworkRoaming();
boolean available = isWfcEnabledByPlatform();
@@ -1330,13 +1204,8 @@
+ ", mode = " + mode
+ ", roaming = " + roaming);
- getConfigInterface().setFeatureValue(
- ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
- TelephonyManager.NETWORK_TYPE_IWLAN,
- isFeatureOn ?
- ImsConfig.FeatureValueConstants.ON :
- ImsConfig.FeatureValueConstants.OFF,
- mImsConfigListener);
+ changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, isFeatureOn);
if (!isFeatureOn) {
mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
@@ -1359,11 +1228,6 @@
com.android.internal.R.bool.config_dynamic_bind_ims);
mConfigManager = (CarrierConfigManager) context.getSystemService(
Context.CARRIER_CONFIG_SERVICE);
- if (Looper.getMainLooper() != null) {
- mProvisionBackoff = new ExponentialBackoff(BACKOFF_INITIAL_DELAY_MS,
- BACKOFF_MAX_DELAY_MS, BACKOFF_MULTIPLIER,
- new Handler(Looper.getMainLooper()), this::handleUpdateProvisionedValues);
- }
createImsService();
}
@@ -1382,7 +1246,7 @@
public boolean isServiceAvailable() {
connectIfServiceIsAvailable();
// mImsServiceProxy will always create an ImsServiceProxy.
- return mImsServiceProxy.isBinderAlive();
+ return mMmTelFeatureConnection.isBinderAlive();
}
/*
@@ -1390,19 +1254,19 @@
*/
public boolean isServiceReady() {
connectIfServiceIsAvailable();
- return mImsServiceProxy.isBinderReady();
+ return mMmTelFeatureConnection.isBinderReady();
}
/**
* If the service is available, try to reconnect.
*/
public void connectIfServiceIsAvailable() {
- if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
+ if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
createImsService();
}
}
- public void setImsConfigListener(ImsConfigListener listener) {
+ public void setConfigListener(ImsConfigListener listener) {
mImsConfigListener = listener;
}
@@ -1411,9 +1275,9 @@
* Adds a callback for status changed events if the binder is already available. If it is not,
* this method will throw an ImsException.
*/
- public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c)
+ public void addNotifyStatusChangedCallbackIfAvailable(MmTelFeatureConnection.IFeatureUpdate c)
throws ImsException {
- if (!mImsServiceProxy.isBinderAlive()) {
+ if (!mMmTelFeatureConnection.isBinderAlive()) {
throw new ImsException("Binder is not active!",
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
@@ -1422,7 +1286,7 @@
}
}
- public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) {
+ public void removeNotifyStatusChangedCallback(MmTelFeatureConnection.IFeatureUpdate c) {
if (c != null) {
mStatusCallbacks.remove(c);
} else {
@@ -1432,63 +1296,30 @@
/**
* Opens the IMS service for making calls and/or receiving generic IMS calls.
- * The caller may make subsquent calls through {@link #makeCall}.
+ * The caller may make subsequent calls through {@link #makeCall}.
* 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 getCallId} and it can be used to take a call.
- *
- * @param serviceClass a service class specified in {@link ImsServiceClass}
- * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
- * @param incomingCallPendingIntent When an incoming call is received,
- * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} 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 identifier (greater than 0) for the specified service
- * @throws NullPointerException if {@code incomingCallPendingIntent}
- * or {@code listener} is null
+ * When the IMS service receives a new call, it will call
+ * {@link MmTelFeature.Listener#onIncomingCall}
+ * The listener contains a call ID extra {@link #getCallId} and it can be used to take a call.
+ * @param listener A {@link MmTelFeature.Listener}, which is the interface the
+ * {@link MmTelFeature} uses to notify the framework of updates
+ * @throws NullPointerException if {@code listener} is null
* @throws ImsException if calling the IMS service results in an error
* @see #getCallId
- * @see #getImsSessionId
*/
- public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
- ImsConnectionStateListener listener) throws ImsException {
+ public void open(MmTelFeature.Listener listener) throws ImsException {
checkAndThrowExceptionIfServiceUnavailable();
- if (incomingCallPendingIntent == null) {
- throw new NullPointerException("incomingCallPendingIntent can't be null");
- }
-
if (listener == null) {
throw new NullPointerException("listener can't be null");
}
- int result = 0;
-
try {
- // Register a stub implementation of the ImsRegistrationListener. There is the
- // possibility that if we use the real implementation of the ImsRegistrationListener,
- // it will be added twice.
- // TODO: Remove ImsRegistrationListener from startSession API (b/62588776)
- result = mImsServiceProxy.startSession(incomingCallPendingIntent,
- new ImsRegistrationListenerBase());
- addRegistrationListener(listener);
- log("open: Session started and registration listener added.");
+ mMmTelFeatureConnection.openConnection(listener);
} catch (RemoteException e) {
- throw new ImsException("open()", e,
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
-
- if (result <= 0) {
- // If the return value is a minus value,
- // it means that an error occurred in the service.
- // So, it needs to convert to the reason code specified in ImsReasonInfo.
- throw new ImsException("open()", (result * (-1)));
- }
-
- return result;
}
/**
@@ -1513,34 +1344,68 @@
* @param listener To listen to IMS registration events; It cannot be null
* @throws NullPointerException if {@code listener} is null
* @throws ImsException if calling the IMS service results in an error
+ * @deprecated use {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} and
+ * {@link #addCapabilitiesCallback(ImsFeature.CapabilityCallback)} instead.
*/
public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
if (listener == null) {
throw new NullPointerException("listener can't be null");
}
- // We only want this Proxy registered once.
- synchronized (mHasRegisteredLock) {
- if (!mHasRegisteredForProxy) {
- try {
- checkAndThrowExceptionIfServiceUnavailable();
- // TODO: Remove once new MmTelFeature is merged in
- mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy);
- IImsRegistration regBinder = mImsServiceProxy.getRegistration();
- if (regBinder != null) {
- regBinder.addRegistrationCallback(mRegistrationCallback);
- }
- log("Registration Callback/Listener registered.");
- // Only record if there isn't a RemoteException.
- mHasRegisteredForProxy = true;
- } catch (RemoteException e) {
- throw new ImsException("addRegistrationListener()", e,
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- }
+ addRegistrationCallback(listener);
+ // connect the ImsConnectionStateListener to the new CapabilityCallback.
+ addCapabilitiesCallback(new ImsFeature.CapabilityCallback() {
+ @Override
+ public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
+ listener.onFeatureCapabilityChangedAdapter(getRegistrationTech(), config);
}
+ });
+ log("Registration Callback registered.");
+ }
+
+ /**
+ * Adds a callback that gets called when IMS registration has changed.
+ * @param callback A {@link ImsRegistrationImplBase.Callback} that will notify the caller when
+ * IMS registration status has changed.
+ * @throws ImsException when the ImsService connection is not available.
+ */
+ public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback)
+ throws ImsException {
+ if (callback == null) {
+ throw new NullPointerException("registration callback can't be null");
}
- synchronized (mRegistrationListeners) {
- log("Local registration listener added: " + listener);
- mRegistrationListeners.add(listener);
+
+ checkAndThrowExceptionIfServiceUnavailable();
+ try {
+ mMmTelFeatureConnection.addRegistrationCallback(callback);
+ log("Registration Callback registered.");
+ // Only record if there isn't a RemoteException.
+ } catch (RemoteException e) {
+ throw new ImsException("addRegistrationCallback(IRIB)", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Adds a callback that gets called when MMTel capability status has changed, for example when
+ * Voice over IMS or VT over IMS is not available currently.
+ * @param callback A {@link ImsFeature.CapabilityCallback} that will notify the caller when
+ * MMTel capability status has changed.
+ * @throws ImsException when the ImsService connection is not available.
+ */
+ public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback)
+ throws ImsException {
+ if (callback == null) {
+ throw new NullPointerException("capabilities callback can't be null");
+ }
+
+ checkAndThrowExceptionIfServiceUnavailable();
+ try {
+ mMmTelFeatureConnection.addCapabilityCallback(callback);
+ log("Capability Callback registered.");
+ // Only record if there isn't a RemoteException.
+ } catch (RemoteException e) {
+ throw new ImsException("addCapabilitiesCallback(IF)", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
}
@@ -1558,33 +1423,38 @@
throw new NullPointerException("listener can't be null");
}
- synchronized (mRegistrationListeners) {
- log("Local registration listener removed: " + listener);
- mRegistrationListeners.remove(listener);
+ checkAndThrowExceptionIfServiceUnavailable();
+ try {
+ mMmTelFeatureConnection.removeRegistrationCallback(listener);
+ log("Registration Callback/Listener registered.");
+ // Only record if there isn't a RemoteException.
+ } catch (RemoteException e) {
+ throw new ImsException("addRegistrationCallback()", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech() {
+ try {
+ return mMmTelFeatureConnection.getRegistrationTech();
+ } catch (RemoteException e) {
+ Log.w(TAG, "getRegistrationTech: no connection to ImsService.");
+ return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
}
}
/**
- * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
+ * Closes the connection and removes all active callbacks.
* All the resources that were allocated to the service are also released.
- *
- * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
- * @throws ImsException if calling the IMS service results in an error
*/
- public void close(int sessionId) throws ImsException {
- checkAndThrowExceptionIfServiceUnavailable();
-
- try {
- mImsServiceProxy.endSession(sessionId);
- } catch (RemoteException e) {
- throw new ImsException("close()", e,
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- } finally {
- mUt = null;
- mConfig = null;
- mEcbm = null;
- mMultiEndpoint = null;
+ public void close() {
+ if (mMmTelFeatureConnection != null) {
+ mMmTelFeatureConnection.closeConnection();
}
+ mUt = null;
+ mConfig = null;
+ mEcbm = null;
+ mMultiEndpoint = null;
}
/**
@@ -1593,8 +1463,7 @@
* @return the Ut interface instance
* @throws ImsException if getting the Ut interface results in an error
*/
- public ImsUtInterface getSupplementaryServiceConfiguration()
- throws ImsException {
+ public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException {
// FIXME: manage the multiple Ut interfaces based on the session id
if (mUt != null && mUt.isBinderAlive()) {
return mUt;
@@ -1602,7 +1471,7 @@
checkAndThrowExceptionIfServiceUnavailable();
try {
- IImsUt iUt = mImsServiceProxy.getUtInterface();
+ IImsUt iUt = mMmTelFeatureConnection.getUtInterface();
if (iUt == null) {
throw new ImsException("getSupplementaryServiceConfiguration()",
@@ -1618,54 +1487,8 @@
}
/**
- * Checks if the IMS service has successfully registered to the IMS network
- * with the specified service & call type.
- *
- * @param serviceType 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 ImsException if calling the IMS service results in an error
- */
- public boolean isConnected(int serviceType, int callType)
- throws ImsException {
- checkAndThrowExceptionIfServiceUnavailable();
-
- try {
- return mImsServiceProxy.isConnected(serviceType, callType);
- } catch (RemoteException e) {
- throw new ImsException("isServiceConnected()", e,
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- }
- }
-
- /**
- * Checks if the specified IMS service is opend.
- *
- * @return true if the specified service id is opened; false otherwise
- * @throws ImsException if calling the IMS service results in an error
- */
- public boolean isOpened() throws ImsException {
- checkAndThrowExceptionIfServiceUnavailable();
-
- try {
- return mImsServiceProxy.isOpened();
- } catch (RemoteException e) {
- throw new ImsException("isOpened()", e,
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- }
- }
-
- /**
* Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
*
- * @param sessionId a session id which is obtained from {@link ImsManager#open}
* @param serviceType a service type that is specified in {@link ImsCallProfile}
* {@link ImsCallProfile#SERVICE_TYPE_NONE}
* {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
@@ -1682,12 +1505,11 @@
* @return a {@link ImsCallProfile} object
* @throws ImsException if calling the IMS service results in an error
*/
- public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
- throws ImsException {
+ public ImsCallProfile createCallProfile(int serviceType, int callType) throws ImsException {
checkAndThrowExceptionIfServiceUnavailable();
try {
- return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
+ return mMmTelFeatureConnection.createCallProfile(serviceType, callType);
} catch (RemoteException e) {
throw new ImsException("createCallProfile()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -1697,19 +1519,17 @@
/**
* Creates a {@link ImsCall} to make a call.
*
- * @param sessionId a session id which is obtained from {@link ImsManager#open}
* @param profile a call profile to make the call
* (it contains service type, call type, media information, etc.)
- * @param participants participants to invite the conference call
+ * @param callees participants to invite the conference call
* @param listener listen to the call events from {@link ImsCall}
* @return a {@link ImsCall} object
* @throws ImsException if calling the IMS service results in an error
*/
- public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
+ public ImsCall makeCall(ImsCallProfile profile, String[] callees,
ImsCall.Listener listener) throws ImsException {
if (DBG) {
- log("makeCall :: sessionId=" + sessionId
- + ", profile=" + profile);
+ log("makeCall :: profile=" + profile);
}
checkAndThrowExceptionIfServiceUnavailable();
@@ -1717,7 +1537,7 @@
ImsCall call = new ImsCall(mContext, profile);
call.setListener(listener);
- ImsCallSession session = createCallSession(sessionId, profile);
+ ImsCallSession session = createCallSession(profile);
if ((callees != null) && (callees.length == 1)) {
call.start(session, callees[0]);
@@ -1732,33 +1552,25 @@
* Creates a {@link ImsCall} to take an incoming call.
*
* @param sessionId a session id which is obtained from {@link ImsManager#open}
- * @param incomingCallIntent the incoming call broadcast intent
+ * @param incomingCallExtras the incoming call broadcast intent
* @param listener to listen to the call events from {@link ImsCall}
* @return a {@link ImsCall} object
* @throws ImsException if calling the IMS service results in an error
*/
- public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
+ public ImsCall takeCall(IImsCallSession session, Bundle incomingCallExtras,
ImsCall.Listener listener) throws ImsException {
if (DBG) {
- log("takeCall :: sessionId=" + sessionId
- + ", incomingCall=" + incomingCallIntent);
+ log("takeCall :: incomingCall=" + incomingCallExtras);
}
checkAndThrowExceptionIfServiceUnavailable();
- if (incomingCallIntent == null) {
+ if (incomingCallExtras == null) {
throw new ImsException("Can't retrieve session with null intent",
ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
}
- int incomingServiceId = getImsSessionId(incomingCallIntent);
-
- if (sessionId != incomingServiceId) {
- throw new ImsException("Service id is mismatched in the incoming call intent",
- ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
- }
-
- String callId = getCallId(incomingCallIntent);
+ String callId = getCallId(incomingCallExtras);
if (callId == null) {
throw new ImsException("Call ID missing in the incoming call intent",
@@ -1766,8 +1578,6 @@
}
try {
- IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
-
if (session == null) {
throw new ImsException("No pending session for the call",
ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
@@ -1797,7 +1607,7 @@
checkAndThrowExceptionIfServiceUnavailable();
try {
- IImsConfig config = mImsServiceProxy.getConfigInterface();
+ IImsConfig config = mMmTelFeatureConnection.getConfigInterface();
if (config == null) {
throw new ImsException("getConfigInterface()",
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
@@ -1810,6 +1620,47 @@
return mConfig;
}
+ public void changeMmTelCapability(
+ @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech,
+ boolean isEnabled) throws RemoteException {
+ CapabilityChangeRequest request = new CapabilityChangeRequest();
+ if (isEnabled) {
+ request.addCapabilitiesToEnableForTech(capability, radioTech);
+ } else {
+ request.addCapabilitiesToDisableForTech(capability, radioTech);
+ }
+ mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
+ if (mImsConfigListener != null) {
+ mImsConfigListener.onSetFeatureResponse(capability,
+ mMmTelFeatureConnection.getRegistrationTech(),
+ isEnabled ? ImsConfig.FeatureValueConstants.ON
+ : ImsConfig.FeatureValueConstants.OFF, -1);
+ }
+ }
+
+ public void setRttEnabled(boolean enabled) {
+ try {
+ setAdvanced4GMode(enabled || isEnhanced4gLteModeSettingEnabledByUser());
+ final int value = enabled ? ImsConfig.FeatureValueConstants.ON :
+ ImsConfig.FeatureValueConstants.OFF;
+ Thread thread = new Thread(() -> {
+ try {
+ Log.i(ImsManager.class.getSimpleName(), "Setting RTT enabled to " + enabled);
+ getConfigInterface().setProvisionedValue(
+ ImsConfig.ConfigConstants.RTT_SETTING_ENABLED, value);
+ } catch (ImsException e) {
+ Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to "
+ + enabled + ": " + e);
+ }
+ });
+ thread.start();
+ } catch (ImsException e) {
+ Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to " + enabled
+ + ": " + e);
+ }
+ }
+
/**
* Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
*/
@@ -1831,7 +1682,7 @@
checkAndThrowExceptionIfServiceUnavailable();
try {
- mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
+ mMmTelFeatureConnection.setUiTTYMode(uiTtyMode, onComplete);
} catch (RemoteException e) {
throw new ImsException("setTTYMode()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -1863,8 +1714,8 @@
return disconnectReasons;
}
- public int getImsServiceStatus() throws ImsException {
- return mImsServiceProxy.getFeatureStatus();
+ public int getImsServiceState() throws ImsException {
+ return mMmTelFeatureConnection.getFeatureState();
}
/**
@@ -1920,29 +1771,15 @@
/**
* Gets the call ID from the specified incoming call broadcast intent.
*
- * @param incomingCallIntent the incoming call broadcast intent
+ * @param incomingCallExtras the incoming call broadcast intent
* @return the call ID or null if the intent does not contain it
*/
- private static String getCallId(Intent incomingCallIntent) {
- if (incomingCallIntent == null) {
+ private static String getCallId(Bundle incomingCallExtras) {
+ if (incomingCallExtras == null) {
return null;
}
- return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
- }
-
- /**
- * Gets the service type from the specified incoming call broadcast intent.
- *
- * @param incomingCallIntent the incoming call broadcast intent
- * @return the session identifier or -1 if the intent does not contain it
- */
- private static int getImsSessionId(Intent incomingCallIntent) {
- if (incomingCallIntent == null) {
- return (-1);
- }
-
- return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
+ return incomingCallExtras.getString(EXTRA_CALL_ID);
}
/**
@@ -1951,10 +1788,10 @@
*/
private void checkAndThrowExceptionIfServiceUnavailable()
throws ImsException {
- if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
+ if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
createImsService();
- if (mImsServiceProxy == null) {
+ if (mMmTelFeatureConnection == null) {
throw new ImsException("Service is unavailable",
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
@@ -1968,30 +1805,21 @@
* 2) android.telephony.ims.ImsService implementation through ImsResolver.
*/
private void createImsService() {
- if (!mConfigDynamicBind) {
- // Deprecated method of binding
- Rlog.i(TAG, "Creating ImsService using ServiceManager");
- mImsServiceProxy = ImsServiceProxyCompat.create(mContext, mPhoneId, mDeathRecipient);
- } else {
- Rlog.i(TAG, "Creating ImsService using ImsResolver");
- mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId);
- }
+ Rlog.i(TAG, "Creating ImsService");
+ mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
+
// Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
- mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() {
+ mMmTelFeatureConnection.setStatusCallback(new MmTelFeatureConnection.IFeatureUpdate() {
@Override
public void notifyStateChanged() {
- mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged);
+ mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyStateChanged);
}
@Override
public void notifyUnavailable() {
- mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable);
+ mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyUnavailable);
}
});
- // We have created a new ImsService connection, signal for re-registration
- synchronized (mHasRegisteredLock) {
- mHasRegisteredForProxy = false;
- }
}
/**
@@ -1999,14 +1827,12 @@
* Use other methods, if applicable, instead of interacting with
* {@link ImsCallSession} directly.
*
- * @param serviceId a service id which is obtained from {@link ImsManager#open}
* @param profile a call profile to make the call
*/
- private ImsCallSession createCallSession(int serviceId,
- ImsCallProfile profile) throws ImsException {
+ private ImsCallSession createCallSession(ImsCallProfile profile) throws ImsException {
try {
// Throws an exception if the ImsService Feature is not ready to accept commands.
- return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile));
+ return new ImsCallSession(mMmTelFeatureConnection.createCallSession(profile));
} catch (RemoteException e) {
Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
throw new ImsException("createCallSession()", e,
@@ -2031,13 +1857,9 @@
* Used for turning on IMS.if its off already
*/
private void turnOnIms() throws ImsException {
- checkAndThrowExceptionIfServiceUnavailable();
-
- try {
- mImsServiceProxy.turnOnIms();
- } catch (RemoteException e) {
- throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- }
+ TelephonyManager tm = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ tm.enableIms(mPhoneId);
}
private boolean isImsTurnOffAllowed() {
@@ -2048,25 +1870,36 @@
private void setLteFeatureValues(boolean turnOn) {
log("setLteFeatureValues: " + turnOn);
- try {
- ImsConfig config = getConfigInterface();
- if (config != null) {
- config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
- TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
+ CapabilityChangeRequest request = new CapabilityChangeRequest();
+ if (turnOn) {
+ request.addCapabilitiesToEnableForTech(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ } else {
+ request.addCapabilitiesToDisableForTech(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ }
- if (isVolteEnabledByPlatform()) {
- boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
- CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
- boolean enableViLte = turnOn && isVtEnabledByUser() &&
- (ignoreDataEnabledChanged || isDataEnabled());
- config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
- TelephonyManager.NETWORK_TYPE_LTE,
- enableViLte ? 1 : 0,
- mImsConfigListener);
- }
+ if (isVolteEnabledByPlatform()) {
+ boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
+ boolean enableViLte = turnOn && isVtEnabledByUser() &&
+ (ignoreDataEnabledChanged || isDataEnabled());
+ if (enableViLte) {
+ request.addCapabilitiesToEnableForTech(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ } else {
+ request.addCapabilitiesToDisableForTech(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
}
- } catch (ImsException e) {
- loge("setLteFeatureValues: exception ", e);
+ }
+ try {
+ mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
+ } catch (RemoteException e) {
+ Log.e(TAG, "setLteFeatureValues: Exception: " + e.getMessage());
}
}
@@ -2094,13 +1927,9 @@
* Once turned off, all calls will be over CS.
*/
private void turnOffIms() throws ImsException {
- checkAndThrowExceptionIfServiceUnavailable();
-
- try {
- mImsServiceProxy.turnOffIms();
- } catch (RemoteException e) {
- throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
- }
+ TelephonyManager tm = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ tm.disableIms(mPhoneId);
}
private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
@@ -2117,7 +1946,7 @@
private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
@Override
public void binderDied() {
- mImsServiceProxy = null;
+ mMmTelFeatureConnection = null;
mUt = null;
mConfig = null;
mEcbm = null;
@@ -2126,270 +1955,19 @@
}
/**
- * Stub implementation of the Registration listener that provides no functionality.
- */
- private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub {
-
- @Override
- public void registrationConnected() throws RemoteException {
- }
-
- @Override
- public void registrationProgressing() throws RemoteException {
- }
-
- @Override
- public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
- }
-
- @Override
- public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
- }
-
- @Override
- public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
- }
-
- @Override
- public void registrationResumed() throws RemoteException {
- }
-
- @Override
- public void registrationSuspended() throws RemoteException {
- }
-
- @Override
- public void registrationServiceCapabilityChanged(int serviceClass, int event)
- throws RemoteException {
- }
-
- @Override
- public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
- int[] disabledFeatures) throws RemoteException {
- }
-
- @Override
- public void voiceMessageCountUpdate(int count) throws RemoteException {
- }
-
- @Override
- public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
- }
-
- @Override
- public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
- throws RemoteException {
- }
- }
-
- /**
- * Adapter class for {@link IImsRegistrationListener}.
- */
- private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
-
- @Deprecated
- public void registrationConnected() {
- if (DBG) {
- log("registrationConnected ::");
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsConnected(
- ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
- }
- }
-
- @Deprecated
- public void registrationProgressing() {
- if (DBG) {
- log("registrationProgressing ::");
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsProgressing(
- ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
- }
- }
-
- @Override
- public void registrationConnectedWithRadioTech(int imsRadioTech) {
- // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
- // values in ServiceState.java.
- if (DBG) {
- log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech));
- }
- }
-
- @Override
- public void registrationProgressingWithRadioTech(int imsRadioTech) {
- // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
- // values in ServiceState.java.
- if (DBG) {
- log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech));
- }
- }
-
- @Override
- public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
- if (DBG) {
- log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
- }
-
- addToRecentDisconnectReasons(imsReasonInfo);
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo));
- }
- }
-
- @Override
- public void registrationResumed() {
- if (DBG) {
- log("registrationResumed ::");
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed);
- }
- }
-
- @Override
- public void registrationSuspended() {
- if (DBG) {
- log("registrationSuspended ::");
- }
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended);
- }
- }
-
- @Override
- public void registrationServiceCapabilityChanged(int serviceClass, int event) {
- log("registrationServiceCapabilityChanged :: serviceClass=" +
- serviceClass + ", event=" + event);
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onImsConnected(
- ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
- }
- }
-
- @Override
- public void registrationFeatureCapabilityChanged(int serviceClass,
- int[] enabledFeatures, int[] disabledFeatures) {
- log("registrationFeatureCapabilityChanged :: serviceClass=" +
- serviceClass);
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass,
- enabledFeatures, disabledFeatures));
- }
- }
-
- @Override
- public void voiceMessageCountUpdate(int count) {
- log("voiceMessageCountUpdate :: count=" + count);
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count));
- }
- }
-
- @Override
- public void registrationAssociatedUriChanged(Uri[] uris) {
- if (DBG) log("registrationAssociatedUriChanged ::");
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris));
- }
- }
-
- @Override
- public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
- if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
- ", imsReasonInfo=" + imsReasonInfo);
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech,
- imsReasonInfo));
- }
- }
- }
-
- // New API for Registration, uses ImsConnectionStateListener for backwards compatibility with
- // deprecated APIs.
- private class ImsRegistrationCallback extends IImsRegistrationCallback.Stub {
-
- @Override
- public void onRegistered(int imsRadioTech) {
- if (DBG) log("onRegistered ::");
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onRegistered(imsRadioTech));
- }
- }
-
- @Override
- public void onRegistering(int imsRadioTech) {
- if (DBG) log("onRegistering ::");
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onRegistering(imsRadioTech));
- }
- }
-
- @Override
- public void onDeregistered(ImsReasonInfo imsReasonInfo) {
- if (DBG) log("onDeregistered ::");
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onDeregistered(imsReasonInfo));
- }
- }
-
- @Override
- public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
- if (DBG) log("onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
- ", imsReasonInfo=" + imsReasonInfo);
-
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
- imsReasonInfo));
- }
- }
-
- @Override
- public void onSubscriberAssociatedUriChanged(Uri[] uris) {
- if (DBG) log("onSubscriberAssociatedUriChanged");
- synchronized (mRegistrationListeners) {
- mRegistrationListeners.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
- }
- }
- }
-
- /**
* Gets the ECBM interface to request ECBM exit.
*
- * @param serviceId a service id which is obtained from {@link ImsManager#open}
* @return the ECBM interface instance
* @throws ImsException if getting the ECBM interface results in an error
*/
- public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
+ public ImsEcbm getEcbmInterface() throws ImsException {
if (mEcbm != null && mEcbm.isBinderAlive()) {
return mEcbm;
}
checkAndThrowExceptionIfServiceUnavailable();
try {
- IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
+ IImsEcbm iEcbm = mMmTelFeatureConnection.getEcbmInterface();
if (iEcbm == null) {
throw new ImsException("getEcbmInterface()",
@@ -2406,7 +1984,7 @@
public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
byte[] pdu) throws ImsException {
try {
- mImsServiceProxy.sendSms(token, messageRef, format, smsc, isRetry, pdu);
+ mMmTelFeatureConnection.sendSms(token, messageRef, format, smsc, isRetry, pdu);
} catch (RemoteException e) {
throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
@@ -2414,7 +1992,7 @@
public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
try {
- mImsServiceProxy.acknowledgeSms(token, messageRef, result);
+ mMmTelFeatureConnection.acknowledgeSms(token, messageRef, result);
} catch (RemoteException e) {
throw new ImsException("acknowledgeSms()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -2423,7 +2001,7 @@
public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
try {
- mImsServiceProxy.acknowledgeSmsReport(token, messageRef, result);
+ mMmTelFeatureConnection.acknowledgeSmsReport(token, messageRef, result);
} catch (RemoteException e) {
throw new ImsException("acknowledgeSmsReport()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -2432,7 +2010,7 @@
public String getSmsFormat() throws ImsException{
try {
- return mImsServiceProxy.getSmsFormat();
+ return mMmTelFeatureConnection.getSmsFormat();
} catch (RemoteException e) {
throw new ImsException("getSmsFormat()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -2441,7 +2019,7 @@
public void setSmsListener(IImsSmsListener listener) throws ImsException {
try {
- mImsServiceProxy.setSmsListener(listener);
+ mMmTelFeatureConnection.setSmsListener(listener);
} catch (RemoteException e) {
throw new ImsException("setSmsListener()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
@@ -2450,36 +2028,27 @@
public void onSmsReady() throws ImsException{
try {
- mImsServiceProxy.onSmsReady();
+ mMmTelFeatureConnection.onSmsReady();
} catch (RemoteException e) {
throw new ImsException("onSmsReady()", e,
ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
}
}
- public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback) {
- // TODO: implement (coming in ag/3472519)
- }
-
- public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback) {
- // TODO: implement (coming in ag/3472519)
- }
-
/**
* Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
*
- * @param serviceId a service id which is obtained from {@link ImsManager#open}
* @return the multi-endpoint interface instance
* @throws ImsException if getting the multi-endpoint interface results in an error
*/
- public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
+ public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
return mMultiEndpoint;
}
checkAndThrowExceptionIfServiceUnavailable();
try {
- IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
+ IImsMultiEndpoint iImsMultiEndpoint = mMmTelFeatureConnection.getMultiEndpointInterface();
if (iImsMultiEndpoint == null) {
throw new ImsException("getMultiEndpointInterface()",
@@ -2518,7 +2087,9 @@
public void factoryReset() {
// Set VoLTE to default
SubscriptionManager.setSubscriptionProperty(getSubId(),
- SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(true));
+ SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
+ booleanToPropertyString(getBooleanCarrierConfig(
+ CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
// Set VoWiFi to default
SubscriptionManager.setSubscriptionProperty(getSubId(),
@@ -2547,40 +2118,22 @@
}
private boolean isDataEnabled() {
- return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
- }
-
- /**
- * Set data enabled/disabled flag.
- * @param enabled True if data is enabled, otherwise disabled.
- */
- public void setDataEnabled(boolean enabled) {
- log("setDataEnabled: " + enabled);
- SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
+ return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled();
}
private boolean isVolteProvisioned() {
- return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
- }
-
- private void setVolteProvisionedProperty(boolean provisioned) {
- SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
+ return getProvisionedBoolNoException(
+ ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
}
private boolean isWfcProvisioned() {
- return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
- }
-
- private void setWfcProvisionedProperty(boolean provisioned) {
- SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
+ return getProvisionedBoolNoException(
+ ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
}
private boolean isVtProvisioned() {
- return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
- }
-
- private void setVtProvisionedProperty(boolean provisioned) {
- SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
+ return getProvisionedBoolNoException(
+ ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
}
private static String booleanToPropertyString(boolean bool) {
@@ -2592,7 +2145,7 @@
pw.println("ImsManager:");
pw.println(" mPhoneId = " + mPhoneId);
pw.println(" mConfigUpdated = " + mConfigUpdated);
- pw.println(" mImsServiceProxy = " + mImsServiceProxy);
+ pw.println(" mImsServiceProxy = " + mMmTelFeatureConnection);
pw.println(" mDataEnabled = " + isDataEnabled());
pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
diff --git a/src/java/com/android/ims/ImsMultiEndpoint.java b/src/java/com/android/ims/ImsMultiEndpoint.java
index 9692696..1315dbd 100644
--- a/src/java/com/android/ims/ImsMultiEndpoint.java
+++ b/src/java/com/android/ims/ImsMultiEndpoint.java
@@ -21,6 +21,8 @@
import android.os.RemoteException;
import android.telephony.Rlog;
+import android.telephony.ims.ImsExternalCallState;
+import android.telephony.ims.ImsReasonInfo;
import java.util.List;
diff --git a/src/java/com/android/ims/ImsServiceBase.java b/src/java/com/android/ims/ImsServiceBase.java
index 66122df..0a15c9d 100644
--- a/src/java/com/android/ims/ImsServiceBase.java
+++ b/src/java/com/android/ims/ImsServiceBase.java
@@ -18,7 +18,7 @@
import android.app.PendingIntent;
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsCallSessionListener;
import com.android.ims.internal.IImsConfig;
diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java
deleted file mode 100644
index a874436..0000000
--- a/src/java/com/android/ims/ImsServiceProxy.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.ims;
-
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telephony.Rlog;
-import android.telephony.TelephonyManager;
-import android.telephony.ims.aidl.IImsCallSessionListener;
-import android.telephony.ims.feature.ImsFeature;
-import android.telephony.SmsMessage;
-import android.telephony.ims.internal.stub.SmsImplBase;
-import android.util.Log;
-
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsConfig;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsServiceFeatureCallback;
-import com.android.ims.internal.IImsSmsListener;
-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 {
-
- protected static final String TAG = "ImsServiceProxy";
- protected final int mSlotId;
- protected IBinder mBinder;
- private final int mSupportedFeature;
- private Context mContext;
-
- // Start by assuming the proxy is available for usage.
- private boolean mIsAvailable = true;
- // ImsFeature Status from the ImsService. Cached.
- private Integer mFeatureStatusCached = null;
- private IFeatureUpdate mStatusCallback;
- private final Object mLock = new Object();
-
- public static ImsServiceProxy create(Context context , int slotId) {
- ImsServiceProxy serviceProxy = new ImsServiceProxy(context, slotId, ImsFeature.MMTEL);
-
- TelephonyManager tm = getTelephonyManager(context);
- if (tm == null) {
- Rlog.w(TAG, "getServiceProxy: TelephonyManager is null!");
- // Binder can be unset in this case because it will be torn down/recreated as part of
- // a retry mechanism until the serviceProxy binder is set successfully.
- return serviceProxy;
- }
-
- IImsMMTelFeature binder = tm.getImsMMTelFeatureAndListen(slotId,
- serviceProxy.getListener());
- if (binder != null) {
- serviceProxy.setBinder(binder.asBinder());
- // Trigger the cache to be updated for feature status.
- serviceProxy.getFeatureStatus();
- } else {
- Rlog.w(TAG, "getServiceProxy: binder is null! Phone Id: " + slotId);
- }
- return serviceProxy;
- }
-
- public static TelephonyManager getTelephonyManager(Context context) {
- return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- }
-
- public interface IFeatureUpdate {
- /**
- * Called when the ImsFeature has changed its state. Use
- * {@link ImsFeature#getFeatureState()} to get the new state.
- */
- void notifyStateChanged();
-
- /**
- * Called when the ImsFeature has become unavailable due to the binder switching or app
- * crashing. A new ImsServiceProxy should be requested for that feature.
- */
- void notifyUnavailable();
- }
-
- private final IImsServiceFeatureCallback mListenerBinder =
- new IImsServiceFeatureCallback.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(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(TAG, "Feature disabled on slotId: " + slotId + " for feature: " +
- feature);
- mIsAvailable = false;
- if (mStatusCallback != null) {
- mStatusCallback.notifyUnavailable();
- }
- }
- }
- }
-
- @Override
- public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException {
- synchronized (mLock) {
- Log.i(TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature +
- " status: " + status);
- if (mSlotId == slotId && feature == mSupportedFeature) {
- mFeatureStatusCached = status;
- if (mStatusCallback != null) {
- mStatusCallback.notifyStateChanged();
- }
- }
- }
- }
- };
-
- public ImsServiceProxy(Context context, int slotId, IBinder binder, int featureType) {
- mSlotId = slotId;
- mBinder = binder;
- mSupportedFeature = featureType;
- mContext = context;
- }
-
- public ImsServiceProxy(Context context, int slotId, int featureType) {
- this(context, slotId, null, featureType);
- }
-
- public @Nullable IImsRegistration getRegistration() {
- TelephonyManager tm = getTelephonyManager(mContext);
- return tm != null ? tm.getImsRegistration(mSlotId, ImsFeature.MMTEL) : null;
- }
-
- public IImsServiceFeatureCallback getListener() {
- return mListenerBinder;
- }
-
- public void setBinder(IBinder binder) {
- mBinder = binder;
- }
-
- public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).startSession(incomingCallIntent, listener);
- }
- }
-
- public void endSession(int sessionId) throws RemoteException {
- synchronized (mLock) {
- // Only check to make sure the binder connection still exists. This method should
- // still be able to be called when the state is STATE_NOT_AVAILABLE.
- checkBinderConnection();
- getServiceInterface(mBinder).endSession(sessionId);
- }
- }
-
- public boolean isConnected(int callServiceType, int callType)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).isConnected(callServiceType, callType);
- }
- }
-
- public boolean isOpened() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).isOpened();
- }
- }
-
- public void addRegistrationListener(IImsRegistrationListener listener)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).addRegistrationListener(listener);
- }
- }
-
- public void removeRegistrationListener(IImsRegistrationListener listener)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).removeRegistrationListener(listener);
- }
- }
-
- public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).createCallProfile(sessionId, callServiceType,
- callType);
- }
- }
-
- public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).createCallSession(sessionId, profile);
- }
- }
-
- public IImsCallSession getPendingCallSession(int sessionId, String callId)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getPendingCallSession(sessionId, callId);
- }
- }
-
- public IImsUt getUtInterface() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getUtInterface();
- }
- }
-
- public IImsConfig getConfigInterface() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getConfigInterface();
- }
- }
-
- public void turnOnIms() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).turnOnIms();
- }
- }
-
- public void turnOffIms() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).turnOffIms();
- }
- }
-
- public IImsEcbm getEcbmInterface() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getEcbmInterface();
- }
- }
-
- public void setUiTTYMode(int uiTtyMode, Message onComplete)
- throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).setUiTTYMode(uiTtyMode, onComplete);
- }
- }
-
- public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getMultiEndpointInterface();
- }
- }
-
- /**
- * @return an integer describing the current Feature Status, defined in
- * {@link ImsFeature.ImsState}.
- */
- public int getFeatureStatus() {
- synchronized (mLock) {
- if (isBinderAlive() && mFeatureStatusCached != null) {
- Log.i(TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached);
- 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;
- }
- Log.i(TAG, "getFeatureStatus - returning " + 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();
- } 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(IFeatureUpdate c) {
- mStatusCallback = c;
- }
-
- public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
- byte[] pdu) throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).sendSms(token, messageRef, format, smsc, isRetry,
- pdu);
- }
- }
-
- public void acknowledgeSms(int token, int messageRef,
- @SmsImplBase.SendStatusResult int result) throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).acknowledgeSms(token, messageRef, result);
- }
- }
-
- public void acknowledgeSmsReport(int token, int messageRef,
- @SmsImplBase.StatusReportResult int result) throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).acknowledgeSmsReport(token, messageRef, result);
- }
- }
-
- public String getSmsFormat() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- return getServiceInterface(mBinder).getSmsFormat();
- }
- }
-
- public void onSmsReady() throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).onSmsReady();
- }
- }
-
- public void setSmsListener(IImsSmsListener listener) throws RemoteException {
- synchronized (mLock) {
- checkServiceIsReady();
- getServiceInterface(mBinder).setSmsListener(listener);
- }
- }
-
- /**
- * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
- * method returns false, it doesn't mean that the Binder connection is not available (use
- * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
- * at this time.
- *
- * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
- * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_NOT_AVAILABLE}.
- */
- public boolean isBinderReady() {
- return isBinderAlive() && getFeatureStatus() == ImsFeature.STATE_READY;
- }
-
- /**
- * @return false if the binder connection is no longer alive.
- */
- public boolean isBinderAlive() {
- return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
- }
-
- protected void checkServiceIsReady() throws RemoteException {
- if (!isBinderReady()) {
- throw new RemoteException("ImsServiceProxy is not ready to accept commands.");
- }
- }
-
- private IImsMMTelFeature getServiceInterface(IBinder b) {
- return IImsMMTelFeature.Stub.asInterface(b);
- }
-
- protected void checkBinderConnection() throws RemoteException {
- if (!isBinderAlive()) {
- throw new RemoteException("ImsServiceProxy is not available for that feature.");
- }
- }
-}
diff --git a/src/java/com/android/ims/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java
deleted file mode 100644
index d5f211a..0000000
--- a/src/java/com/android/ims/ImsServiceProxyCompat.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.ims;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.telephony.Rlog;
-import android.telephony.TelephonyManager;
-import android.telephony.ims.feature.ImsFeature;
-
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
-import com.android.ims.internal.IImsConfig;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsService;
-import com.android.ims.internal.IImsUt;
-
-/**
- * Compatibility class that implements the new ImsService MMTelFeature interface, but
- * uses the old IImsService interface to support older devices that implement the deprecated
- * opt/net/ims interface.
- * @hide
- */
-
-public class ImsServiceProxyCompat extends ImsServiceProxy {
-
- private static final int SERVICE_ID = ImsFeature.MMTEL;
-
- /**
- * For accessing the IMS related service.
- * Internal use only.
- * @hide
- */
- private static final String IMS_SERVICE = "ims";
-
- public static ImsServiceProxyCompat create(Context context, int slotId,
- IBinder.DeathRecipient recipient) {
- IBinder binder = ServiceManager.checkService(IMS_SERVICE);
-
- if (binder != null) {
- try {
- binder.linkToDeath(recipient, 0);
- } catch (RemoteException e) {
- }
- }
-
- // If the proxy is created with a null binder, subsequent calls that depend on a live
- // binder will fail, causing this structure to be torn down and created again.
- return new ImsServiceProxyCompat(context, slotId, binder);
- }
-
- public ImsServiceProxyCompat(Context context, int slotId, IBinder binder) {
- super(context, slotId, binder, SERVICE_ID);
- }
-
- @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 callServiceType, int callType)
- throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).isConnected(SERVICE_ID, callServiceType, callType);
- }
-
- @Override
- public boolean isOpened() throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).isOpened(SERVICE_ID);
- }
-
- @Override
- public void addRegistrationListener(IImsRegistrationListener listener)
- throws RemoteException {
- checkBinderConnection();
- getServiceInterface(mBinder).addRegistrationListener(mSlotId, ImsFeature.MMTEL, listener);
- }
-
- @Override
- public void removeRegistrationListener(IImsRegistrationListener listener)
- throws RemoteException {
- // 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)
- throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).createCallSession(sessionId, profile, null);
- }
-
- @Override
- public IImsCallSession getPendingCallSession(int sessionId, String callId)
- throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).getPendingCallSession(sessionId, callId);
- }
-
- @Override
- public IImsUt getUtInterface() throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).getUtInterface(SERVICE_ID);
- }
-
- @Override
- public IImsConfig getConfigInterface() throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).getConfigInterface(mSlotId);
- }
-
- @Override
- public void turnOnIms() throws RemoteException {
- checkBinderConnection();
- getServiceInterface(mBinder).turnOnIms(mSlotId);
- }
-
- @Override
- public void turnOffIms() throws RemoteException {
- checkBinderConnection();
- getServiceInterface(mBinder).turnOffIms(mSlotId);
- }
-
- @Override
- public IImsEcbm getEcbmInterface() throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).getEcbmInterface(SERVICE_ID);
- }
-
- @Override
- public void setUiTTYMode(int uiTtyMode, Message onComplete)
- throws RemoteException {
- checkBinderConnection();
- getServiceInterface(mBinder).setUiTTYMode(SERVICE_ID, uiTtyMode, onComplete);
- }
-
- @Override
- public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
- checkBinderConnection();
- return getServiceInterface(mBinder).getMultiEndpointInterface(SERVICE_ID);
- }
- @Override
- public int getFeatureStatus() {
- return ImsFeature.STATE_READY;
- }
-
- @Override
- public boolean isBinderAlive() {
- return mBinder != null && mBinder.isBinderAlive();
- }
-
- private IImsService getServiceInterface(IBinder b) {
- return IImsService.Stub.asInterface(b);
- }
-}
diff --git a/src/java/com/android/ims/ImsUt.java b/src/java/com/android/ims/ImsUt.java
index eaeb551..b3d4c8a 100644
--- a/src/java/com/android/ims/ImsUt.java
+++ b/src/java/com/android/ims/ImsUt.java
@@ -27,6 +27,10 @@
import android.os.Registrant;
import android.os.RemoteException;
import android.telephony.Rlog;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
+import android.telephony.ims.ImsSsInfo;
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java
new file mode 100644
index 0000000..571670d
--- /dev/null
+++ b/src/java/com/android/ims/MmTelFeatureConnection.java
@@ -0,0 +1,623 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.ImsSmsImplBase;
+import android.util.Log;
+
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsServiceFeatureCallback;
+import com.android.ims.internal.IImsUt;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A container of the IImsServiceController binder, which implements all of the ImsFeatures that
+ * the platform currently supports: MMTel and RCS.
+ * @hide
+ */
+
+public class MmTelFeatureConnection {
+
+ protected static final String TAG = "MmTelFeatureConnection";
+ protected final int mSlotId;
+ protected IBinder mBinder;
+ private Context mContext;
+
+ // Start by assuming the proxy is available for usage.
+ private volatile boolean mIsAvailable = true;
+ // ImsFeature Status from the ImsService. Cached.
+ private Integer mFeatureStateCached = null;
+ private IFeatureUpdate mStatusCallback;
+ private final Object mLock = new Object();
+
+ private MmTelFeature.Listener mMmTelFeatureListener;
+
+ private abstract class CallbackAdapterManager<T> {
+ private static final String TAG = "CallbackAdapterManager";
+
+ protected final Set<T> mLocalCallbacks = new HashSet<>();
+ private boolean mHasConnected = false;
+
+ public void addCallback(T localCallback) throws RemoteException {
+ // We only one one binding to the ImsService per process.
+ // Store any more locally.
+ synchronized (mLock) {
+ if(!mHasConnected) {
+ // throws a RemoteException if a connection can not be established.
+ if(createConnection()) {
+ mHasConnected = true;
+ } else {
+ throw new RemoteException("Can not create connection!");
+ }
+ }
+ Log.i(TAG, "Local callback added: " + localCallback);
+ mLocalCallbacks.add(localCallback);
+ }
+ }
+
+ public void removeCallback(T localCallback) {
+ // We only maintain one binding to the ImsService per process.
+ synchronized (mLock) {
+ Log.i(TAG, "Local callback removed: " + localCallback);
+ mLocalCallbacks.remove(localCallback);
+ // If we have removed all local callbacks, remove callback to ImsService.
+ if(mHasConnected) {
+ if (mLocalCallbacks.isEmpty()) {
+ removeConnection();
+ mHasConnected = false;
+ }
+ }
+ }
+ }
+
+ public void close() {
+ synchronized (mLock) {
+ if (mHasConnected) {
+ removeConnection();
+ // Still mark the connection as disconnected, even if this fails.
+ mHasConnected = false;
+ }
+ Log.i(TAG, "Closing connection and clearing callbacks");
+ mLocalCallbacks.clear();
+ }
+ }
+
+ abstract boolean createConnection() throws RemoteException;
+
+ abstract void removeConnection();
+ }
+ private ImsRegistrationCallbackAdapter mRegistrationCallbackManager
+ = new ImsRegistrationCallbackAdapter();
+ private class ImsRegistrationCallbackAdapter
+ extends CallbackAdapterManager<ImsRegistrationImplBase.Callback> {
+ private final RegistrationCallbackAdapter mRegistrationCallbackAdapter
+ = new RegistrationCallbackAdapter();
+
+ private class RegistrationCallbackAdapter extends IImsRegistrationCallback.Stub {
+
+ @Override
+ public void onRegistered(int imsRadioTech) {
+ Log.i(TAG, "onRegistered ::");
+
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech));
+ }
+ }
+
+ @Override
+ public void onRegistering(int imsRadioTech) {
+ Log.i(TAG, "onRegistering ::");
+
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech));
+ }
+ }
+
+ @Override
+ public void onDeregistered(ImsReasonInfo imsReasonInfo) {
+ Log.i(TAG, "onDeregistered ::");
+
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo));
+ }
+ }
+
+ @Override
+ public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
+ Log.i(TAG, "onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
+ ", imsReasonInfo=" + imsReasonInfo);
+
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
+ imsReasonInfo));
+ }
+ }
+
+ @Override
+ public void onSubscriberAssociatedUriChanged(Uri[] uris) {
+ Log.i(TAG, "onSubscriberAssociatedUriChanged");
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
+ }
+ }
+ }
+
+ @Override
+ boolean createConnection() throws RemoteException {
+ IImsRegistration imsRegistration = getRegistration();
+ if (imsRegistration != null) {
+ getRegistration().addRegistrationCallback(mRegistrationCallbackAdapter);
+ return true;
+ } else {
+ Log.e(TAG, "ImsRegistration is null");
+ return false;
+ }
+ }
+
+ @Override
+ void removeConnection() {
+ IImsRegistration imsRegistration = getRegistration();
+ if (imsRegistration != null) {
+ try {
+ getRegistration().addRegistrationCallback(mRegistrationCallbackAdapter);
+ } catch (RemoteException e) {
+ Log.w(TAG, "removeConnection: couldn't remove registration callback");
+ }
+ } else {
+ Log.e(TAG, "ImsRegistration is null");
+ }
+ }
+ }
+
+ private final CapabilityCallbackManager mCapabilityCallbackManager
+ = new CapabilityCallbackManager();
+ private class CapabilityCallbackManager
+ extends CallbackAdapterManager<ImsFeature.CapabilityCallback> {
+ private final CapabilityCallbackAdapter mCallbackAdapter = new CapabilityCallbackAdapter();
+
+ private class CapabilityCallbackAdapter extends ImsFeature.CapabilityCallback {
+ // Called when the Capabilities Status on this connection have changed.
+ @Override
+ public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
+ synchronized (mLock) {
+ mLocalCallbacks.forEach(
+ callback -> callback.onCapabilitiesStatusChanged(config));
+ }
+ }
+ }
+
+ @Override
+ boolean createConnection() throws RemoteException {
+ IImsMmTelFeature binder = getServiceInterface(mBinder);
+ if (binder != null) {
+ binder.addCapabilityCallback(mCallbackAdapter);
+ return true;
+ } else {
+ Log.w(TAG, "create: Couldn't get IImsMmTelFeature binder");
+ return false;
+ }
+ }
+
+ @Override
+ void removeConnection() {
+ IImsMmTelFeature binder = getServiceInterface(mBinder);
+ if (binder != null) {
+ try {
+ binder.removeCapabilityCallback(mCallbackAdapter);
+ } catch (RemoteException e) {
+ Log.w(TAG, "remove: IImsMmTelFeature binder is dead");
+ }
+ } else {
+ Log.w(TAG, "remove: Couldn't get IImsMmTelFeature binder");
+ }
+ }
+ }
+
+
+ public static MmTelFeatureConnection create(Context context , int slotId) {
+ MmTelFeatureConnection serviceProxy = new MmTelFeatureConnection(context, slotId);
+
+ TelephonyManager tm = getTelephonyManager(context);
+ if (tm == null) {
+ Rlog.w(TAG, "create: TelephonyManager is null!");
+ // Binder can be unset in this case because it will be torn down/recreated as part of
+ // a retry mechanism until the serviceProxy binder is set successfully.
+ return serviceProxy;
+ }
+
+ IImsMmTelFeature binder = tm.getImsMmTelFeatureAndListen(slotId,
+ serviceProxy.getListener());
+ if (binder != null) {
+ serviceProxy.setBinder(binder.asBinder());
+ // Trigger the cache to be updated for feature status.
+ serviceProxy.getFeatureState();
+ } else {
+ Rlog.w(TAG, "create: binder is null! Slot Id: " + slotId);
+ }
+ return serviceProxy;
+ }
+
+ public static TelephonyManager getTelephonyManager(Context context) {
+ return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
+ public interface IFeatureUpdate {
+ /**
+ * Called when the ImsFeature has changed its state. Use
+ * {@link ImsFeature#getFeatureState()} to get the new state.
+ */
+ void notifyStateChanged();
+
+ /**
+ * Called when the ImsFeature has become unavailable due to the binder switching or app
+ * crashing. A new ImsServiceProxy should be requested for that feature.
+ */
+ void notifyUnavailable();
+ }
+
+ private final IImsServiceFeatureCallback mListenerBinder =
+ new IImsServiceFeatureCallback.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 == ImsFeature.FEATURE_MMTEL) {
+ Log.i(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 == ImsFeature.FEATURE_MMTEL) {
+ Log.i(TAG, "Feature disabled on slotId: " + slotId + " for feature: " +
+ feature);
+ mIsAvailable = false;
+ if (mStatusCallback != null) {
+ mStatusCallback.notifyUnavailable();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException {
+ synchronized (mLock) {
+ Log.i(TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature +
+ " status: " + status);
+ if (mSlotId == slotId && feature == ImsFeature.FEATURE_MMTEL) {
+ mFeatureStateCached = status;
+ if (mStatusCallback != null) {
+ mStatusCallback.notifyStateChanged();
+ }
+ }
+ }
+ }
+ };
+
+ public MmTelFeatureConnection(Context context, int slotId) {
+ mSlotId = slotId;
+ mContext = context;
+ }
+
+ private @Nullable IImsRegistration getRegistration() {
+ TelephonyManager tm = getTelephonyManager(mContext);
+ return tm != null ? tm.getImsRegistration(mSlotId, ImsFeature.FEATURE_MMTEL) : null;
+ }
+
+ private IImsConfig getConfig() {
+ TelephonyManager tm = getTelephonyManager(mContext);
+ return tm != null ? tm.getImsConfig(mSlotId, ImsFeature.FEATURE_MMTEL) : null;
+ }
+
+ public IImsServiceFeatureCallback getListener() {
+ return mListenerBinder;
+ }
+
+ public void setBinder(IBinder binder) {
+ mBinder = binder;
+ }
+
+ /**
+ * Opens the connection to the {@link MmTelFeature} and establishes a listener back to the
+ * framework. Calling this method multiple times will reset the listener attached to the
+ * {@link MmTelFeature}.
+ * @param listener A {@link MmTelFeature.Listener} that will be used by the {@link MmTelFeature}
+ * to notify the framework of updates.
+ */
+ public void openConnection(MmTelFeature.Listener listener) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ mMmTelFeatureListener = listener;
+ getServiceInterface(mBinder).setListener(mMmTelFeatureListener);
+ }
+ }
+
+ public void closeConnection() {
+ mRegistrationCallbackManager.close();
+ mCapabilityCallbackManager.close();
+ try {
+ getServiceInterface(mBinder).setListener(null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "closeConnection: couldn't remove listener!");
+ }
+ }
+
+ public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback)
+ throws RemoteException {
+ mRegistrationCallbackManager.addCallback(callback);
+ }
+
+ public void removeRegistrationCallback(ImsRegistrationImplBase.Callback callback)
+ throws RemoteException {
+ mRegistrationCallbackManager.removeCallback(callback);
+ }
+
+ public void addCapabilityCallback(ImsFeature.CapabilityCallback callback)
+ throws RemoteException {
+ mCapabilityCallbackManager.addCallback(callback);
+ }
+
+ public void removeCapabilityCallback(ImsFeature.CapabilityCallback callback)
+ throws RemoteException {
+ mCapabilityCallbackManager.removeCallback(callback);
+ }
+
+ public void changeEnabledCapabilities(CapabilityChangeRequest request,
+ ImsFeature.CapabilityCallback callback) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).changeCapabilitiesConfiguration(request, callback);
+ }
+ }
+
+ public void queryEnabledCapabilities(int capability, int radioTech,
+ ImsFeature.CapabilityCallback callback) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).queryCapabilityConfiguration(capability, radioTech,
+ callback);
+ }
+ }
+
+ public MmTelFeature.MmTelCapabilities queryCapabilityStatus() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return new MmTelFeature.MmTelCapabilities(
+ getServiceInterface(mBinder).queryCapabilityStatus());
+ }
+ }
+
+ public ImsCallProfile createCallProfile(int callServiceType, int callType)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).createCallProfile(callServiceType, callType);
+ }
+ }
+
+ public IImsCallSession createCallSession(ImsCallProfile profile)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).createCallSession(profile);
+ }
+ }
+
+ public IImsUt getUtInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getUtInterface();
+ }
+ }
+
+ public IImsConfig getConfigInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getConfig();
+ }
+ }
+
+ public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech()
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ IImsRegistration registration = getRegistration();
+ if (registration != null) {
+ return registration.getRegistrationTechnology();
+ } else {
+ return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+ }
+ }
+ }
+
+ public IImsEcbm getEcbmInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getEcbmInterface();
+ }
+ }
+
+ public void setUiTTYMode(int uiTtyMode, Message onComplete)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).setUiTtyMode(uiTtyMode, onComplete);
+ }
+ }
+
+ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getMultiEndpointInterface();
+ }
+ }
+
+ public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+ byte[] pdu) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).sendSms(token, messageRef, format, smsc, isRetry,
+ pdu);
+ }
+ }
+
+ public void acknowledgeSms(int token, int messageRef,
+ @ImsSmsImplBase.SendStatusResult int result) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).acknowledgeSms(token, messageRef, result);
+ }
+ }
+
+ public void acknowledgeSmsReport(int token, int messageRef,
+ @ImsSmsImplBase.StatusReportResult int result) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).acknowledgeSmsReport(token, messageRef, result);
+ }
+ }
+
+ public String getSmsFormat() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getSmsFormat();
+ }
+ }
+
+ public void onSmsReady() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).onSmsReady();
+ }
+ }
+
+ public void setSmsListener(IImsSmsListener listener) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).setSmsListener(listener);
+ }
+ }
+
+ /**
+ * @return an integer describing the current Feature Status, defined in
+ * {@link ImsFeature.ImsState}.
+ */
+ public int getFeatureState() {
+ synchronized (mLock) {
+ if (isBinderAlive() && mFeatureStateCached != null) {
+ Log.i(TAG, "getFeatureState - returning cached: " + mFeatureStateCached);
+ return mFeatureStateCached;
+ }
+ }
+ // Don't synchronize on Binder call.
+ Integer status = retrieveFeatureState();
+ synchronized (mLock) {
+ if (status == null) {
+ return ImsFeature.STATE_UNAVAILABLE;
+ }
+ // Cache only non-null value for feature status.
+ mFeatureStateCached = status;
+ }
+ Log.i(TAG, "getFeatureState - returning " + status);
+ return status;
+ }
+
+ /**
+ * Internal method used to retrieve the feature status from the corresponding ImsService.
+ */
+ private Integer retrieveFeatureState() {
+ if (mBinder != null) {
+ try {
+ return getServiceInterface(mBinder).getFeatureState();
+ } 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(IFeatureUpdate c) {
+ mStatusCallback = c;
+ }
+
+ /**
+ * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
+ * method returns false, it doesn't mean that the Binder connection is not available (use
+ * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
+ * at this time.
+ *
+ * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
+ * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_UNAVAILABLE}.
+ */
+ public boolean isBinderReady() {
+ return isBinderAlive() && getFeatureState() == ImsFeature.STATE_READY;
+ }
+
+ /**
+ * @return false if the binder connection is no longer alive.
+ */
+ public boolean isBinderAlive() {
+ return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
+ }
+
+ protected void checkServiceIsReady() throws RemoteException {
+ if (!isBinderReady()) {
+ throw new RemoteException("ImsServiceProxy is not ready to accept commands.");
+ }
+ }
+
+ private IImsMmTelFeature getServiceInterface(IBinder b) {
+ return IImsMmTelFeature.Stub.asInterface(b);
+ }
+
+ protected void checkBinderConnection() throws RemoteException {
+ if (!isBinderAlive()) {
+ throw new RemoteException("ImsServiceProxy is not available for that feature.");
+ }
+ }
+}
diff --git a/src/java/com/android/ims/internal/VideoPauseTracker.java b/src/java/com/android/ims/internal/VideoPauseTracker.java
index baa3163..9243008 100644
--- a/src/java/com/android/ims/internal/VideoPauseTracker.java
+++ b/src/java/com/android/ims/internal/VideoPauseTracker.java
@@ -18,11 +18,11 @@
import android.telecom.Log;
import android.telecom.VideoProfile;
+import android.telephony.ims.ImsVideoCallProvider;
import android.util.ArraySet;
import java.util.Collection;
import java.util.Set;
-import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
@@ -71,7 +71,7 @@
*
* @param source The source of the pause request.
* @return {@code true} if a pause should be issued to the
- * {@link com.android.ims.internal.ImsVideoCallProvider}, {@code false} otherwise.
+ * {@link ImsVideoCallProvider}, {@code false} otherwise.
*/
public boolean shouldPauseVideoFor(int source) {
synchronized (mPauseRequestsLock) {
@@ -102,7 +102,7 @@
*
* @param source The source of the resume request.
* @return {@code true} if a resume should be issued to the
- * {@link com.android.ims.internal.ImsVideoCallProvider}, {@code false} otherwise.
+ * {@link ImsVideoCallProvider}, {@code false} otherwise.
*/
public boolean shouldResumeVideoFor(int source) {
synchronized (mPauseRequestsLock) {
diff --git a/tests/src/com/android/ims/ImsConfigTest.java b/tests/src/com/android/ims/ImsConfigTest.java
index 18d53b1..4cf7a92 100644
--- a/tests/src/com/android/ims/ImsConfigTest.java
+++ b/tests/src/com/android/ims/ImsConfigTest.java
@@ -17,8 +17,7 @@
package com.android.ims;
import android.support.test.runner.AndroidJUnit4;
-
-import com.android.ims.internal.IImsConfig;
+import android.telephony.ims.aidl.IImsConfig;
import org.junit.After;
import org.junit.Before;
@@ -59,6 +58,6 @@
mTestImsConfig.getProvisionedValue(testItem);
- verify(mMockImsConfigInterface).getProvisionedValue(eq(testItem));
+ verify(mMockImsConfigInterface).getConfigInt(eq(testItem));
}
}