From ef26719590b924c3c4baf503e4ea4d0baeffa3c9 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Mon, 28 Aug 2017 13:19:22 -0700 Subject: Remove "ForSlot" from ImsManager instance methods Adding "ForSlot" to ImsManager instance methods was redundant and does not yield a clean API. This change removes "ForSlot" from the methods. Bug: 65063634 Test: Manual Change-Id: Ida63b5c375df7af67bd3f7c5763d04f11fce92ea --- src/java/com/android/ims/ImsManager.java | 798 +++++++++++-------------------- 1 file changed, 279 insertions(+), 519 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 8e250863..a77abcd6 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -50,7 +50,6 @@ import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsServiceController; import com.android.ims.internal.IImsUt; import com.android.ims.internal.ImsCallSession; -import com.android.ims.internal.IImsConfig; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.ExponentialBackoff; @@ -60,7 +59,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.HashSet; -import java.util.Optional; import java.util.Set; /** @@ -270,29 +268,25 @@ public class ImsManager { * Returns the user configuration of Enhanced 4G LTE Mode setting. * * @deprecated Doesn't support MSIM devices. Use - * {@link #isEnhanced4gLteModeSettingEnabledByUserForSlot} instead. + * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead. */ public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) { - // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true. - // If user changes SIM from editable mode to uneditable mode, need to return true. - if (!getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isEnhanced4gLteModeSettingEnabledByUser(); } - int enabled = android.provider.Settings.Global.getInt( - context.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, - ImsConfig.FeatureValueConstants.ON); - return (enabled == 1) ? true : false; + loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value."); + return false; } /** * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. */ - public boolean isEnhanced4gLteModeSettingEnabledByUserForSlot() { + public boolean isEnhanced4gLteModeSettingEnabledByUser() { // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true. // If user changes SIM from editable mode to uneditable mode, need to return true. - if (!getBooleanCarrierConfigForSlot( + if (!getBooleanCarrierConfig( CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { return true; } @@ -306,26 +300,16 @@ public class ImsManager { /** * Change persistent Enhanced 4G LTE Mode setting. * - * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSettingForSlot} + * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)} * instead. */ public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) { - int value = enabled ? 1 : 0; - android.provider.Settings.Global.putInt( - context.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value); - - if (isNonTtyOrTtyOnVolteEnabled(context)) { - ImsManager imsManager = ImsManager.getInstance(context, - SubscriptionManager.getDefaultVoicePhoneId()); - if (imsManager != null) { - try { - imsManager.setAdvanced4GMode(enabled); - } catch (ImsException ie) { - // do nothing - } - } + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + mgr.setEnhanced4gLteModeSetting(enabled); } + loge("setEnhanced4gLteModeSetting: ImsManager null, value not set."); } /** @@ -334,9 +318,9 @@ public class ImsManager { * always set the setting to true. * */ - public void setEnhanced4gLteModeSettingForSlot(boolean enabled) { + public void setEnhanced4gLteModeSetting(boolean enabled) { // If false, we must always keep advanced 4G mode set to true (1). - int value = getBooleanCarrierConfigForSlot( + int value = getBooleanCarrierConfig( CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) ? (enabled ? 1: 0) : 1; try { @@ -352,7 +336,7 @@ public class ImsManager { android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value); - if (isNonTtyOrTtyOnVolteEnabledForSlot()) { + if (isNonTtyOrTtyOnVolteEnabled()) { try { setAdvanced4GMode(enabled); } catch (ImsException ie) { @@ -365,35 +349,31 @@ public class ImsManager { * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is * supported. * @deprecated Does not support MSIM devices. Please use - * {@link #isNonTtyOrTtyOnVolteEnabledForSlot} instead. + * {@link #isNonTtyOrTtyOnVolteEnabled()} instead. */ public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) { - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { - return true; - } - - TelecomManager tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); - if (tm == null) { - Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available"); - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isNonTtyOrTtyOnVolteEnabled(); } - return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF; + loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value."); + return false; } /** * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is * supported on a per slot basis. */ - public boolean isNonTtyOrTtyOnVolteEnabledForSlot() { - if (getBooleanCarrierConfigForSlot( + public boolean isNonTtyOrTtyOnVolteEnabled() { + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { return true; } TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); if (tm == null) { - Log.w(TAG, "isNonTtyOrTtyOnVolteEnabledForSlot: telecom not available"); + Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available"); return true; } return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF; @@ -402,26 +382,23 @@ public class ImsManager { /** * Returns a platform configuration for VoLTE which may override the user setting. * @deprecated Does not support MSIM devices. Please use - * {@link #isVolteEnabledByPlatformForSlot()} instead. + * {@link #isVolteEnabledByPlatform()} instead. */ public static boolean isVolteEnabledByPlatform(Context context) { - if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE, - PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) { - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isVolteEnabledByPlatform(); } - - return context.getResources().getBoolean( - com.android.internal.R.bool.config_device_volte_available) - && getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL) - && isGbaValid(context); + loge("isVolteEnabledByPlatform: ImsManager null, returning default value."); + return false; } /** * Returns a platform configuration for VoLTE which may override the user setting on a per Slot * basis. */ - public boolean isVolteEnabledByPlatformForSlot() { + public boolean isVolteEnabledByPlatform() { if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE, PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) { return true; @@ -429,35 +406,32 @@ public class ImsManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_device_volte_available) - && getBooleanCarrierConfigForSlot( + && getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL) - && isGbaValidForSlot(); + && isGbaValid(); } /** * Indicates whether VoLTE is provisioned on device. * * @deprecated Does not support MSIM devices. Please use - * {@link #isVolteProvisionedOnDeviceForSlot()} instead. + * {@link #isVolteProvisionedOnDevice()} instead. */ public static boolean isVolteProvisionedOnDevice(Context context) { - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { - ImsManager mgr = ImsManager.getInstance(context, - SubscriptionManager.getDefaultVoicePhoneId()); - if (mgr != null) { - return mgr.isVolteProvisioned(); - } + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isVolteProvisionedOnDevice(); } - + loge("isVolteProvisionedOnDevice: ImsManager null, returning default value."); return true; } /** * Indicates whether VoLTE is provisioned on this slot. */ - public boolean isVolteProvisionedOnDeviceForSlot() { - if (getBooleanCarrierConfigForSlot( + public boolean isVolteProvisionedOnDevice() { + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { return isVolteProvisioned(); } @@ -472,25 +446,15 @@ public class ImsManager { * provisioned on device, this method returns false. * * @deprecated Does not support MSIM devices. Please use - * {@link #isWfcProvisionedOnDeviceForSlot()} instead. + * {@link #isWfcProvisionedOnDevice()} instead. */ public static boolean isWfcProvisionedOnDevice(Context context) { - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) { - if (!isVolteProvisionedOnDevice(context)) { - return false; - } - } - - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { - ImsManager mgr = ImsManager.getInstance(context, - SubscriptionManager.getDefaultVoicePhoneId()); - if (mgr != null) { - return mgr.isWfcProvisioned(); - } + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isWfcProvisionedOnDevice(); } - + loge("isWfcProvisionedOnDevice: ImsManager null, returning default value."); return true; } @@ -500,15 +464,15 @@ public class ImsManager { * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not * provisioned on device, this method returns false. */ - public boolean isWfcProvisionedOnDeviceForSlot() { - if (getBooleanCarrierConfigForSlot( + public boolean isWfcProvisionedOnDevice() { + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) { - if (!isVolteProvisionedOnDeviceForSlot()) { + if (!isVolteProvisionedOnDevice()) { return false; } } - if (getBooleanCarrierConfigForSlot( + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { return isWfcProvisioned(); } @@ -520,26 +484,23 @@ public class ImsManager { * Indicates whether VT is provisioned on device * * @deprecated Does not support MSIM devices. Please use - * {@link #isVtProvisionedOnDeviceForSlot()} instead. + * {@link #isVtProvisionedOnDevice()} instead. */ public static boolean isVtProvisionedOnDevice(Context context) { - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { - ImsManager mgr = ImsManager.getInstance(context, - SubscriptionManager.getDefaultVoicePhoneId()); - if (mgr != null) { - return mgr.isVtProvisioned(); - } + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isVtProvisionedOnDevice(); } - + loge("isVtProvisionedOnDevice: ImsManager null, returning default value."); return true; } /** * Indicates whether VT is provisioned on slot. */ - public boolean isVtProvisionedOnDeviceForSlot() { - if (getBooleanCarrierConfigForSlot( + public boolean isVtProvisionedOnDevice() { + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { return isVtProvisioned(); } @@ -554,20 +515,16 @@ public class ImsManager { * which must be done correctly). * * @deprecated Does not support MSIM devices. Please use - * {@link #isVtEnabledByPlatformForSlot()} instead. + * {@link #isVtEnabledByPlatform()} instead. */ public static boolean isVtEnabledByPlatform(Context context) { - if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE, - PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) { - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isVtEnabledByPlatform(); } - - return - context.getResources().getBoolean( - com.android.internal.R.bool.config_device_vt_available) && - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) && - isGbaValid(context); + loge("isVtEnabledByPlatform: ImsManager null, returning default value."); + return false; } /** @@ -576,7 +533,7 @@ public class ImsManager { * Note: VT presumes that VoLTE is enabled (these are configuration settings * which must be done correctly). */ - public boolean isVtEnabledByPlatformForSlot() { + public boolean isVtEnabledByPlatform() { if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE, PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) { return true; @@ -584,27 +541,30 @@ public class ImsManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_device_vt_available) && - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) && - isGbaValidForSlot(); + isGbaValid(); } /** * Returns the user configuration of VT setting * @deprecated Does not support MSIM devices. Please use - * {@link #isVtEnabledByUserForSlot()} instead. + * {@link #isVtEnabledByUser()} instead. */ public static boolean isVtEnabledByUser(Context context) { - int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, - ImsConfig.FeatureValueConstants.ON); - return (enabled == 1) ? true : false; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isVtEnabledByUser(); + } + loge("isVtEnabledByUser: ImsManager null, returning default value."); + return false; } /** * Returns the user configuration of VT setting per slot. */ - public boolean isVtEnabledByUserForSlot() { + public boolean isVtEnabledByUser() { int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.VT_IMS_ENABLED, ImsConfig.FeatureValueConstants.ON); @@ -614,44 +574,21 @@ public class ImsManager { /** * Change persistent VT enabled setting * - * @deprecated Does not support MSIM devices. Please use - * {@link #setVtSettingForSlot} instead. + * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead. */ public static void setVtSetting(Context context, boolean enabled) { - int value = enabled ? 1 : 0; - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, value); - - ImsManager imsManager = ImsManager.getInstance(context, + ImsManager mgr = ImsManager.getInstance(context, SubscriptionManager.getDefaultVoicePhoneId()); - if (imsManager != null) { - try { - ImsConfig config = imsManager.getConfigInterface(); - config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, - TelephonyManager.NETWORK_TYPE_LTE, - enabled ? ImsConfig.FeatureValueConstants.ON - : ImsConfig.FeatureValueConstants.OFF, - imsManager.mImsConfigListener); - - if (enabled) { - log("setVtSetting() : turnOnIms"); - imsManager.turnOnIms(); - } else if (isTurnOffImsAllowedByPlatform(context) - && (!isVolteEnabledByPlatform(context) - || !isEnhanced4gLteModeSettingEnabledByUser(context))) { - log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms"); - imsManager.turnOffIms(); - } - } catch (ImsException e) { - loge("setVtSetting(): ", e); - } + if (mgr != null) { + mgr.setVtSetting(enabled); } + loge("setVtSetting: ImsManager null, can not set value."); } /** * Change persistent VT enabled setting for slot. */ - public void setVtSettingForSlot(boolean enabled) { + public void setVtSetting(boolean enabled) { int value = enabled ? 1 : 0; android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.VT_IMS_ENABLED, value); @@ -665,16 +602,16 @@ public class ImsManager { mImsConfigListener); if (enabled) { - log("setVtSettingForSlot() : turnOnIms"); + log("setVtSetting(b) : turnOnIms"); turnOnIms(); - } else if (isVolteEnabledByPlatformForSlot() - && (!isVolteEnabledByPlatformForSlot() - || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) { - log("setVtSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms"); + } else if (isVolteEnabledByPlatform() + && (!isVolteEnabledByPlatform() + || !isEnhanced4gLteModeSettingEnabledByUser())) { + log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms"); turnOffIms(); } } catch (ImsException e) { - loge("setVtSettingForSlot(): ", e); + loge("setVtSetting(b): ", e); } } @@ -683,27 +620,28 @@ public class ImsManager { * The platform property may override the carrier config. * * @deprecated Does not support MSIM devices. Please use - * {@link #isTurnOffImsAllowedByPlatformForSlot} instead. + * {@link #isTurnOffImsAllowedByPlatform()} instead. */ private static boolean isTurnOffImsAllowedByPlatform(Context context) { - if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, - PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) { - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isTurnOffImsAllowedByPlatform(); } - return getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL); + loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value."); + return true; } /** * Returns whether turning off ims is allowed by platform. * The platform property may override the carrier config. */ - private boolean isTurnOffImsAllowedByPlatformForSlot() { + private boolean isTurnOffImsAllowedByPlatform() { if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) { return true; } - return getBooleanCarrierConfigForSlot( + return getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL); } @@ -711,24 +649,25 @@ public class ImsManager { * Returns the user configuration of WFC setting * * @deprecated Does not support MSIM devices. Please use - * {@link #isTurnOffImsAllowedByPlatformForSlot} instead. + * {@link #isWfcEnabledByUser()} instead. */ public static boolean isWfcEnabledByUser(Context context) { - int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - return (enabled == 1) ? true : false; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isWfcEnabledByUser(); + } + loge("isWfcEnabledByUser: ImsManager null, returning default value."); + return true; } /** * Returns the user configuration of WFC setting for slot. */ - public boolean isWfcEnabledByUserForSlot() { + public boolean isWfcEnabledByUser() { int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); return enabled == 1; @@ -737,56 +676,26 @@ public class ImsManager { /** * Change persistent WFC enabled setting. * @deprecated Does not support MSIM devices. Please use - * {@link #setWfcSettingForSlot} instead. + * {@link #setWfcSetting} instead. */ public static void setWfcSetting(Context context, boolean enabled) { - int value = enabled ? 1 : 0; - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, value); - - ImsManager imsManager = ImsManager.getInstance(context, + ImsManager mgr = ImsManager.getInstance(context, SubscriptionManager.getDefaultVoicePhoneId()); - if (imsManager != null) { - try { - ImsConfig config = imsManager.getConfigInterface(); - config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI, - TelephonyManager.NETWORK_TYPE_IWLAN, - enabled ? ImsConfig.FeatureValueConstants.ON - : ImsConfig.FeatureValueConstants.OFF, - imsManager.mImsConfigListener); - - if (enabled) { - log("setWfcSetting() : turnOnIms"); - imsManager.turnOnIms(); - } else if (isTurnOffImsAllowedByPlatform(context) - && (!isVolteEnabledByPlatform(context) - || !isEnhanced4gLteModeSettingEnabledByUser(context))) { - log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms"); - imsManager.turnOffIms(); - } - - TelephonyManager tm = (TelephonyManager) context - .getSystemService(Context.TELEPHONY_SERVICE); - setWfcModeInternal(context, enabled - // Choose wfc mode per current roaming preference - ? getWfcMode(context, tm.isNetworkRoaming()) - // Force IMS to register over LTE when turning off WFC - : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED); - } catch (ImsException e) { - loge("setWfcSetting(): ", e); - } + if (mgr != null) { + mgr.setWfcSetting(enabled); } + loge("setWfcSetting: ImsManager null, can not set value."); } /** * Change persistent WFC enabled setting for slot. */ - public void setWfcSettingForSlot(boolean enabled) { + public void setWfcSetting(boolean enabled) { int value = enabled ? 1 : 0; android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ENABLED, value); - setWfcNonPersistentForSlot(enabled, getWfcModeForSlot()); + setWfcNonPersistent(enabled, getWfcMode()); } /** @@ -794,7 +703,7 @@ public class ImsManager { * * @param wfcMode The WFC preference if WFC is enabled */ - public void setWfcNonPersistentForSlot(boolean enabled, int wfcMode) { + 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 @@ -809,40 +718,42 @@ public class ImsManager { mImsConfigListener); if (enabled) { - log("setWfcSettingForSlot() : turnOnIms"); + log("setWfcSetting() : turnOnIms"); turnOnIms(); - } else if (isTurnOffImsAllowedByPlatformForSlot() - && (!isVolteEnabledByPlatformForSlot() - || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) { - log("setWfcSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms"); + } else if (isTurnOffImsAllowedByPlatform() + && (!isVolteEnabledByPlatform() + || !isEnhanced4gLteModeSettingEnabledByUser())) { + log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms"); turnOffIms(); } - setWfcModeInternalForSlot(imsWfcModeFeatureValue); + setWfcModeInternal(imsWfcModeFeatureValue); } catch (ImsException e) { - loge("setWfcSettingForSlot(): ", e); + loge("setWfcSetting(): ", e); } } /** * Returns the user configuration of WFC preference setting. * - * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode()} instead. */ public static int getWfcMode(Context context) { - int setting = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - if (DBG) log("getWfcMode - setting=" + setting); - return setting; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.getWfcMode(); + } + loge("getWfcMode: ImsManager null, returning default value."); + return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY; } /** * Returns the user configuration of WFC preference setting */ - public int getWfcModeForSlot() { + public int getWfcMode() { int setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot( + android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); if (DBG) log("getWfcMode - setting=" + setting); return setting; @@ -851,25 +762,26 @@ public class ImsManager { /** * Change persistent WFC preference setting. * - * @deprecated Doesn't support MSIM devices. Use {@link #setWfcModeForSlot} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead. */ public static void setWfcMode(Context context, int wfcMode) { - if (DBG) log("setWfcMode - setting=" + wfcMode); - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); - - setWfcModeInternal(context, wfcMode); + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + mgr.setWfcMode(wfcMode); + } + loge("setWfcMode: ImsManager null, can not set value."); } /** * Change persistent WFC preference setting for slot. */ - public void setWfcModeForSlot(int wfcMode) { - if (DBG) log("setWfcModeForSlot - setting=" + wfcMode); + public void setWfcMode(int wfcMode) { + if (DBG) log("setWfcMode(i) - setting=" + wfcMode); android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); - setWfcModeInternalForSlot(wfcMode); + setWfcModeInternal(wfcMode); } /** @@ -877,9 +789,8 @@ public class ImsManager { */ private void updateDefaultWfcMode() { if (DBG) log("updateDefaultWfcMode"); - if (!getBooleanCarrierConfigForSlot( - CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { - setWfcModeForSlot(getIntCarrierConfigForSlot( + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { + setWfcMode(getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); } } @@ -889,23 +800,16 @@ public class ImsManager { * * @param roaming {@code false} for home network setting, {@code true} for roaming setting * - * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead. */ public static int getWfcMode(Context context, boolean roaming) { - int setting = 0; - if (!roaming) { - setting = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - if (DBG) log("getWfcMode - setting=" + setting); - } else { - setting = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, - getIntCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); - if (DBG) log("getWfcMode (roaming) - setting=" + setting); + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.getWfcMode(roaming); } - return setting; + loge("getWfcMode: ImsManager null, returning default value."); + return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY; } /** @@ -913,19 +817,19 @@ public class ImsManager { * * @param roaming {@code false} for home network setting, {@code true} for roaming setting */ - public int getWfcModeForSlot(boolean roaming) { + public int getWfcMode(boolean roaming) { int setting = 0; if (!roaming) { setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot( + android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - if (DBG) log("getWfcModeForSlot - setting=" + setting); + if (DBG) log("getWfcMode - setting=" + setting); } else { setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, - getIntCarrierConfigForSlot( + getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); - if (DBG) log("getWfcModeForSlot (roaming) - setting=" + setting); + if (DBG) log("getWfcMode (roaming) - setting=" + setting); } return setting; } @@ -935,24 +839,16 @@ public class ImsManager { * * @param roaming {@code false} for home network setting, {@code true} for roaming setting * - * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcModeForSlot} instead. + * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)} + * instead. */ public static void setWfcMode(Context context, int wfcMode, boolean roaming) { - if (!roaming) { - if (DBG) log("setWfcMode - setting=" + wfcMode); - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); - } else { - if (DBG) log("setWfcMode (roaming) - setting=" + wfcMode); - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode); - } - - TelephonyManager tm = (TelephonyManager) - context.getSystemService(Context.TELEPHONY_SERVICE); - if (roaming == tm.isNetworkRoaming()) { - setWfcModeInternal(context, wfcMode); + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + mgr.setWfcMode(wfcMode, roaming); } + loge("setWfcMode: ImsManager null, can not set value."); } /** @@ -960,27 +856,32 @@ public class ImsManager { * * @param roaming {@code false} for home network setting, {@code true} for roaming setting */ - public void setWfcModeForSlot(int wfcMode, boolean roaming) { + public void setWfcMode(int wfcMode, boolean roaming) { if (!roaming) { - if (DBG) log("setWfcModeForSlot - setting=" + wfcMode); + if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode); android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); } else { - if (DBG) log("setWfcModeForSlot (roaming) - setting=" + wfcMode); + if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode); android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode); } + + TelephonyManager tm = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + if (roaming == tm.isNetworkRoaming(getSubId())) { + setWfcModeInternal(wfcMode); + } + } + + private int getSubId() { int[] subIds = SubscriptionManager.getSubId(mPhoneId); int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; if (subIds != null && subIds.length >= 1) { subId = subIds[0]; } - TelephonyManager tm = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - if (roaming == tm.isNetworkRoaming(subId)) { - setWfcModeInternalForSlot(wfcMode); - } + return subId; } private static void setWfcModeInternal(Context context, int wfcMode) { @@ -1003,7 +904,7 @@ public class ImsManager { } } - private void setWfcModeInternalForSlot(int wfcMode) { + private void setWfcModeInternal(int wfcMode) { final int value = wfcMode; Thread thread = new Thread(() -> { try { @@ -1021,24 +922,25 @@ public class ImsManager { * Returns the user configuration of WFC roaming setting * * @deprecated Does not support MSIM devices. Please use - * {@link #isWfcRoamingEnabledByUserForSlot} instead. + * {@link #isWfcRoamingEnabledByUser()} instead. */ public static boolean isWfcRoamingEnabledByUser(Context context) { - int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - return (enabled == 1) ? true : false; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isWfcRoamingEnabledByUser(); + } + loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value."); + return false; } /** * Returns the user configuration of WFC roaming setting for slot */ - public boolean isWfcRoamingEnabledByUserForSlot() { + public boolean isWfcRoamingEnabledByUser() { int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); return (enabled == 1); @@ -1048,22 +950,18 @@ public class ImsManager { * Change persistent WFC roaming enabled setting */ public static void setWfcRoamingSetting(Context context, boolean enabled) { - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - enabled ? ImsConfig.FeatureValueConstants.ON - : ImsConfig.FeatureValueConstants.OFF); - - final ImsManager imsManager = ImsManager.getInstance(context, + ImsManager mgr = ImsManager.getInstance(context, SubscriptionManager.getDefaultVoicePhoneId()); - if (imsManager != null) { - imsManager.setWfcRoamingSettingInternal(enabled); + if (mgr != null) { + mgr.setWfcRoamingSetting(enabled); } + loge("setWfcRoamingSetting: ImsManager null, value not set."); } /** * Change persistent WFC roaming enabled setting */ - public void setWfcRoamingSettingForSlot(boolean enabled) { + public void setWfcRoamingSetting(boolean enabled) { android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, enabled ? ImsConfig.FeatureValueConstants.ON @@ -1093,21 +991,17 @@ public class ImsManager { * setting. Note: WFC presumes that VoLTE is enabled (these are * configuration settings which must be done correctly). * - * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatformForSlot} + * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()} * instead. */ public static boolean isWfcEnabledByPlatform(Context context) { - if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE, - PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) { - return true; + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + return mgr.isWfcEnabledByPlatform(); } - - return - context.getResources().getBoolean( - com.android.internal.R.bool.config_device_wfc_ims_available) && - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) && - isGbaValid(context); + loge("isWfcEnabledByPlatform: ImsManager null, returning default value."); + return false; } /** @@ -1115,7 +1009,7 @@ public class ImsManager { * setting per slot. Note: WFC presumes that VoLTE is enabled (these are * configuration settings which must be done correctly). */ - public boolean isWfcEnabledByPlatformForSlot() { + public boolean isWfcEnabledByPlatform() { if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE, PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) { return true; @@ -1123,34 +1017,9 @@ public class ImsManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_device_wfc_ims_available) && - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) && - isGbaValidForSlot(); - } - - /** - * If carrier requires that IMS is only available if GBA capable SIM is used, - * then this function checks GBA bit in EF IST. - * - * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7). - * - * @deprecated Use {@link #isGbaValidForSlot} instead - */ - private static boolean isGbaValid(Context context) { - if (getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) { - final TelephonyManager telephonyManager = TelephonyManager.getDefault(); - String efIst = telephonyManager.getIsimIst(); - if (efIst == null) { - loge("ISF is NULL"); - return true; - } - boolean result = efIst != null && efIst.length() > 1 && - (0x02 & (byte)efIst.charAt(1)) != 0; - if (DBG) log("GBA capable=" + result + ", ISF=" + efIst); - return result; - } - return true; + isGbaValid(); } /** @@ -1159,18 +1028,18 @@ public class ImsManager { * * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7). */ - private boolean isGbaValidForSlot() { - if (getBooleanCarrierConfigForSlot( + private boolean isGbaValid() { + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) { - final TelephonyManager telephonyManager = TelephonyManager.getDefault(); + final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId()); String efIst = telephonyManager.getIsimIst(); if (efIst == null) { - loge("isGbaValidForSlot - ISF is NULL"); + loge("isGbaValid - ISF is NULL"); return true; } boolean result = efIst != null && efIst.length() > 1 && (0x02 & (byte)efIst.charAt(1)) != 0; - if (DBG) log("isGbaValidForSlot - GBA capable=" + result + ", ISF=" + efIst); + if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst); return result; } return true; @@ -1269,7 +1138,7 @@ public class ImsManager { // used internally only, use #updateProvisionedValues instead. private void handleUpdateProvisionedValues() { - if (getBooleanCarrierConfigForSlot( + if (getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { new AsyncUpdateProvisionedValues().execute(); @@ -1297,50 +1166,15 @@ public class ImsManager { * @param phoneId phone id * @param force update * - * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfigForSlot} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)} + * instead. */ public static void updateImsServiceConfig(Context context, int phoneId, boolean force) { - if (!force) { - if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) { - log("updateImsServiceConfig: SIM not ready"); - // Don't disable IMS if SIM is not ready - return; - } - } - - final ImsManager imsManager = ImsManager.getInstance(context, phoneId); - if (imsManager != null && (!imsManager.mConfigUpdated || force)) { - try { - imsManager.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. - boolean isImsUsed = imsManager.updateVolteFeatureValue(); - isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues(); - isImsUsed |= imsManager.updateVideoCallFeatureValue(); - - if (isImsUsed || !isTurnOffImsAllowedByPlatform(context)) { - // Turn on IMS if it is used. - // Also, if turning off is not allowed for current carrier, - // we need to turn IMS on because it might be turned off before - // phone switched to current carrier. - log("updateImsServiceConfig: turnOnIms"); - imsManager.turnOnIms(); - } else { - // Turn off IMS if it is not used AND turning off is allowed for carrier. - log("updateImsServiceConfig: turnOffIms"); - imsManager.turnOffIms(); - } - - imsManager.mConfigUpdated = true; - } catch (ImsException e) { - loge("updateImsServiceConfig: ", e); - imsManager.mConfigUpdated = false; - } + ImsManager mgr = ImsManager.getInstance(context, phoneId); + if (mgr != null) { + mgr.updateImsServiceConfig(force); } + loge("updateImsServiceConfig: ImsManager null, returning without update."); } /** @@ -1350,10 +1184,11 @@ public class ImsManager { * @param phoneId phone id * @param force update */ - public void updateImsServiceConfigForSlot(boolean force) { + public void updateImsServiceConfig(boolean force) { if (!force) { - if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) { - log("updateImsServiceConfigForSlot: SIM not ready"); + TelephonyManager tm = new TelephonyManager(mContext, getSubId()); + if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) { + log("updateImsServiceConfig: SIM not ready"); // Don't disable IMS if SIM is not ready return; } @@ -1372,22 +1207,22 @@ public class ImsManager { isImsUsed |= updateWfcFeatureAndProvisionedValues(); isImsUsed |= updateVideoCallFeatureValue(); - if (isImsUsed || !isTurnOffImsAllowedByPlatformForSlot()) { + if (isImsUsed || !isTurnOffImsAllowedByPlatform()) { // Turn on IMS if it is used. // Also, if turning off is not allowed for current carrier, // we need to turn IMS on because it might be turned off before // phone switched to current carrier. - log("updateImsServiceConfigForSlot: turnOnIms"); + log("updateImsServiceConfig: turnOnIms"); turnOnIms(); } else { // Turn off IMS if it is not used AND turning off is allowed for carrier. - log("updateImsServiceConfigForSlot: turnOffIms"); + log("updateImsServiceConfig: turnOffIms"); turnOffIms(); } mConfigUpdated = true; } catch (ImsException e) { - loge("updateImsServiceConfigForSlot: ", e); + loge("updateImsServiceConfig: ", e); mConfigUpdated = false; } } @@ -1399,9 +1234,9 @@ public class ImsManager { * @throws ImsException */ private boolean updateVolteFeatureValue() throws ImsException { - boolean available = isVolteEnabledByPlatformForSlot(); - boolean enabled = isEnhanced4gLteModeSettingEnabledByUserForSlot(); - boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot(); + boolean available = isVolteEnabledByPlatform(); + boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(); + boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(); boolean isFeatureOn = available && enabled && isNonTty; log("updateVolteFeatureValue: available = " + available @@ -1425,11 +1260,11 @@ public class ImsManager { * @throws ImsException */ private boolean updateVideoCallFeatureValue() throws ImsException { - boolean available = isVtEnabledByPlatformForSlot(); - boolean enabled = isVtEnabledByUserForSlot(); - boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot(); + boolean available = isVtEnabledByPlatform(); + boolean enabled = isVtEnabledByUser(); + boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(); boolean isDataEnabled = isDataEnabled(); - boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext, + boolean ignoreDataEnabledChanged = getBooleanCarrierConfig( CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS); boolean isFeatureOn = available && enabled && isNonTty @@ -1457,12 +1292,13 @@ public class ImsManager { * @throws ImsException */ private boolean updateWfcFeatureAndProvisionedValues() throws ImsException { - boolean isNetworkRoaming = TelephonyManager.getDefault().isNetworkRoaming(); - boolean available = isWfcEnabledByPlatformForSlot(); - boolean enabled = isWfcEnabledByUserForSlot(); + TelephonyManager tm = new TelephonyManager(mContext, getSubId()); + boolean isNetworkRoaming = tm.isNetworkRoaming(); + boolean available = isWfcEnabledByPlatform(); + boolean enabled = isWfcEnabledByUser(); updateDefaultWfcMode(); - int mode = getWfcModeForSlot(isNetworkRoaming); - boolean roaming = isWfcRoamingEnabledByUserForSlot(); + int mode = getWfcMode(isNetworkRoaming); + boolean roaming = isWfcRoamingEnabledByUser(); boolean isFeatureOn = available && enabled; log("updateWfcFeatureAndProvisionedValues: available = " + available @@ -1489,7 +1325,7 @@ public class ImsManager { } /** - * Do NOT use this directly, instead use {@link #getInstance}. + * Do NOT use this directly, instead use {@link #getInstance(Context, int)}. */ @VisibleForTesting public ImsManager(Context context, int phoneId) { @@ -1935,10 +1771,10 @@ public class ImsManager { * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status) */ public void setTtyMode(int ttyMode) throws ImsException { - if (!getBooleanCarrierConfigForSlot( + if (!getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) && - isEnhanced4gLteModeSettingEnabledByUserForSlot()); + isEnhanced4gLteModeSettingEnabledByUser()); } } @@ -1991,35 +1827,10 @@ public class ImsManager { /** * Get the boolean config from carrier config manager. * - * @param context the context to get carrier service * @param key config key defined in CarrierConfigManager * @return boolean value of corresponding key. - * - * @deprecated Does not support MSIM devices. Use - * {@link #getBooleanCarrierConfigForSlot(Context, String)} instead. */ - private static boolean getBooleanCarrierConfig(Context context, String key) { - CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService( - Context.CARRIER_CONFIG_SERVICE); - PersistableBundle b = null; - if (configManager != null) { - b = configManager.getConfig(); - } - if (b != null) { - return b.getBoolean(key); - } else { - // Return static default defined in CarrierConfigManager. - return CarrierConfigManager.getDefaultConfig().getBoolean(key); - } - } - - /** - * Get the boolean config from carrier config manager. - * - * @param key config key defined in CarrierConfigManager - * @return boolean value of corresponding key. - */ - private boolean getBooleanCarrierConfigForSlot(String key) { + private boolean getBooleanCarrierConfig(String key) { int[] subIds = SubscriptionManager.getSubId(mPhoneId); int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; if (subIds != null && subIds.length >= 1) { @@ -2041,34 +1852,10 @@ public class ImsManager { /** * Get the int config from carrier config manager. * - * @param context the context to get carrier service * @param key config key defined in CarrierConfigManager * @return integer value of corresponding key. - * - * @deprecated Doesn't support MSIM devices. Use {@link #getIntCarrierConfigForSlot} instead. */ - private static int getIntCarrierConfig(Context context, String key) { - CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService( - Context.CARRIER_CONFIG_SERVICE); - PersistableBundle b = null; - if (configManager != null) { - b = configManager.getConfig(); - } - if (b != null) { - return b.getInt(key); - } else { - // Return static default defined in CarrierConfigManager. - return CarrierConfigManager.getDefaultConfig().getInt(key); - } - } - - /** - * Get the int config from carrier config manager. - * - * @param key config key defined in CarrierConfigManager - * @return integer value of corresponding key. - */ - private int getIntCarrierConfigForSlot(String key) { + private int getIntCarrierConfig(String key) { int[] subIds = SubscriptionManager.getSubId(mPhoneId); int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; if (subIds != null && subIds.length >= 1) { @@ -2233,9 +2020,9 @@ public class ImsManager { } private boolean isImsTurnOffAllowed() { - return isTurnOffImsAllowedByPlatformForSlot() - && (!isWfcEnabledByPlatformForSlot() - || !isWfcEnabledByUserForSlot()); + return isTurnOffImsAllowedByPlatform() + && (!isWfcEnabledByPlatform() + || !isWfcEnabledByUser()); } private void setLteFeatureValues(boolean turnOn) { @@ -2246,10 +2033,10 @@ public class ImsManager { config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE, TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener); - if (isVolteEnabledByPlatformForSlot()) { - boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext, + if (isVolteEnabledByPlatform()) { + boolean ignoreDataEnabledChanged = getBooleanCarrierConfig( CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS); - boolean enableViLte = turnOn && isVtEnabledByUserForSlot() && + boolean enableViLte = turnOn && isVtEnabledByUser() && (ignoreDataEnabledChanged || isDataEnabled()); config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, TelephonyManager.NETWORK_TYPE_LTE, @@ -2576,44 +2363,17 @@ public class ImsManager { /** * Resets ImsManager settings back to factory defaults. * - * @deprecated Doesn't support MSIM devices. Use {@link #factoryResetSlot()} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead. * * @hide */ public static void factoryReset(Context context) { - // Set VoLTE to default - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, - ImsConfig.FeatureValueConstants.ON); - - // Set VoWiFi to default - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - - // Set VoWiFi mode to default - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, - getIntCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - - // Set VoWiFi roaming to default - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfig(context, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - - // Set VT to default - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, - ImsConfig.FeatureValueConstants.ON); - - // Push settings to ImsConfig - ImsManager.updateImsServiceConfig(context, - SubscriptionManager.getDefaultVoicePhoneId(), true); + ImsManager mgr = ImsManager.getInstance(context, + SubscriptionManager.getDefaultVoicePhoneId()); + if (mgr != null) { + mgr.factoryReset(); + } + loge("factoryReset: ImsManager null."); } /** @@ -2621,7 +2381,7 @@ public class ImsManager { * * @hide */ - public void factoryResetSlot() { + public void factoryReset() { // Set VoLTE to default android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, @@ -2630,20 +2390,20 @@ public class ImsManager { // Set VoWiFi to default android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); // Set VoWiFi mode to default android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_MODE, - getIntCarrierConfigForSlot( + getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); // Set VoWiFi roaming to default android.provider.Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfigForSlot( + getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); @@ -2653,7 +2413,7 @@ public class ImsManager { ImsConfig.FeatureValueConstants.ON); // Push settings to ImsConfig - updateImsServiceConfigForSlot(true); + updateImsServiceConfig(true); } private boolean isDataEnabled() { @@ -2699,27 +2459,27 @@ public class ImsManager { pw.println(" mConfigUpdated = " + mConfigUpdated); pw.println(" mImsServiceProxy = " + mImsServiceProxy); pw.println(" mDataEnabled = " + isDataEnabled()); - pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(mContext, + pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig( CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)); - pw.println(" isGbaValid = " + isGbaValidForSlot()); + pw.println(" isGbaValid = " + isGbaValid()); pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed()); - pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabledForSlot()); + pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled()); - pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatformForSlot()); - pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDeviceForSlot()); + pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform()); + pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice()); pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " + - isEnhanced4gLteModeSettingEnabledByUserForSlot()); - pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatformForSlot()); - pw.println(" isVtEnabledByUser = " + isVtEnabledByUserForSlot()); + isEnhanced4gLteModeSettingEnabledByUser()); + pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform()); + pw.println(" isVtEnabledByUser = " + isVtEnabledByUser()); - pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatformForSlot()); - pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUserForSlot()); - pw.println(" getWfcMode = " + getWfcModeForSlot()); - pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUserForSlot()); + pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform()); + pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser()); + pw.println(" getWfcMode = " + getWfcMode()); + pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser()); - pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDeviceForSlot()); - pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDeviceForSlot()); + pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice()); + pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice()); pw.flush(); } } -- cgit v1.2.3 From 212ca656df4b96b93b73f78de37090a528bc719f Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Thu, 28 Sep 2017 17:28:45 -0700 Subject: Use Subscription properties to store Ims user settings. To support multi-sim Ims settings, SubscriptionManager is a better place than Global settings, since the settings are per subId. So we use SubscriptionManager to store them now. Bug: 66699661 Test: Manual Change-Id: Icad66768bfecb7f1add1896e211fa377ec044895 --- src/java/com/android/ims/ImsManager.java | 254 ++++++++++++++++--------------- 1 file changed, 135 insertions(+), 119 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index a77abcd6..305735dc 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -237,6 +237,8 @@ public class ImsManager { 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; /** @@ -281,20 +283,22 @@ public class ImsManager { } /** - * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. + * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If not set, it + * returns true as default value. */ public boolean isEnhanced4gLteModeSettingEnabledByUser() { // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true. // If user changes SIM from editable mode to uneditable mode, need to return true. - if (!getBooleanCarrierConfig( - CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { return true; } - int enabled = android.provider.Settings.Global.getInt( - mContext.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, - ImsConfig.FeatureValueConstants.ON); - return (enabled == 1); + + int setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // If it's never set, by default we return true. + return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1); } /** @@ -319,28 +323,23 @@ public class ImsManager { * */ public void setEnhanced4gLteModeSetting(boolean enabled) { - // If false, we must always keep advanced 4G mode set to true (1). - int value = getBooleanCarrierConfig( - CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) ? (enabled ? 1: 0) : 1; - - try { - int prevSetting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED); - if (prevSetting == value) { - // Don't trigger setAdvanced4GMode if the setting hasn't changed. - return; - } - } catch (Settings.SettingNotFoundException e) { - // Setting doesn't exist yet, so set it below. - } - - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value); - if (isNonTtyOrTtyOnVolteEnabled()) { - try { - setAdvanced4GMode(enabled); - } catch (ImsException ie) { - // do nothing + // If false, we must always keep advanced 4G mode set to true. + enabled = getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) + ? enabled : true; + + int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + if (prevSetting != (enabled ? 1 : 0)) { + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled)); + if (isNonTtyOrTtyOnVolteEnabled()) { + try { + setAdvanced4GMode(enabled); + } catch (ImsException ie) { + // do nothing + } } } } @@ -406,8 +405,7 @@ public class ImsManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_device_volte_available) - && getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL) + && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL) && isGbaValid(); } @@ -541,8 +539,7 @@ public class ImsManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_device_vt_available) && - getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) && + getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) && isGbaValid(); } @@ -562,13 +559,16 @@ public class ImsManager { } /** - * Returns the user configuration of VT setting per slot. + * Returns the user configuration of VT setting per slot. If not set, it + * returns true as default value. */ public boolean isVtEnabledByUser() { - int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, - ImsConfig.FeatureValueConstants.ON); - return (enabled == 1); + int setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.VT_IMS_ENABLED, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // If it's never set, by default we return true. + return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1); } /** @@ -589,10 +589,9 @@ public class ImsManager { * Change persistent VT enabled setting for slot. */ public void setVtSetting(boolean enabled) { - int value = enabled ? 1 : 0; - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, value); - + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.VT_IMS_ENABLED, + booleanToPropertyString(enabled)); try { ImsConfig config = getConfigInterface(); config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, @@ -662,15 +661,21 @@ public class ImsManager { } /** - * Returns the user configuration of WFC setting for slot. + * Returns the user configuration of WFC setting for slot. If not set, it + * queries CarrierConfig value as default. */ public boolean isWfcEnabledByUser() { - int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - return enabled == 1; + int setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.WFC_IMS_ENABLED, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. + if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + return getBooleanCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL); + } else { + return setting == 1; + } } /** @@ -691,9 +696,8 @@ public class ImsManager { * Change persistent WFC enabled setting for slot. */ public void setWfcSetting(boolean enabled) { - int value = enabled ? 1 : 0; - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, value); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled)); setWfcNonPersistent(enabled, getWfcMode()); } @@ -736,7 +740,7 @@ public class ImsManager { /** * Returns the user configuration of WFC preference setting. * - * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode()} instead. + * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead. */ public static int getWfcMode(Context context) { ImsManager mgr = ImsManager.getInstance(context, @@ -750,13 +754,10 @@ public class ImsManager { /** * Returns the user configuration of WFC preference setting + * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead. */ public int getWfcMode() { - int setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - if (DBG) log("getWfcMode - setting=" + setting); - return setting; + return getWfcMode(false); } /** @@ -778,8 +779,9 @@ public class ImsManager { */ public void setWfcMode(int wfcMode) { if (DBG) log("setWfcMode(i) - setting=" + wfcMode); - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); + + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode)); setWfcModeInternal(wfcMode); } @@ -813,22 +815,35 @@ public class ImsManager { } /** - * Returns the user configuration of WFC preference setting for slot + * Returns the user configuration of WFC preference setting for slot. If not set, it + * queries CarrierConfig value as default. * * @param roaming {@code false} for home network setting, {@code true} for roaming setting */ public int getWfcMode(boolean roaming) { int setting = 0; if (!roaming) { - setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); + setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.WFC_IMS_MODE, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. + if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + setting = getIntCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT); + } if (DBG) log("getWfcMode - setting=" + setting); } else { - setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, - getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); + setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. + if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + setting = getIntCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); + } + if (DBG) log("getWfcMode (roaming) - setting=" + setting); } return setting; @@ -859,15 +874,14 @@ public class ImsManager { public void setWfcMode(int wfcMode, boolean roaming) { if (!roaming) { if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode); - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode)); } else { if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode); - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode)); } - TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); if (roaming == tm.isNetworkRoaming(getSubId())) { @@ -907,13 +921,12 @@ public class ImsManager { private void setWfcModeInternal(int wfcMode) { final int value = wfcMode; Thread thread = new Thread(() -> { - try { - getConfigInterface().setProvisionedValue( - ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, - value); - } catch (ImsException e) { - // do nothing - } + try { + getConfigInterface().setProvisionedValue( + ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value); + } catch (ImsException e) { + // do nothing + } }); thread.start(); } @@ -935,15 +948,19 @@ public class ImsManager { } /** - * Returns the user configuration of WFC roaming setting for slot + * Returns the user configuration of WFC roaming setting for slot. If not set, it + * queries CarrierConfig value as default. */ public boolean isWfcRoamingEnabledByUser() { - int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); - return (enabled == 1); + int setting = SubscriptionManager.getIntegerSubscriptionProperty( + getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + return getBooleanCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL); + } else { + return (setting == 1); + } } /** @@ -962,10 +979,9 @@ public class ImsManager { * Change persistent WFC roaming enabled setting */ public void setWfcRoamingSetting(boolean enabled) { - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - enabled ? ImsConfig.FeatureValueConstants.ON - : ImsConfig.FeatureValueConstants.OFF); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled) + ); setWfcRoamingSettingInternal(enabled); } @@ -975,13 +991,12 @@ public class ImsManager { ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF; Thread thread = new Thread(() -> { - try { - getConfigInterface().setProvisionedValue( - ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, - value); - } catch (ImsException e) { - // do nothing - } + try { + getConfigInterface().setProvisionedValue( + ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value); + } catch (ImsException e) { + // do nothing + } }); thread.start(); } @@ -2383,34 +2398,30 @@ public class ImsManager { */ public void factoryReset() { // Set VoLTE to default - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, - ImsConfig.FeatureValueConstants.ON); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(true)); // Set VoWiFi to default - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ENABLED, - getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_ENABLED, + booleanToPropertyString(getBooleanCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL))); // Set VoWiFi mode to default - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_MODE, - getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_MODE, + Integer.toString(getIntCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT))); // Set VoWiFi roaming to default - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, - getBooleanCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? - ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.WFC_IMS_ROAMING_ENABLED, + booleanToPropertyString(getBooleanCarrierConfig( + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL))); // Set VT to default - android.provider.Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.VT_IMS_ENABLED, - ImsConfig.FeatureValueConstants.ON); + SubscriptionManager.setSubscriptionProperty(getSubId(), + SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true)); // Push settings to ImsConfig updateImsServiceConfig(true); @@ -2453,6 +2464,11 @@ public class ImsManager { SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE); } + private static String booleanToPropertyString(boolean bool) { + return bool ? "1" : "0"; + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("ImsManager:"); pw.println(" mPhoneId = " + mPhoneId); -- cgit v1.2.3 From 96aee546ee86f6b3b3d8bb7e513dcfc929001492 Mon Sep 17 00:00:00 2001 From: "manabu, shimoda" Date: Fri, 6 Oct 2017 15:39:36 +0900 Subject: Replace the default value of Enhanced 4G LTE mode with to carrier config Replace the default value of Enhanced 4G LTE mode with carrier confg to control it by carrier configuration. Test: Manually override the carrier config Bug: 67725875 Change-Id: Ib4b19692670e7343e52f1840e7d768dbd3abf8f8 --- src/java/com/android/ims/ImsManager.java | 54 ++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 813118ba..f28c83c2 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -281,22 +281,28 @@ public class ImsManager { } /** - * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If not set, it - * returns true as default value. + * 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), 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() { - // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true. - // If user changes SIM from editable mode to uneditable mode, need to return true. - if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { - return true; - } - int setting = SubscriptionManager.getIntegerSubscriptionProperty( getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED, SUB_PROPERTY_NOT_INITIALIZED, mContext); + boolean onByDefault = getBooleanCarrierConfig( + CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL); - // If it's never set, by default we return true. - return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1); + // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) + || setting == SUB_PROPERTY_NOT_INITIALIZED) { + return onByDefault; + } else { + return (setting == ImsConfig.FeatureValueConstants.ON); + } } /** @@ -315,21 +321,26 @@ public class ImsManager { } /** - * Change persistent Enhanced 4G LTE Mode setting. If the the option is not editable + * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will - * always set the setting to true. + * set the setting to the default value specified by + * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}. * */ public void setEnhanced4gLteModeSetting(boolean enabled) { - // If false, we must always keep advanced 4G mode set to true. - enabled = getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) - ? enabled : true; + // If editable=false, we must keep default advanced 4G mode. + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { + enabled = getBooleanCarrierConfig( + CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL); + } int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty( getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED, SUB_PROPERTY_NOT_INITIALIZED, mContext); - if (prevSetting != (enabled ? 1 : 0)) { + if (prevSetting != (enabled ? + ImsConfig.FeatureValueConstants.ON : + ImsConfig.FeatureValueConstants.OFF)) { SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled)); if (isNonTtyOrTtyOnVolteEnabled()) { @@ -566,7 +577,8 @@ public class ImsManager { 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); } /** @@ -672,7 +684,7 @@ public class ImsManager { return getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL); } else { - return setting == 1; + return setting == ImsConfig.FeatureValueConstants.ON; } } @@ -957,7 +969,7 @@ public class ImsManager { return getBooleanCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL); } else { - return (setting == 1); + return setting == ImsConfig.FeatureValueConstants.ON; } } @@ -2405,7 +2417,9 @@ public class ImsManager { 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(), -- cgit v1.2.3 From 18837ff9ab39d96edc6962b9a2732144d96919b9 Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Wed, 25 Oct 2017 17:05:41 -0700 Subject: IMS provisioned value refactor. Instead of writing IMS provisioned values into system property, now we always query it from ImsConfig, which keeps a cach version of the values. Bug: 66701374 Test: unittest Change-Id: I4bf6880a500d7ccf1c2e149e86b803a7ae376ad9 --- src/java/com/android/ims/ImsManager.java | 214 ++++++++----------------------- 1 file changed, 55 insertions(+), 159 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index e0a966a7..1f38bceb 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -20,10 +20,7 @@ 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.IBinder; -import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.PersistableBundle; @@ -50,15 +47,14 @@ import com.android.ims.internal.IImsServiceController; import com.android.ims.internal.IImsUt; import com.android.ims.internal.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; /** * Provides APIs for IMS services, such as initiating IMS calls, and provides access to @@ -172,6 +168,11 @@ public class ImsManager { */ 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; @@ -211,10 +212,6 @@ public class ImsManager { 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"; @@ -227,19 +224,6 @@ public class ImsManager { private ConcurrentLinkedDeque 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. * @@ -408,8 +392,13 @@ public class ImsManager { * 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; } @@ -542,8 +531,12 @@ public class ImsManager { * 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; } @@ -647,10 +640,15 @@ public class ImsManager { * 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); } @@ -1036,8 +1034,12 @@ public class ImsManager { * 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; } @@ -1072,116 +1074,28 @@ public class ImsManager { } /** - * 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; - - } - } - - private class AsyncUpdateProvisionedValues extends AsyncTask { - @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(); + * 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); } + 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; } } @@ -1206,8 +1120,6 @@ public class ImsManager { /** * 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) { @@ -1222,8 +1134,6 @@ public class ImsManager { 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 @@ -1361,11 +1271,6 @@ public class ImsManager { 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(); } @@ -2462,27 +2367,18 @@ public class ImsManager { } 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) { -- cgit v1.2.3 From d0ef12c70fc9543ee85eedce106ec6b839f4cdce Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Wed, 20 Dec 2017 11:38:25 -0800 Subject: Remove DATA_ENABLED_PROP system property. DATA_ENABLED_PROP system property is used inclusively to ImsManager to keep track of whether mobile data is enabled. Now we have a system API that ImsManager can use. So we are removing it. Bug: 67602046 Test: manual and existing unit-tests Change-Id: I0e1100a72674737adcc06fe36110f4dc3ed25056 --- src/java/com/android/ims/ImsManager.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 1f38bceb..e991a5dd 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -212,10 +212,6 @@ public class ImsManager { private boolean mHasRegisteredForProxy = false; private final Object mHasRegisteredLock = new Object(); - // 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"; - public static final String TRUE = "true"; public static final String FALSE = "false"; @@ -2354,16 +2350,7 @@ public class ImsManager { } 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() { -- cgit v1.2.3 From 44fd8af20803fbdb61bcb31f653cfc1679f42499 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 14 Dec 2017 14:24:02 -0800 Subject: Integrate Registration APIs Integrates IMS Registration APIs into the platform and fixes a few issues that were occuring when switching between two different ImsServices: 1) Preserve Backwards compatibility by modifying ImsConnectionStateListener to extend the new ImsRegistration Listener APIs. 2) Add a new callback (ImsFeatureUpdate#notifyUnavailable) that is triggered by the framework when the ImsService is no longer available due to it switching or crashing. 3) Small refactor of ImsServiceProxy for initialization and querying ImsRegistration. 4) Integrate ImsRegistration into ImsManager. Bug: 63987047 Test: Manual, Telephony unit tests Change-Id: I268efbfc3df7e400a3348f9b4586edda53ca728a --- .../android/ims/ImsConnectionStateListener.java | 35 ++++- src/java/com/android/ims/ImsManager.java | 147 +++++++++++++-------- src/java/com/android/ims/ImsServiceProxy.java | 76 +++++++++-- .../com/android/ims/ImsServiceProxyCompat.java | 27 ++++ 4 files changed, 215 insertions(+), 70 deletions(-) diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index 4425854b..216bc410 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -17,15 +17,42 @@ package com.android.ims; import android.net.Uri; +import android.telephony.ims.stub.ImsRegistrationImplBase; /** * Listener for receiving notifications about changes to the IMS connection. * It provides a state of IMS registration between UE and IMS network, the service * availability of the local device during IMS registered. - * + * @Deprecated Use {@link ImsRegistrationImplBase.Callback} instead. * @hide */ -public class ImsConnectionStateListener { +public class ImsConnectionStateListener extends ImsRegistrationImplBase.Callback { + + @Override + public final void onRegistered(@ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + onImsConnected(imsRadioTech); + } + + @Override + public final void onRegistering(@ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + onImsProgressing(imsRadioTech); + } + + @Override + public final void onDeregistered(ImsReasonInfo info) { + onImsDisconnected(info); + } + + @Override + public final void onTechnologyChangeFailed( + @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { + onRegistrationChangeFailed(imsRadioTech, info); + } + + @Override + public void onSubscriberAssociatedUriChanged(Uri[] uris) { + registrationAssociatedUriChanged(uris); + } /** * Called when the device is connected to the IMS network with {@param imsRadioTech}. */ @@ -50,6 +77,7 @@ public class ImsConnectionStateListener { /** * Called when its suspended IMS connection is resumed, meaning the connection * now allows throughput. + * @deprecated not used in newer IMS provider implementations. */ public void onImsResumed() { // no-op @@ -57,6 +85,7 @@ public class ImsConnectionStateListener { /** * Called when its current IMS connection is suspended, meaning there is no data throughput. + * @deprecated not used in newer IMS provider implementations. */ public void onImsSuspended() { // no-op @@ -64,6 +93,7 @@ public class ImsConnectionStateListener { /** * Called when its current IMS connection feature capability changes. + * @deprecated Not used in newer IMS provider implementations. */ public void onFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures, int[] disabledFeatures) { @@ -72,6 +102,7 @@ public class ImsConnectionStateListener { /** * Called when waiting voice message count changes. + * @deprecated not used in newer IMS provider implementations. */ public void onVoiceMessageCountChanged(int count) { // no-op diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index e991a5dd..32d21e93 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -25,7 +25,6 @@ import android.os.Message; import android.os.Parcel; import android.os.PersistableBundle; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemProperties; import android.provider.Settings; import android.telecom.TelecomManager; @@ -34,16 +33,14 @@ import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.telephony.ims.feature.ImsFeature; 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.IImsRegistrationCallback; import com.android.ims.internal.IImsRegistrationListener; -import com.android.ims.internal.IImsServiceController; import com.android.ims.internal.IImsUt; import com.android.ims.internal.ImsCallSession; import com.android.internal.annotations.VisibleForTesting; @@ -55,6 +52,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.CopyOnWriteArraySet; /** * Provides APIs for IMS services, such as initiating IMS calls, and provides access to @@ -78,13 +76,6 @@ public class ImsManager { public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off"; public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0; - /** - * For accessing the IMS related service. - * Internal use only. - * @hide - */ - private static final String IMS_SERVICE = "ims"; - /** * The result code to be sent back with the incoming call {@link PendingIntent}. * @see #open(PendingIntent, ImsConnectionStateListener) @@ -198,14 +189,20 @@ public class ImsManager { private ImsMultiEndpoint mMultiEndpoint = null; - private Set mStatusCallbacks = new HashSet<>(); + private Set mStatusCallbacks = new CopyOnWriteArraySet<>(); // Keep track of the ImsRegistrationListenerProxys that have been created so that we can // remove them from the ImsService. private final Set mRegistrationListeners = new HashSet<>(); - private final ImsRegistrationListenerProxy mRegistrationListenerProxy = + + // 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. @@ -1314,7 +1311,7 @@ public class ImsManager { * 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.INotifyStatusChanged c) + public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c) throws ImsException { if (!mImsServiceProxy.isBinderAlive()) { throw new ImsException("Binder is not active!", @@ -1325,6 +1322,14 @@ public class ImsManager { } } + public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) { + if (c != null) { + mStatusCallbacks.remove(c); + } else { + Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!"); + } + } + /** * Opens the IMS service for making calls and/or receiving generic IMS calls. * The caller may make subsquent calls through {@link #makeCall}. @@ -1409,9 +1414,7 @@ public class ImsManager { * @throws NullPointerException if {@code listener} is null * @throws ImsException if calling the IMS service results in an error */ - public void addRegistrationListener(ImsConnectionStateListener listener) - throws ImsException { - + public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException { if (listener == null) { throw new NullPointerException("listener can't be null"); } @@ -1420,8 +1423,11 @@ public class ImsManager { if (!mHasRegisteredForProxy) { try { checkAndThrowExceptionIfServiceUnavailable(); - mImsServiceProxy.addRegistrationListener(mRegistrationListenerProxy); - log("RegistrationListenerProxy registered."); + // TODO: Remove once new MmTelFeature is merged in + mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy); + mImsServiceProxy.getRegistration().addRegistrationCallback( + mRegistrationCallback); + log("Registration Callback/Listener registered."); // Only record if there isn't a RemoteException. mHasRegisteredForProxy = true; } catch (RemoteException e) { @@ -1861,53 +1867,31 @@ public class ImsManager { */ private void createImsService() { if (!mConfigDynamicBind) { - // Old method of binding + // Deprecated method of binding Rlog.i(TAG, "Creating ImsService using ServiceManager"); - mImsServiceProxy = getServiceProxyCompat(); + mImsServiceProxy = ImsServiceProxyCompat.create(mPhoneId, mDeathRecipient); } else { Rlog.i(TAG, "Creating ImsService using ImsResolver"); - mImsServiceProxy = getServiceProxy(); + mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId); } + // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable. + mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() { + @Override + public void notifyStateChanged() { + mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged); + } + + @Override + public void notifyUnavailable() { + mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable); + } + }); // We have created a new ImsService connection, signal for re-registration synchronized (mHasRegisteredLock) { mHasRegisteredForProxy = false; } } - // Deprecated method of binding with the ImsService defined in the ServiceManager. - private ImsServiceProxyCompat getServiceProxyCompat() { - IBinder binder = ServiceManager.checkService(IMS_SERVICE); - - if (binder != null) { - try { - binder.linkToDeath(mDeathRecipient, 0); - } catch (RemoteException e) { - } - } - - return new ImsServiceProxyCompat(mPhoneId, binder); - } - - // New method of binding with the ImsResolver - private ImsServiceProxy getServiceProxy() { - TelephonyManager tm = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL); - serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach( - ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged)); - // Returns null if the service is not available. - IImsMMTelFeature b = tm.getImsMMTelFeatureAndListen(mPhoneId, - serviceProxy.getListener()); - if (b != null) { - serviceProxy.setBinder(b.asBinder()); - // Trigger the cache to be updated for feature status. - serviceProxy.getFeatureStatus(); - } else { - Rlog.w(TAG, "getServiceProxy: b is null! Phone Id: " + mPhoneId); - } - return serviceProxy; - } - /** * Creates a {@link ImsCallSession} with the specified call profile. * Use other methods, if applicable, instead of interacting with @@ -2238,6 +2222,57 @@ public class ImsManager { } } + // 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. * diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index f3489194..543e31ef 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -16,10 +16,14 @@ 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.feature.ImsFeature; import android.util.Log; @@ -29,6 +33,7 @@ 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.IImsUt; @@ -41,20 +46,58 @@ import com.android.ims.internal.IImsUt; public class ImsServiceProxy { - protected String LOG_TAG = "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 ImsServiceProxy.INotifyStatusChanged mStatusCallback; + private IFeatureUpdate mStatusCallback; private final Object mLock = new Object(); - public interface INotifyStatusChanged { - void notifyStatusChanged(); + 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 = @@ -65,7 +108,7 @@ public class ImsServiceProxy { // The feature has been re-enabled. This may happen when the service crashes. synchronized (mLock) { if (!mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { - Log.i(LOG_TAG, "Feature enabled on slotId: " + slotId + " for feature: " + + Log.i(TAG, "Feature enabled on slotId: " + slotId + " for feature: " + feature); mIsAvailable = true; } @@ -76,9 +119,12 @@ public class ImsServiceProxy { public void imsFeatureRemoved(int slotId, int feature) throws RemoteException { synchronized (mLock) { if (mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { - Log.i(LOG_TAG, "Feature disabled on slotId: " + slotId + " for feature: " + + Log.i(TAG, "Feature disabled on slotId: " + slotId + " for feature: " + feature); mIsAvailable = false; + if (mStatusCallback != null) { + mStatusCallback.notifyUnavailable(); + } } } } @@ -86,12 +132,12 @@ public class ImsServiceProxy { @Override public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException { synchronized (mLock) { - Log.i(LOG_TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature + + Log.i(TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature + " status: " + status); if (mSlotId == slotId && feature == mSupportedFeature) { mFeatureStatusCached = status; if (mStatusCallback != null) { - mStatusCallback.notifyStatusChanged(); + mStatusCallback.notifyStateChanged(); } } } @@ -104,8 +150,14 @@ public class ImsServiceProxy { mSupportedFeature = featureType; } - public ImsServiceProxy(int slotId, int featureType) { + public ImsServiceProxy(Context context, int slotId, int featureType) { this(slotId, null, featureType); + mContext = context; + } + + public @Nullable IImsRegistration getRegistration() { + TelephonyManager tm = getTelephonyManager(mContext); + return tm != null ? tm.getImsRegistration(mSlotId, ImsFeature.MMTEL) : null; } public IImsServiceFeatureCallback getListener() { @@ -246,7 +298,7 @@ public class ImsServiceProxy { public int getFeatureStatus() { synchronized (mLock) { if (isBinderAlive() && mFeatureStatusCached != null) { - Log.i(LOG_TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached); + Log.i(TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached); return mFeatureStatusCached; } } @@ -259,7 +311,7 @@ public class ImsServiceProxy { // Cache only non-null value for feature status. mFeatureStatusCached = status; } - Log.i(LOG_TAG, "getFeatureStatus - returning " + status); + Log.i(TAG, "getFeatureStatus - returning " + status); return status; } @@ -280,7 +332,7 @@ public class ImsServiceProxy { /** * @param c Callback that will fire when the feature status has changed. */ - public void setStatusCallback(INotifyStatusChanged c) { + public void setStatusCallback(IFeatureUpdate c) { mStatusCallback = c; } diff --git a/src/java/com/android/ims/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java index 5ba1f351..44f72e6a 100644 --- a/src/java/com/android/ims/ImsServiceProxyCompat.java +++ b/src/java/com/android/ims/ImsServiceProxyCompat.java @@ -17,15 +17,20 @@ 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; @@ -42,6 +47,28 @@ 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(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(slotId, binder); + } + public ImsServiceProxyCompat(int slotId, IBinder binder) { super(slotId, binder, SERVICE_ID); } -- cgit v1.2.3 From 4d68a98979d3cbf25011c5aa5f9971a3b9b33c75 Mon Sep 17 00:00:00 2001 From: Mohamed Abdalkader Date: Wed, 10 Jan 2018 13:29:26 -0800 Subject: Expose SMS Apis through ImsServiceProxy. Test: manual, telephony unit tests. BUG=69846044 Change-Id: I36a3a7e94546e1bcd7c4af9b9335378404833b4a --- src/java/com/android/ims/ImsManager.java | 46 +++++++++++++++++++++++++++ src/java/com/android/ims/ImsServiceProxy.java | 42 ++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 32d21e93..d335fa2e 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -41,6 +41,8 @@ import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; 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 com.android.internal.annotations.VisibleForTesting; @@ -2301,6 +2303,50 @@ public class ImsManager { return mEcbm; } + 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); + } catch (RemoteException e) { + throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } + + public void acknowledgeSms(int token, int messageRef, int result) throws ImsException { + try { + mImsServiceProxy.acknowledgeSms(token, messageRef, result); + } catch (RemoteException e) { + throw new ImsException("acknowledgeSms()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } + + public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{ + try { + mImsServiceProxy.acknowledgeSmsReport(token, messageRef, result); + } catch (RemoteException e) { + throw new ImsException("acknowledgeSmsReport()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } + + public String getSmsFormat() throws ImsException{ + try { + return mImsServiceProxy.getSmsFormat(); + } catch (RemoteException e) { + throw new ImsException("getSmsFormat()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } + + public void setSmsListener(IImsSmsListener listener) throws ImsException { + try { + mImsServiceProxy.setSmsListener(listener); + } catch (RemoteException e) { + throw new ImsException("setSmsListener()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } /** * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications.. * diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index 543e31ef..a22dadd4 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -25,6 +25,8 @@ import android.os.RemoteException; import android.telephony.Rlog; import android.telephony.TelephonyManager; import android.telephony.ims.feature.ImsFeature; +import android.telephony.SmsMessage; +import android.telephony.ims.internal.SmsImplBase; import android.util.Log; import com.android.ims.internal.IImsCallSession; @@ -36,6 +38,7 @@ 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; /** @@ -336,6 +339,45 @@ public class ImsServiceProxy { 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 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 -- cgit v1.2.3 From e1453f43ef9785dc22b6d70b87916408e35b9874 Mon Sep 17 00:00:00 2001 From: Mohamed Abdalkader Date: Fri, 19 Jan 2018 19:48:31 -0800 Subject: Add stub implementation of adding reg and cap callbacks. To unblock SMS/IMS reg integration. Test: manually testing failure and retry logic only now as testing success case is not yet feisble. BUG=69846044 Change-Id: I7b6066306a09db9dfd0f332661ea078407c5a960 --- src/java/com/android/ims/ImsManager.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index c73db6ad..d8ada6fe 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -29,6 +29,8 @@ 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; @@ -2350,6 +2352,15 @@ public class ImsManager { 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.. * -- cgit v1.2.3 From c47babb13958b24c4a972b8f64a5a4acbf433468 Mon Sep 17 00:00:00 2001 From: Mohamed Abdalkader Date: Mon, 22 Jan 2018 16:03:21 -0800 Subject: Fix accidental use of internal version of sms apis. Test: manual BUG=69846044 Change-Id: Id60c34793606436e7946e44e48432ed9922415fa --- src/java/com/android/ims/ImsServiceProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index 153c5f52..7fcaac2b 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -26,7 +26,7 @@ import android.telephony.Rlog; import android.telephony.TelephonyManager; import android.telephony.ims.feature.ImsFeature; import android.telephony.SmsMessage; -import android.telephony.ims.internal.SmsImplBase; +import android.telephony.ims.internal.stub.SmsImplBase; import android.util.Log; import com.android.ims.internal.IImsCallSession; -- cgit v1.2.3 From 0e734e17231072b8d9cc60784c962eccc54a96f1 Mon Sep 17 00:00:00 2001 From: Mohamed Abdalkader Date: Tue, 23 Jan 2018 13:11:00 -0800 Subject: Add and trigger onReady API for SMS over IMS Test: manual test that normal code path is fine since this code path is not yet exercisable. BUG=69846044 Change-Id: Id56b04eea65ee06953cc819bab07b2659da2738c --- src/java/com/android/ims/ImsManager.java | 9 +++++++++ src/java/com/android/ims/ImsServiceProxy.java | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index d8ada6fe..e86bfde7 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -2353,6 +2353,15 @@ public class ImsManager { } } + public void onSmsReady() throws ImsException{ + try { + mImsServiceProxy.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) } diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index 7fcaac2b..4ac8fea4 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -371,6 +371,13 @@ public class ImsServiceProxy { } } + public void onSmsReady() throws RemoteException { + synchronized (mLock) { + checkServiceIsReady(); + getServiceInterface(mBinder).onSmsReady(); + } + } + public void setSmsListener(IImsSmsListener listener) throws RemoteException { synchronized (mLock) { checkServiceIsReady(); -- cgit v1.2.3 From 318ea44a124f41f50cc845df5d8335aed88bee77 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 11 Jan 2018 10:29:04 -0800 Subject: Integrate new ImsCallSessionListener Modify MMTelFeature#createCallSession to not take ImsCallSessionListener. This is set by setListener. Test: Manual IMS Tests Bug: 63987047 Change-Id: Ibfcf2e6d496bb6c834148531d46da1308fcf029b --- src/java/com/android/ims/ImsManager.java | 2 +- src/java/com/android/ims/ImsServiceProxy.java | 8 ++++---- src/java/com/android/ims/ImsServiceProxyCompat.java | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index e86bfde7..0df9b51f 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -1911,7 +1911,7 @@ public class ImsManager { 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, null)); + return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile)); } catch (RemoteException e) { Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage()); throw new ImsException("createCallSession()", e, diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index 4ac8fea4..a8744361 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -24,13 +24,13 @@ 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.IImsCallSessionListener; import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMMTelFeature; @@ -228,11 +228,11 @@ public class ImsServiceProxy { } } - public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, - IImsCallSessionListener listener) throws RemoteException { + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) + throws RemoteException { synchronized (mLock) { checkServiceIsReady(); - return getServiceInterface(mBinder).createCallSession(sessionId, profile, listener); + return getServiceInterface(mBinder).createCallSession(sessionId, profile); } } diff --git a/src/java/com/android/ims/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java index a6d1865e..d5f211a0 100644 --- a/src/java/com/android/ims/ImsServiceProxyCompat.java +++ b/src/java/com/android/ims/ImsServiceProxyCompat.java @@ -123,10 +123,10 @@ public class ImsServiceProxyCompat extends ImsServiceProxy { } @Override - public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile, - IImsCallSessionListener listener) throws RemoteException { + public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile) + throws RemoteException { checkBinderConnection(); - return getServiceInterface(mBinder).createCallSession(sessionId, profile, listener); + return getServiceInterface(mBinder).createCallSession(sessionId, profile, null); } @Override -- cgit v1.2.3 From 172977ad7b0d5f4f91146c1a25d29189527781b2 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Tue, 16 Jan 2018 09:36:56 -0800 Subject: Integrate MMTel APIs into the framework 1) Integrates the new ImsService APIs into ImsManager. 2) Removes all Compat layers (ImsServiceProxy) and moves all relevant functionality into MmTelFeatureConnection. Also tries to encapsulate more of the MmTel specific functionality in this class. 3) Compat method for ImsConnectionStateListener that converts old method of updating MMTel capabilites to the new method. Bug: 63987047 Test: Telephony Test ImsService App Change-Id: Ic30429bed05191f00a8e4bc1d2b63f125d4e7524 --- .../android/ims/ImsConnectionStateListener.java | 67 ++ src/java/com/android/ims/ImsManager.java | 814 ++++++--------------- .../com/android/ims/ImsServiceProxyCompat.java | 194 ----- .../com/android/ims/MmTelFeatureConnection.java | 614 ++++++++++++++++ 4 files changed, 913 insertions(+), 776 deletions(-) delete mode 100644 src/java/com/android/ims/ImsServiceProxyCompat.java create mode 100644 src/java/com/android/ims/MmTelFeatureConnection.java diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index 216bc410..049b846d 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -17,8 +17,12 @@ package com.android.ims; import android.net.Uri; +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 +57,69 @@ public class ImsConnectionStateListener extends ImsRegistrationImplBase.Callback 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/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 0df9b51f..bb2b237d 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -16,36 +16,34 @@ 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.Bundle; import android.os.IBinder; 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.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.telephony.ims.stub.ImsRegistrationImplBase; 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 com.android.internal.annotations.VisibleForTesting; @@ -54,7 +52,6 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.CopyOnWriteArraySet; @@ -83,13 +80,13 @@ public class ImsManager { /** * 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"; @@ -179,7 +176,7 @@ public class ImsManager { 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; @@ -194,25 +191,8 @@ public class ImsManager { private ImsMultiEndpoint mMultiEndpoint = null; - private Set mStatusCallbacks = new CopyOnWriteArraySet<>(); - - // Keep track of the ImsRegistrationListenerProxys that have been created so that we can - // remove them from the ImsService. - private final Set 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(); + private Set mStatusCallbacks = + new CopyOnWriteArraySet<>(); public static final String TRUE = "true"; public static final String FALSE = "false"; @@ -591,16 +571,12 @@ public class ImsManager { * 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"); @@ -611,7 +587,10 @@ public class ImsManager { 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); } } @@ -715,18 +694,13 @@ public class ImsManager { * @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"); @@ -739,7 +713,7 @@ public class ImsManager { } setWfcModeInternal(imsWfcModeFeatureValue); - } catch (ImsException e) { + } catch (ImsException | RemoteException e) { loge("setWfcSetting(): ", e); } } @@ -913,7 +887,7 @@ public class ImsManager { 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) { @@ -929,7 +903,7 @@ public class ImsManager { 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 @@ -999,7 +973,7 @@ public class ImsManager { : ImsConfig.FeatureValueConstants.OFF; Thread thread = new Thread(() -> { try { - getConfigInterface().setProvisionedValue( + getConfigInterface().setConfig( ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value); } catch (ImsException e) { // do nothing @@ -1135,8 +1109,8 @@ public class ImsManager { // 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(); @@ -1155,7 +1129,7 @@ public class ImsManager { } mConfigUpdated = true; - } catch (ImsException e) { + } catch (ImsException | RemoteException e) { loge("updateImsServiceConfig: ", e); mConfigUpdated = false; } @@ -1167,7 +1141,7 @@ public class ImsManager { * @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(); @@ -1177,13 +1151,8 @@ public class ImsManager { + ", 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; } @@ -1193,7 +1162,7 @@ public class ImsManager { * @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(); @@ -1209,13 +1178,8 @@ public class ImsManager { + ", 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; } @@ -1225,7 +1189,7 @@ public class ImsManager { * @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(); @@ -1240,13 +1204,8 @@ public class ImsManager { + ", 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; @@ -1287,7 +1246,7 @@ public class ImsManager { public boolean isServiceAvailable() { connectIfServiceIsAvailable(); // mImsServiceProxy will always create an ImsServiceProxy. - return mImsServiceProxy.isBinderAlive(); + return mMmTelFeatureConnection.isBinderAlive(); } /* @@ -1295,19 +1254,19 @@ public class ImsManager { */ 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; } @@ -1316,9 +1275,9 @@ public class ImsManager { * 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); } @@ -1327,7 +1286,7 @@ public class ImsManager { } } - public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) { + public void removeNotifyStatusChangedCallback(MmTelFeatureConnection.IFeatureUpdate c) { if (c != null) { mStatusCallbacks.remove(c); } else { @@ -1337,63 +1296,30 @@ public class ImsManager { /** * 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; } /** @@ -1418,34 +1344,68 @@ public class ImsManager { * @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); } } @@ -1463,33 +1423,38 @@ public class ImsManager { 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; } /** @@ -1498,8 +1463,7 @@ public class ImsManager { * @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; @@ -1507,7 +1471,7 @@ public class ImsManager { checkAndThrowExceptionIfServiceUnavailable(); try { - IImsUt iUt = mImsServiceProxy.getUtInterface(); + IImsUt iUt = mMmTelFeatureConnection.getUtInterface(); if (iUt == null) { throw new ImsException("getSupplementaryServiceConfiguration()", @@ -1522,55 +1486,9 @@ public class ImsManager { return mUt; } - /** - * 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} @@ -1587,12 +1505,11 @@ public class ImsManager { * @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); @@ -1602,19 +1519,17 @@ public class ImsManager { /** * 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(); @@ -1622,7 +1537,7 @@ public class ImsManager { 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]); @@ -1637,33 +1552,25 @@ public class ImsManager { * 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", @@ -1671,8 +1578,6 @@ public class ImsManager { } 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); @@ -1702,7 +1607,7 @@ public class ImsManager { checkAndThrowExceptionIfServiceUnavailable(); try { - IImsConfig config = mImsServiceProxy.getConfigInterface(); + IImsConfig config = mMmTelFeatureConnection.getConfigInterface(); if (config == null) { throw new ImsException("getConfigInterface()", ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); @@ -1715,6 +1620,25 @@ public class ImsManager { 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); + } + } + /** * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status) */ @@ -1736,7 +1660,7 @@ public class ImsManager { checkAndThrowExceptionIfServiceUnavailable(); try { - mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete); + mMmTelFeatureConnection.setUiTTYMode(uiTtyMode, onComplete); } catch (RemoteException e) { throw new ImsException("setTTYMode()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); @@ -1768,8 +1692,8 @@ public class ImsManager { return disconnectReasons; } - public int getImsServiceStatus() throws ImsException { - return mImsServiceProxy.getFeatureStatus(); + public int getImsServiceState() throws ImsException { + return mMmTelFeatureConnection.getFeatureState(); } /** @@ -1825,29 +1749,15 @@ public class ImsManager { /** * 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); } /** @@ -1856,10 +1766,10 @@ public class ImsManager { */ 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); } @@ -1873,30 +1783,21 @@ public class ImsManager { * 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; - } } /** @@ -1904,14 +1805,12 @@ public class ImsManager { * 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, @@ -1936,13 +1835,9 @@ public class ImsManager { * 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() { @@ -1953,25 +1848,36 @@ public class ImsManager { 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); - - 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); - } + 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()); + 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()); } } @@ -1999,13 +1905,9 @@ public class ImsManager { * 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) { @@ -2022,7 +1924,7 @@ public class ImsManager { private class ImsServiceDeathRecipient implements IBinder.DeathRecipient { @Override public void binderDied() { - mImsServiceProxy = null; + mMmTelFeatureConnection = null; mUt = null; mConfig = null; mEcbm = null; @@ -2030,271 +1932,20 @@ public class ImsManager { } } - /** - * 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()", @@ -2311,7 +1962,7 @@ public class ImsManager { 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); } @@ -2319,7 +1970,7 @@ public class ImsManager { 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); @@ -2328,7 +1979,7 @@ public class ImsManager { 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); @@ -2337,7 +1988,7 @@ public class ImsManager { 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); @@ -2346,7 +1997,7 @@ public class ImsManager { 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); @@ -2373,18 +2024,17 @@ public class ImsManager { /** * 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()", @@ -2481,7 +2131,7 @@ public class ImsManager { 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/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java deleted file mode 100644 index d5f211a0..00000000 --- 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/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java new file mode 100644 index 00000000..00dec65c --- /dev/null +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -0,0 +1,614 @@ +/* + * 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.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 { + private static final String TAG = "CallbackAdapterManager"; + + protected final Set 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 { + 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 { + 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 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."); + } + } +} -- cgit v1.2.3 From 190ed93698d354e1087d9d55af7ba81ab7c7e74a Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Tue, 23 Jan 2018 13:41:32 -0800 Subject: Change ImsService namespaces Moves some of the ImsService namespaces to support the move to @SystemApi. Test: Telephony Unit tests Bug: 63987047 Change-Id: I4d1a0afc926dfd7d70b3db16dd81f986585a0992 --- src/java/com/android/ims/ImsCall.java | 7 +- .../android/ims/ImsConnectionStateListener.java | 1 + src/java/com/android/ims/ImsEcbm.java | 8 +- .../android/ims/ImsExternalCallStateListener.java | 2 + src/java/com/android/ims/ImsManager.java | 16 +- src/java/com/android/ims/ImsMultiEndpoint.java | 2 + src/java/com/android/ims/ImsServiceBase.java | 2 +- src/java/com/android/ims/ImsServiceProxy.java | 423 --------------------- src/java/com/android/ims/ImsUt.java | 4 + .../com/android/ims/MmTelFeatureConnection.java | 9 + .../android/ims/internal/VideoPauseTracker.java | 6 +- tests/src/com/android/ims/ImsConfigTest.java | 5 +- 12 files changed, 35 insertions(+), 450 deletions(-) delete mode 100644 src/java/com/android/ims/ImsServiceProxy.java diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index 6200a07c..760e5e81 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -36,10 +36,15 @@ import java.util.Objects; 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; diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index 049b846d..d5fb633c 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -17,6 +17,7 @@ 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; diff --git a/src/java/com/android/ims/ImsEcbm.java b/src/java/com/android/ims/ImsEcbm.java index 53549bf0..99d99f17 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 3f4f163f..aae4c9b8 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 bb2b237d..063f5a86 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -28,24 +28,24 @@ import android.os.RemoteException; import android.os.SystemProperties; 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.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.telephony.ims.stub.ImsRegistrationImplBase; 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.IImsUt; -import com.android.ims.internal.ImsCallSession; +import android.telephony.ims.ImsCallSession; import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; @@ -2006,21 +2006,13 @@ public class ImsManager { 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.. * diff --git a/src/java/com/android/ims/ImsMultiEndpoint.java b/src/java/com/android/ims/ImsMultiEndpoint.java index 96926960..1315dbd3 100644 --- a/src/java/com/android/ims/ImsMultiEndpoint.java +++ b/src/java/com/android/ims/ImsMultiEndpoint.java @@ -21,6 +21,8 @@ import com.android.ims.internal.IImsExternalCallStateListener; 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 66122df6..0a15c9d9 100644 --- a/src/java/com/android/ims/ImsServiceBase.java +++ b/src/java/com/android/ims/ImsServiceBase.java @@ -18,7 +18,7 @@ package com.android.ims; 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 a8744361..00000000 --- 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/ImsUt.java b/src/java/com/android/ims/ImsUt.java index eaeb5511..b3d4c8af 100644 --- a/src/java/com/android/ims/ImsUt.java +++ b/src/java/com/android/ims/ImsUt.java @@ -27,6 +27,10 @@ import android.os.Message; 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 index 00dec65c..571670d5 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -24,6 +24,8 @@ 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; @@ -524,6 +526,13 @@ public class MmTelFeatureConnection { } } + public void onSmsReady() throws RemoteException { + synchronized (mLock) { + checkServiceIsReady(); + getServiceInterface(mBinder).onSmsReady(); + } + } + public void setSmsListener(IImsSmsListener listener) throws RemoteException { synchronized (mLock) { checkServiceIsReady(); diff --git a/src/java/com/android/ims/internal/VideoPauseTracker.java b/src/java/com/android/ims/internal/VideoPauseTracker.java index baa3163f..92430082 100644 --- a/src/java/com/android/ims/internal/VideoPauseTracker.java +++ b/src/java/com/android/ims/internal/VideoPauseTracker.java @@ -18,11 +18,11 @@ package com.android.ims.internal; 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 @@ public class VideoPauseTracker { * * @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 @@ public class VideoPauseTracker { * * @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 18d53b1c..4cf7a926 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 @@ public class ImsConfigTest extends ImsTestBase { mTestImsConfig.getProvisionedValue(testItem); - verify(mMockImsConfigInterface).getProvisionedValue(eq(testItem)); + verify(mMockImsConfigInterface).getConfigInt(eq(testItem)); } } -- cgit v1.2.3 From b77d897e37ce5c04e0704b4f516b4240b9ace68d Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Mon, 22 Jan 2018 19:15:05 -0800 Subject: RTT bugfixes and logging Add logging for RTT interface with IMS stack Fix a few bugs relating to RTT requests and initialization Add a method to set the RTT config value in the IMS stack Bug: 63934808 Bug: 72156722 Test: manual Change-Id: I44934ef53c9cc821582b381d82ee6834a9bdfe6a --- src/java/com/android/ims/ImsCall.java | 3 +++ src/java/com/android/ims/ImsManager.java | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index 760e5e81..e32103ef 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -1628,6 +1628,7 @@ public class ImsCall implements ICall { // 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); @@ -3077,6 +3078,7 @@ public class ImsCall implements ICall { public void callSessionRttModifyRequestReceived(ImsCallSession session, ImsCallProfile callProfile) { ImsCall.Listener listener; + logi("callSessionRttModifyRequestReceived"); synchronized(ImsCall.this) { listener = mListener; @@ -3101,6 +3103,7 @@ public class ImsCall implements ICall { public void callSessionRttModifyResponseReceived(int status) { ImsCall.Listener listener; + logi("callSessionRttModifyResponseReceived"); synchronized(ImsCall.this) { listener = mListener; } diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 063f5a86..0a0eb249 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -1639,6 +1639,28 @@ public class ImsManager { } } + 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) */ -- cgit v1.2.3 From 43213e2b9bf20b8395d4f081a64c4ef39342e04f Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Fri, 9 Feb 2018 16:55:05 -0800 Subject: Rtt bugfixes, part 5 * Answer RTT incoming calls with the proper bit set in ImsStreamMediaProfile Bug: 72762206 Test: manual Change-Id: Ic3c4517a06f57d6c5a2a1d92e5eab9df9929dd64 --- src/java/com/android/ims/ImsCall.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index 1d728a1a..40d9faa2 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -604,6 +604,12 @@ public class ImsCall implements ICall { */ private int mOverrideReason = ImsReasonInfo.CODE_UNSPECIFIED; + /** + * When true, if this call is incoming, it will be answered with an + * {@link ImsStreamMediaProfile} that has RTT enabled. + */ + private boolean mAnswerWithRtt = false; + /** * Create an IMS call object. * @@ -1135,6 +1141,11 @@ public class ImsCall implements ICall { public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException { logi("accept :: callType=" + callType + ", profile=" + profile); + if (mAnswerWithRtt) { + profile.mRttMode = ImsStreamMediaProfile.RTT_MODE_FULL; + logi("accept :: changing media profile RTT mode to full"); + } + synchronized(mLockObj) { if (mSession == null) { throw new ImsException("No call to answer", @@ -1681,6 +1692,10 @@ public class ImsCall implements ICall { } } + public void setAnswerWithRtt() { + mAnswerWithRtt = true; + } + private void clear(ImsReasonInfo lastReasonInfo) { mInCall = false; mHold = false; -- cgit v1.2.3 From 27b7c1d502149ab8cee920282721933245c7b525 Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Tue, 27 Feb 2018 13:04:12 -0800 Subject: RTT logging tweaks Add response status to RTT upgrade response log Test: logging change Change-Id: Ibab5624fefa1c9f8fb63da03b419e0cf9b62d496 --- src/java/com/android/ims/ImsCall.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index 40d9faa2..582a0269 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -3142,7 +3142,7 @@ public class ImsCall implements ICall { public void callSessionRttModifyResponseReceived(int status) { ImsCall.Listener listener; - logi("callSessionRttModifyResponseReceived"); + logi("callSessionRttModifyResponseReceived: " + status); synchronized(ImsCall.this) { listener = mListener; } -- cgit v1.2.3 From 0aed76da29d1ffbf4b515b2835567cff8dac465a Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Mon, 5 Mar 2018 16:39:02 -0800 Subject: Dynamic Query for ImsService 1) Fixes ImsManager.Connector bug where we would reset retry count, even if there was an ImsException. 2) ImsManager#isServiceAvailable now uses ImsResolver state to figure out if an ImsService is possibly going to bind/ unbind. Test: Telephony test ImsService, telephony unit tests Bug: 72642524 Merged-In: I6d68b98126b2b682b4f2c54947acdd90e7bc51b0 Change-Id: Iac4de9091c3374970be450930424a22d9158de13 --- src/java/com/android/ims/ImsManager.java | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 521b46ad..29176a27 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -339,10 +339,19 @@ public class ImsManager { private void notifyReady() throws ImsException { ImsManager manager; synchronized (mLock) { - mRetryCount = 0; manager = mImsManager; } - mListener.connectionReady(manager); + try { + mListener.connectionReady(manager); + } + catch (ImsException e) { + Log.w(TAG, "Connector: notifyReady exception: " + e.getMessage()); + throw e; + } + // Only reset retry count if connectionReady does not generate an ImsException/ + synchronized (mLock) { + mRetryCount = 0; + } } private void notifyNotReady() { @@ -1421,10 +1430,18 @@ public class ImsManager { } /* - * Returns a flag indicating whether the IMS service is available. If it is not available, - * it will try to connect before reporting failure. + * Returns a flag indicating whether the IMS service is available. If it is not available or + * busy, it will try to connect before reporting failure. */ public boolean isServiceAvailable() { + // If we are busy resolving dynamic IMS bindings, we are not available yet. + TelephonyManager tm = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + if (tm.isResolvingImsBinding()) { + Log.d(TAG, "isServiceAvailable: resolving IMS binding, returning false"); + return false; + } + connectIfServiceIsAvailable(); // mImsServiceProxy will always create an ImsServiceProxy. return mMmTelFeatureConnection.isBinderAlive(); -- cgit v1.2.3 From d1b1a3cb525ce13cf10e327c8de5878b73d7a5cd Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 8 Mar 2018 11:37:35 -0800 Subject: Add ImsManager#removeRegistrationListener Adds a removeRegistrationListener API to complement the existing add method. Bug: 73951668 Test: Manual Merged-In: Ieee1d53763d3544ad8e014f900559559c043248c Change-Id: I3c31236ec51480c819936a7ba1fac882d5a42200 --- src/java/com/android/ims/ImsManager.java | 22 +++++++++++++++++++++- .../com/android/ims/MmTelFeatureConnection.java | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 521b46ad..3a971cf4 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -1556,7 +1556,6 @@ public class ImsManager { throw new NullPointerException("registration callback can't be null"); } - checkAndThrowExceptionIfServiceUnavailable(); try { mMmTelFeatureConnection.addRegistrationCallback(callback); log("Registration Callback registered."); @@ -1567,6 +1566,27 @@ public class ImsManager { } } + /** + * Removes a previously added registration callback that was added via + * {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} . + * @param callback A {@link ImsRegistrationImplBase.Callback} that was previously added. + * @throws ImsException when the ImsService connection is not available. + */ + public void removeRegistrationListener(ImsRegistrationImplBase.Callback callback) + throws ImsException { + if (callback == null) { + throw new NullPointerException("registration callback can't be null"); + } + + try { + mMmTelFeatureConnection.removeRegistrationCallback(callback); + log("Registration callback removed."); + } catch (RemoteException e) { + throw new ImsException("removeRegistrationCallback(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. diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index 2d11ae60..6028f6f3 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -196,7 +196,7 @@ public class MmTelFeatureConnection { IImsRegistration imsRegistration = getRegistration(); if (imsRegistration != null) { try { - getRegistration().addRegistrationCallback(mRegistrationCallbackAdapter); + getRegistration().removeRegistrationCallback(mRegistrationCallbackAdapter); } catch (RemoteException e) { Log.w(TAG, "removeConnection: couldn't remove registration callback"); } -- cgit v1.2.3 From fe2b2222bb6ab7049a8c869972bd6012cfaf2a02 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 8 Mar 2018 16:16:15 -0800 Subject: Moves IMS Emergency Calling state The IMS Emergency Calling availability state used to be stored in the ImsServiceController and polled when needed. This change moves the state to MmTelFeatureConnection via an update. By moving it here, we can reduce the number of calls through TelephonyManager and support MSIM. Bug: 74389647 Test: Telephony Unit Tests, Telephony Test ImsService app Merged-In: I692cd6b41f787bb1f75d696f2f2a73c79b03e0e8 Change-Id: I35ff8723afff2e69ab36e6e99c2efd5ae7a4868a --- .../com/android/ims/MmTelFeatureConnection.java | 57 ++++++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index 6028f6f3..276688c4 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -60,12 +60,13 @@ public class MmTelFeatureConnection { protected IBinder mBinder; private Context mContext; - // Start by assuming the proxy is available for usage. - private volatile boolean mIsAvailable = true; + private volatile boolean mIsAvailable = false; // ImsFeature Status from the ImsService. Cached. private Integer mFeatureStateCached = null; private IFeatureUpdate mStatusCallback; private final Object mLock = new Object(); + // Updated by IImsServiceFeatureCallback when FEATURE_EMERGENCY_MMTEL is sent. + private boolean mSupportsEmergencyCalling = false; private MmTelFeature.Listener mMmTelFeatureListener; @@ -297,25 +298,51 @@ public class MmTelFeatureConnection { @Override public void imsFeatureCreated(int slotId, int feature) throws RemoteException { - // The feature has been re-enabled. This may happen when the service crashes. + // The feature has been enabled. This happens when the feature is first created and may + // happen when the feature is re-enabled. synchronized (mLock) { - if (!mIsAvailable && mSlotId == slotId && feature == ImsFeature.FEATURE_MMTEL) { - Log.i(TAG, "Feature enabled on slotId: " + slotId + " for feature: " + - feature); - mIsAvailable = true; + if(mSlotId != slotId) { + return; } + switch (feature) { + case ImsFeature.FEATURE_MMTEL: { + if (!mIsAvailable) { + Log.i(TAG, "MmTel enabled on slotId: " + slotId); + mIsAvailable = true; + } + break; + } + case ImsFeature.FEATURE_EMERGENCY_MMTEL: { + mSupportsEmergencyCalling = true; + Log.i(TAG, "Emergency calling enabled on slotId: " + slotId); + break; + } + } + } } @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(); + if(mSlotId != slotId) { + return; + } + switch (feature) { + case ImsFeature.FEATURE_MMTEL: { + if (mIsAvailable) { + Log.i(TAG, "MmTel disabled on slotId: " + slotId); + mIsAvailable = false; + if (mStatusCallback != null) { + mStatusCallback.notifyUnavailable(); + } + } + break; + } + case ImsFeature.FEATURE_EMERGENCY_MMTEL : { + mSupportsEmergencyCalling = false; + Log.i(TAG, "Emergency calling disabled on slotId: " + slotId); + break; } } } @@ -352,8 +379,7 @@ public class MmTelFeatureConnection { } public boolean isEmergencyMmTelAvailable() { - TelephonyManager tm = getTelephonyManager(mContext); - return tm != null ? tm.isEmergencyMmTelAvailable(mSlotId) : false; + return mSupportsEmergencyCalling; } public IImsServiceFeatureCallback getListener() { @@ -565,7 +591,6 @@ public class MmTelFeatureConnection { public int getFeatureState() { synchronized (mLock) { if (isBinderAlive() && mFeatureStateCached != null) { - Log.i(TAG, "getFeatureState - returning cached: " + mFeatureStateCached); return mFeatureStateCached; } } -- cgit v1.2.3 From 57f6a85c80fe022e3844d5d203839023149ea471 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 8 Mar 2018 13:14:38 -0800 Subject: Do not Lock on Registration and Config Query ImsRegistration and ImsConfig interfaces do not need to be locked on because they access a TelephonyManager API independent of MmTelFeature state. Bug: 74119196 Test: Telephony Unit Tests Merged-In: I48a554c509b61094dd65b3d8ac6195a891508a64 Change-Id: I458db42cd815f87f57eab6b13878532105297180 --- src/java/com/android/ims/MmTelFeatureConnection.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index 276688c4..5679591b 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -484,22 +484,16 @@ public class MmTelFeatureConnection { } public IImsConfig getConfigInterface() throws RemoteException { - synchronized (mLock) { - checkServiceIsReady(); - return getConfig(); - } + return getConfig(); } public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech() - throws RemoteException { - synchronized (mLock) { - checkServiceIsReady(); - IImsRegistration registration = getRegistration(); - if (registration != null) { + throws RemoteException { + IImsRegistration registration = getRegistration(); + if (registration != null) { return registration.getRegistrationTechnology(); - } else { - return ImsRegistrationImplBase.REGISTRATION_TECH_NONE; - } + } else { + return ImsRegistrationImplBase.REGISTRATION_TECH_NONE; } } -- cgit v1.2.3 From 48632581b200abe7110593d413f7038bd146fce3 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Fri, 16 Mar 2018 11:46:30 -0700 Subject: Cache IImsRegistration and IImsConfig interfaces We currently query the IImsRegistration and IImsConfig interfaces instead of caching them in the MmTelFeatureConnection. This can lead to unnecessary pressure on cleanup of binder objects when accessing these interfaces through IPC. Test: Manual Bug: 72644425 Merged-In: Iebbb0a5e6e6b6715f46901ecdf07a034d8c37910 Change-Id: I4f07dd159ca2c1ed8cd50cd9603c4ed577171a74 --- .../com/android/ims/MmTelFeatureConnection.java | 52 +++++++++++++++++++--- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index 276688c4..6b140d93 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -68,7 +68,10 @@ public class MmTelFeatureConnection { // Updated by IImsServiceFeatureCallback when FEATURE_EMERGENCY_MMTEL is sent. private boolean mSupportsEmergencyCalling = false; - private MmTelFeature.Listener mMmTelFeatureListener; + // Cache the Registration and Config interfaces as long as the MmTel feature is connected. If + // it becomes disconnected, invalidate. + private IImsRegistration mRegistrationBinder; + private IImsConfig mConfigBinder; private abstract class CallbackAdapterManager { private static final String TAG = "CallbackAdapterManager"; @@ -333,6 +336,7 @@ public class MmTelFeatureConnection { if (mIsAvailable) { Log.i(TAG, "MmTel disabled on slotId: " + slotId); mIsAvailable = false; + mmTelFeatureRemoved(); if (mStatusCallback != null) { mStatusCallback.notifyUnavailable(); } @@ -368,14 +372,53 @@ public class MmTelFeatureConnection { mContext = context; } + // Called when the MmTelFeatureConnection has received an unavailable notification. + private void mmTelFeatureRemoved() { + synchronized (mLock) { + // invalidate caches. + mRegistrationBinder = null; + mConfigBinder = null; + } + } + private @Nullable IImsRegistration getRegistration() { + synchronized (mLock) { + // null if cache is invalid; + if (mRegistrationBinder != null) { + return mRegistrationBinder; + } + } TelephonyManager tm = getTelephonyManager(mContext); - return tm != null ? tm.getImsRegistration(mSlotId, ImsFeature.FEATURE_MMTEL) : null; + // We don't want to synchronize on a binder call to another process. + IImsRegistration regBinder = tm != null + ? tm.getImsRegistration(mSlotId, ImsFeature.FEATURE_MMTEL) : null; + synchronized (mLock) { + // mRegistrationBinder may have changed while we tried to get the registration + // interface. + if (mRegistrationBinder == null) { + mRegistrationBinder = regBinder; + } + } + return mRegistrationBinder; } private IImsConfig getConfig() { + synchronized (mLock) { + // null if cache is invalid; + if (mConfigBinder != null) { + return mConfigBinder; + } + } TelephonyManager tm = getTelephonyManager(mContext); - return tm != null ? tm.getImsConfig(mSlotId, ImsFeature.FEATURE_MMTEL) : null; + IImsConfig configBinder = tm != null + ? tm.getImsConfig(mSlotId, ImsFeature.FEATURE_MMTEL) : null; + synchronized (mLock) { + // mConfigBinder may have changed while we tried to get the config interface. + if (mConfigBinder == null) { + mConfigBinder = configBinder; + } + } + return mConfigBinder; } public boolean isEmergencyMmTelAvailable() { @@ -400,8 +443,7 @@ public class MmTelFeatureConnection { public void openConnection(MmTelFeature.Listener listener) throws RemoteException { synchronized (mLock) { checkServiceIsReady(); - mMmTelFeatureListener = listener; - getServiceInterface(mBinder).setListener(mMmTelFeatureListener); + getServiceInterface(mBinder).setListener(listener); } } -- cgit v1.2.3 From 2384f4290ee73ca55d58db0f6cd40bc409ccecd3 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 15 Mar 2018 16:09:41 -0700 Subject: Fix error in setVtSetting logic Fix error in setVtSetting logic that was created when ImsManager was refactored to move away from static members. Bug: 72676168 Test: Manual Merged-In: I1f859deeb1a33ed488d4d5f4d025e96ddf20a5e0 Change-Id: Ia99f2dcbada5387bf07a1e1b345f1da31e1f14d6 --- src/java/com/android/ims/ImsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 2a35fd37..2b348960 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -771,7 +771,7 @@ public class ImsManager { if (enabled) { log("setVtSetting(b) : turnOnIms"); turnOnIms(); - } else if (isVolteEnabledByPlatform() + } else if (isTurnOffImsAllowedByPlatform() && (!isVolteEnabledByPlatform() || !isEnhanced4gLteModeSettingEnabledByUser())) { log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms"); -- cgit v1.2.3 From b8cd44005f3529ffac188ca80f3b5b02e6432009 Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Fri, 23 Mar 2018 18:51:51 -0700 Subject: Apply renamed API in TelephonyManager Bug: 71584593 Test: unittest Change-Id: Iefe06d6d03f5b84cca559345e4196c13292189a8 --- src/java/com/android/ims/ImsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 2b348960..e7a857d1 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -2359,7 +2359,7 @@ public class ImsManager { } private boolean isDataEnabled() { - return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled(); + return new TelephonyManager(mContext, getSubId()).isDataCapable(); } private boolean isVolteProvisioned() { -- cgit v1.2.3 From 23916134059344b22fc52eaf9cec2f6cc3edee07 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Fri, 6 Apr 2018 09:37:50 -0700 Subject: Make sure the mBinder is not null before clearing listener Bug: 77693258 Test: Unit Tests/GTS Tests Change-Id: I85bae2f073960b81ba0afe791138d2765a7f4ed6 --- src/java/com/android/ims/MmTelFeatureConnection.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index de8f9282..b2472c8a 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -451,7 +451,11 @@ public class MmTelFeatureConnection { mRegistrationCallbackManager.close(); mCapabilityCallbackManager.close(); try { - getServiceInterface(mBinder).setListener(null); + synchronized (mLock) { + if (isBinderAlive()) { + getServiceInterface(mBinder).setListener(null); + } + } } catch (RemoteException e) { Log.w(TAG, "closeConnection: couldn't remove listener!"); } -- cgit v1.2.3 From b19b283163202f78946e9a2e7a322ad826a0fc81 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Wed, 11 Apr 2018 11:27:50 -0700 Subject: Update docs for setUiTtyMode and using Message across IPC Bug: 77870347 Test: Manual Change-Id: I9d3abff727e57dacab2e339a094545de9c46ed68 --- src/java/com/android/ims/ImsManager.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index e7a857d1..1502089c 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -1894,6 +1894,15 @@ public class ImsManager { /** * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call * settings screen. + * @param uiTtyMode TTY Mode, valid options are: + * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} + * @param onComplete A Message that will be called by the ImsService when it has completed this + * operation or null if not waiting for an async response. The Message must contain a + * valid {@link Message#replyTo} {@link android.os.Messenger}, since it will be passed + * through Binder to another process. */ public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete) throws ImsException { -- cgit v1.2.3 From eba31e19e041fff22c7fa70aaec8a0e5daadc374 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Tue, 17 Apr 2018 11:27:21 -0700 Subject: setWfcSetting: set WFC mode w.r.t. roaming state When turing on WFC, WFC mode in modem should also be updated to user set WFC mode: roaming mode if in roaming network or home mode otherwise. The code was using home mode always; so it causes user setting mismatch with modem setting in roaming, if home mode is different from roaming mode. Bug: 77882002 Test: manual - force device in roaming state, and turn on WFC; verify that modem uses roaming mode not home mode. Change-Id: I510aa469736de7a9262a87ec6399f5ca97cb3af1 --- src/java/com/android/ims/ImsManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index e7a857d1..8e547717 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -875,7 +875,9 @@ public class ImsManager { SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled)); - setWfcNonPersistent(enabled, getWfcMode()); + TelephonyManager tm = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + setWfcNonPersistent(enabled, getWfcMode(tm.isNetworkRoaming(getSubId()))); } /** -- cgit v1.2.3 From 1050b07afe6abc7353de7612c8e4e4d085ca7c46 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Tue, 17 Apr 2018 16:50:51 -0700 Subject: Fix deadlock during Testing Fixes an issue where rapid setup/teardown of ImsServices and callback registration was causing a deadlock in GTS testing. Bug: 77141737 Test: atest GtsImsServiceTests Change-Id: Ie63be1ff1793408039a1facfdb53b706f757543d --- .../com/android/ims/MmTelFeatureConnection.java | 64 ++++++++++++---------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index b2472c8a..07069219 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -44,8 +44,10 @@ import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.ims.internal.IImsUt; +import java.util.Collections; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * A container of the IImsServiceController binder, which implements all of the ImsFeatures that @@ -76,32 +78,33 @@ public class MmTelFeatureConnection { private abstract class CallbackAdapterManager { private static final String TAG = "CallbackAdapterManager"; - protected final Set mLocalCallbacks = new HashSet<>(); + protected final Set mLocalCallbacks = + Collections.newSetFromMap(new ConcurrentHashMap<>()); 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) { + if (!mHasConnected) { // throws a RemoteException if a connection can not be established. - if(createConnection()) { + if (createConnection()) { mHasConnected = true; } else { throw new RemoteException("Can not create connection!"); } } - Log.i(TAG, "Local callback added: " + localCallback); - mLocalCallbacks.add(localCallback); } + 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. + Log.i(TAG, "Local callback removed: " + localCallback); + mLocalCallbacks.remove(localCallback); synchronized (mLock) { - Log.i(TAG, "Local callback removed: " + localCallback); - mLocalCallbacks.remove(localCallback); - // If we have removed all local callbacks, remove callback to ImsService. + // If we have removed all local callbacks, remove callback to ImsService. if(mHasConnected) { if (mLocalCallbacks.isEmpty()) { removeConnection(); @@ -118,9 +121,9 @@ public class MmTelFeatureConnection { // Still mark the connection as disconnected, even if this fails. mHasConnected = false; } - Log.i(TAG, "Closing connection and clearing callbacks"); - mLocalCallbacks.clear(); } + Log.i(TAG, "Closing connection and clearing callbacks"); + mLocalCallbacks.clear(); } abstract boolean createConnection() throws RemoteException; @@ -140,27 +143,21 @@ public class MmTelFeatureConnection { public void onRegistered(int imsRadioTech) { Log.i(TAG, "onRegistered ::"); - synchronized (mLock) { - mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech)); - } + mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech)); } @Override public void onRegistering(int imsRadioTech) { Log.i(TAG, "onRegistering ::"); - synchronized (mLock) { - mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech)); - } + mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech)); } @Override public void onDeregistered(ImsReasonInfo imsReasonInfo) { Log.i(TAG, "onDeregistered ::"); - synchronized (mLock) { - mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo)); - } + mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo)); } @Override @@ -168,18 +165,15 @@ public class MmTelFeatureConnection { 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)); - } + + mLocalCallbacks.forEach(l -> l.onSubscriberAssociatedUriChanged(uris)); } } @@ -220,16 +214,18 @@ public class MmTelFeatureConnection { // 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)); - } + mLocalCallbacks.forEach( + callback -> callback.onCapabilitiesStatusChanged(config)); } } @Override boolean createConnection() throws RemoteException { - IImsMmTelFeature binder = getServiceInterface(mBinder); + IImsMmTelFeature binder; + synchronized (mLock) { + checkServiceIsReady(); + binder = getServiceInterface(mBinder); + } if (binder != null) { binder.addCapabilityCallback(mCallbackAdapter); return true; @@ -241,7 +237,15 @@ public class MmTelFeatureConnection { @Override void removeConnection() { - IImsMmTelFeature binder = getServiceInterface(mBinder); + IImsMmTelFeature binder = null; + synchronized (mLock) { + try { + checkServiceIsReady(); + binder = getServiceInterface(mBinder); + } catch (RemoteException e) { + // binder is null + } + } if (binder != null) { try { binder.removeCapabilityCallback(mCallbackAdapter); -- cgit v1.2.3 From 01720f232536a5f266918d9da1d1b8a500ee7113 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Tue, 24 Apr 2018 14:04:38 -0700 Subject: Fix typo in IMS compat translation code The IMS compat layer had a typo in it, causing code to receive an unexpected result for VoWiFi changes. Bug: 78310624 Test: Manual Change-Id: Ib991008fbc3cf6ba7729305bf7dae62c1bad62cc --- src/java/com/android/ims/ImsConnectionStateListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index d5fb633c..8ac473a5 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -102,7 +102,7 @@ public class ImsConnectionStateListener extends ImsRegistrationImplBase.Callback } if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO)) { enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI] = - ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI; + ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI; } if (c.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT)) { enabledCapabilities[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI] = -- cgit v1.2.3 From 6d1186c2fd8ed6d49f0adf1902792868a8d49af7 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 26 Apr 2018 14:23:45 -0700 Subject: Handle Dead Objects from Phone Crashes better 1) Check to make sure ImsService is available when calling changeMmTelCapability. 2) Remove caching of ImsConfig in ImsManager. It is already cached properly in MmTelFeatureConnection. 3) Create a DeathRecipient for MmTelFeature in MmTelFeatureConnection that cleans up all caches and notifies ImsManager that the connection is now unavailable. Bug: 77941698 Test: Manual Change-Id: I9c3721fe275a94f7f8841e8e84a2f9d8a3c4823b --- src/java/com/android/ims/ImsManager.java | 66 +++++++++------------- .../com/android/ims/MmTelFeatureConnection.java | 47 ++++++++++----- tests/Android.mk | 4 +- tests/src/com/android/ims/ImsConfigTest.java | 6 +- 4 files changed, 66 insertions(+), 57 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 957c8d67..67a85532 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -367,18 +367,16 @@ public class ImsManager { private int mPhoneId; private final boolean mConfigDynamicBind; private @Nullable MmTelFeatureConnection mMmTelFeatureConnection = null; - private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient(); - // Ut interface for the supplementary service configuration - private ImsUt mUt = null; - // Interface to get/set ims config items - private ImsConfig mConfig = null; private boolean mConfigUpdated = false; private ImsConfigListener mImsConfigListener; + //TODO: Move these caches into the MmTelFeature Connection and restrict their lifetimes to the + // lifetime of the MmTelFeature. + // Ut interface for the supplementary service configuration + private ImsUt mUt = null; // ECBM interface private ImsEcbm mEcbm = null; - private ImsMultiEndpoint mMultiEndpoint = null; private Set mStatusCallbacks = @@ -777,7 +775,7 @@ public class ImsManager { log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms"); turnOffIms(); } - } catch (ImsException | RemoteException e) { + } catch (ImsException e) { // The ImsService is down. Since the SubscriptionManager already recorded the user's // preference, it will be resent in updateImsServiceConfig when the ImsPhoneCallTracker // reconnects. @@ -905,7 +903,7 @@ public class ImsManager { } setWfcModeInternal(imsWfcModeFeatureValue); - } catch (ImsException | RemoteException e) { + } catch (ImsException e) { loge("setWfcSetting(): ", e); } } @@ -1321,7 +1319,7 @@ public class ImsManager { } mConfigUpdated = true; - } catch (ImsException | RemoteException e) { + } catch (ImsException e) { loge("updateImsServiceConfig: ", e); mConfigUpdated = false; } @@ -1333,7 +1331,7 @@ public class ImsManager { * @return whether feature is On * @throws ImsException */ - private boolean updateVolteFeatureValue() throws RemoteException { + private boolean updateVolteFeatureValue() throws ImsException { boolean available = isVolteEnabledByPlatform(); boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(); boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(); @@ -1354,7 +1352,7 @@ public class ImsManager { * @return whether feature is On * @throws ImsException */ - private boolean updateVideoCallFeatureValue() throws RemoteException { + private boolean updateVideoCallFeatureValue() throws ImsException { boolean available = isVtEnabledByPlatform(); boolean enabled = isVtEnabledByUser(); boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(); @@ -1381,7 +1379,7 @@ public class ImsManager { * @return whether feature is On * @throws ImsException */ - private boolean updateWfcFeatureAndProvisionedValues() throws RemoteException { + private boolean updateWfcFeatureAndProvisionedValues() throws ImsException { TelephonyManager tm = new TelephonyManager(mContext, getSubId()); boolean isNetworkRoaming = tm.isNetworkRoaming(); boolean available = isWfcEnabledByPlatform(); @@ -1673,7 +1671,6 @@ public class ImsManager { mMmTelFeatureConnection.closeConnection(); } mUt = null; - mConfig = null; mEcbm = null; mMultiEndpoint = null; } @@ -1822,41 +1819,44 @@ public class ImsManager { * @throws ImsException if getting the setting interface results in an error. */ public ImsConfig getConfigInterface() throws ImsException { - if (mConfig != null && mConfig.isBinderAlive()) { - return mConfig; - } - checkAndThrowExceptionIfServiceUnavailable(); + try { IImsConfig config = mMmTelFeatureConnection.getConfigInterface(); if (config == null) { throw new ImsException("getConfigInterface()", ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); } - mConfig = new ImsConfig(config, mContext); + return new ImsConfig(config); } catch (RemoteException e) { throw new ImsException("getConfigInterface()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } - return mConfig; } public void changeMmTelCapability( @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech, - boolean isEnabled) throws RemoteException { + boolean isEnabled) throws ImsException { + checkAndThrowExceptionIfServiceUnavailable(); + 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); + try { + mMmTelFeatureConnection.changeEnabledCapabilities(request, null); + if (mImsConfigListener != null) { + mImsConfigListener.onSetFeatureResponse(capability, + mMmTelFeatureConnection.getRegistrationTech(), + isEnabled ? ImsConfig.FeatureValueConstants.ON + : ImsConfig.FeatureValueConstants.OFF, -1); + } + } catch (RemoteException e) { + throw new ImsException("changeMmTelCapability()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } } @@ -2170,20 +2170,6 @@ public class ImsManager { mRecentDisconnectReasons.addLast(reason); } - /** - * Death recipient class for monitoring IMS service. - */ - private class ImsServiceDeathRecipient implements IBinder.DeathRecipient { - @Override - public void binderDied() { - mMmTelFeatureConnection = null; - mUt = null; - mConfig = null; - mEcbm = null; - mMultiEndpoint = null; - } - } - /** * Gets the ECBM interface to request ECBM exit. * diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java index 07069219..d6954f3f 100644 --- a/src/java/com/android/ims/MmTelFeatureConnection.java +++ b/src/java/com/android/ims/MmTelFeatureConnection.java @@ -75,6 +75,11 @@ public class MmTelFeatureConnection { private IImsRegistration mRegistrationBinder; private IImsConfig mConfigBinder; + private IBinder.DeathRecipient mDeathRecipient = () -> { + Log.w(TAG, "DeathRecipient triggered, binder died."); + onRemovedOrDied(); + }; + private abstract class CallbackAdapterManager { private static final String TAG = "CallbackAdapterManager"; @@ -337,14 +342,8 @@ public class MmTelFeatureConnection { } switch (feature) { case ImsFeature.FEATURE_MMTEL: { - if (mIsAvailable) { - Log.i(TAG, "MmTel disabled on slotId: " + slotId); - mIsAvailable = false; - mmTelFeatureRemoved(); - if (mStatusCallback != null) { - mStatusCallback.notifyUnavailable(); - } - } + Log.i(TAG, "MmTel removed on slotId: " + slotId); + onRemovedOrDied(); break; } case ImsFeature.FEATURE_EMERGENCY_MMTEL : { @@ -376,12 +375,23 @@ public class MmTelFeatureConnection { mContext = context; } - // Called when the MmTelFeatureConnection has received an unavailable notification. - private void mmTelFeatureRemoved() { + /** + * Called when the MmTelFeature has either been removed by Telephony or crashed. + */ + private void onRemovedOrDied() { synchronized (mLock) { - // invalidate caches. - mRegistrationBinder = null; - mConfigBinder = null; + if (mIsAvailable) { + mIsAvailable = false; + // invalidate caches. + mRegistrationBinder = null; + mConfigBinder = null; + if (mBinder != null) { + mBinder.unlinkToDeath(mDeathRecipient, 0); + } + if (mStatusCallback != null) { + mStatusCallback.notifyUnavailable(); + } + } } } @@ -434,7 +444,16 @@ public class MmTelFeatureConnection { } public void setBinder(IBinder binder) { - mBinder = binder; + synchronized (mLock) { + mBinder = binder; + try { + if (mBinder != null) { + mBinder.linkToDeath(mDeathRecipient, 0); + } + } catch (RemoteException e) { + // No need to do anything if the binder is already dead. + } + } } /** diff --git a/tests/Android.mk b/tests/Android.mk index e07cab5c..a0b998b8 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -25,7 +25,9 @@ LOCAL_CERTIFICATE := platform LOCAL_MODULE_TAGS := tests -LOCAL_JAVA_LIBRARIES := ims-common android.test.runner +LOCAL_JAVA_LIBRARIES := ims-common \ + android.test.runner \ + android.test.base LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ diff --git a/tests/src/com/android/ims/ImsConfigTest.java b/tests/src/com/android/ims/ImsConfigTest.java index 4cf7a926..31d9bcb0 100644 --- a/tests/src/com/android/ims/ImsConfigTest.java +++ b/tests/src/com/android/ims/ImsConfigTest.java @@ -18,6 +18,7 @@ package com.android.ims; import android.support.test.runner.AndroidJUnit4; import android.telephony.ims.aidl.IImsConfig; +import android.test.suitebuilder.annotation.SmallTest; import org.junit.After; import org.junit.Before; @@ -42,7 +43,7 @@ public class ImsConfigTest extends ImsTestBase { @Override public void setUp() throws Exception { super.setUp(); - mTestImsConfig = new ImsConfig(mMockImsConfigInterface, mContext); + mTestImsConfig = new ImsConfig(mMockImsConfigInterface); } @After @@ -53,10 +54,11 @@ public class ImsConfigTest extends ImsTestBase { } @Test + @SmallTest public void testImsConfigGetProvisionedValue() throws Exception { int testItem = 0; - mTestImsConfig.getProvisionedValue(testItem); + mTestImsConfig.getConfigInt(testItem); verify(mMockImsConfigInterface).getConfigInt(eq(testItem)); } -- cgit v1.2.3 From 74974e523316f3b32f5979bb878c9370845b480f Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Tue, 1 May 2018 16:16:47 -0700 Subject: Do not set WFC mode separately when not editable WFC mode was being set separately when setting is not editable. Moved this behavior to getWfcMode so that only one query is made. Bug: 77831154 Test: Manual Change-Id: I4d2cb555522246959654b8c04bec9c9b73bdc947 --- src/java/com/android/ims/ImsManager.java | 80 +++++++++++++------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 957c8d67..8ae97c81 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -959,17 +959,6 @@ public class ImsManager { setWfcModeInternal(wfcMode); } - /** - * Changes the WFC mode to its default value for Carriers with non-editable WFC settings. - */ - private void updateDefaultWfcMode() { - if (DBG) log("updateDefaultWfcMode"); - if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { - setWfcMode(getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); - } - } - /** * Returns the user configuration of WFC preference setting * @@ -994,34 +983,52 @@ public class ImsManager { * @param roaming {@code false} for home network setting, {@code true} for roaming setting */ public int getWfcMode(boolean roaming) { - int setting = 0; + int setting; if (!roaming) { - setting = SubscriptionManager.getIntegerSubscriptionProperty( - getSubId(), SubscriptionManager.WFC_IMS_MODE, - SUB_PROPERTY_NOT_INITIALIZED, mContext); - - // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. - if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + // The WFC mode is not editable, return the default setting in the CarrierConfig, not + // the user set value. + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { setting = getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT); + + } else { + setting = getSettingFromSubscriptionManager(SubscriptionManager.WFC_IMS_MODE, + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT); } if (DBG) log("getWfcMode - setting=" + setting); } else { - setting = SubscriptionManager.getIntegerSubscriptionProperty( - getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE, - SUB_PROPERTY_NOT_INITIALIZED, mContext); - - // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. - if (setting == SUB_PROPERTY_NOT_INITIALIZED) { + // The WFC roaming mode is not editable, return the default setting in the + // CarrierConfig, not the user set value. + if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { setting = getIntCarrierConfig( CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); - } + } else { + setting = getSettingFromSubscriptionManager( + SubscriptionManager.WFC_IMS_ROAMING_MODE, + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); + } if (DBG) log("getWfcMode (roaming) - setting=" + setting); } return setting; } + /** + * Returns the SubscriptionManager setting for the subSetting string. If it is not set, default + * to the default CarrierConfig value for defaultConfigKey. + */ + private int getSettingFromSubscriptionManager(String subSetting, String defaultConfigKey) { + int result; + result = SubscriptionManager.getIntegerSubscriptionProperty(getSubId(), subSetting, + SUB_PROPERTY_NOT_INITIALIZED, mContext); + + // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db. + if (result == SUB_PROPERTY_NOT_INITIALIZED) { + result = getIntCarrierConfig(defaultConfigKey); + } + return result; + } + /** * Change persistent WFC preference setting * @@ -1071,26 +1078,6 @@ public class ImsManager { return subId; } - private static void setWfcModeInternal(Context context, int wfcMode) { - final ImsManager imsManager = ImsManager.getInstance(context, - SubscriptionManager.getDefaultVoicePhoneId()); - if (imsManager != null) { - final int value = wfcMode; - Thread thread = new Thread(new Runnable() { - public void run() { - try { - imsManager.getConfigInterface().setConfig( - ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, - value); - } catch (ImsException e) { - // do nothing - } - } - }); - thread.start(); - } - } - private void setWfcModeInternal(int wfcMode) { final int value = wfcMode; Thread thread = new Thread(() -> { @@ -1386,7 +1373,6 @@ public class ImsManager { boolean isNetworkRoaming = tm.isNetworkRoaming(); boolean available = isWfcEnabledByPlatform(); boolean enabled = isWfcEnabledByUser(); - updateDefaultWfcMode(); int mode = getWfcMode(isNetworkRoaming); boolean roaming = isWfcRoamingEnabledByUser(); boolean isFeatureOn = available && enabled; @@ -1403,7 +1389,7 @@ public class ImsManager { mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED; roaming = false; } - setWfcModeInternal(mContext, mode); + setWfcModeInternal(mode); setWfcRoamingSettingInternal(roaming); return isFeatureOn; -- cgit v1.2.3 From df97867f425c58af459da176b0220354a3ee38a0 Mon Sep 17 00:00:00 2001 From: Brad Ebinger Date: Thu, 24 May 2018 09:48:47 -0700 Subject: Fix editable roaming mode query bug We were querying whether or not the WFC mode was editable, instead of the WFC roaming mode. This was causing the issue where the user was unable to set WiFi preferred mode when the WFC mode was not editable. Bug: 80168790 Test: Manual Change-Id: I8895ee97e7917192305e8ad53fd4de9ce1bfca01 --- src/java/com/android/ims/ImsManager.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 7b22bebd..590ab5ac 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -995,17 +995,13 @@ public class ImsManager { } if (DBG) log("getWfcMode - setting=" + setting); } else { - // The WFC roaming mode is not editable, return the default setting in the - // CarrierConfig, not the user set value. - if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { - setting = getIntCarrierConfig( - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); - - } else { - setting = getSettingFromSubscriptionManager( - SubscriptionManager.WFC_IMS_ROAMING_MODE, - CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); - } + // The WFC roaming mode is set in the Settings UI to be the same as the WFC mode if the + // roaming mode is set to not "editable" (see + // CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL for explanation), so can't + // override those settings here by setting the WFC roaming mode to default, like above. + setting = getSettingFromSubscriptionManager( + SubscriptionManager.WFC_IMS_ROAMING_MODE, + CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT); if (DBG) log("getWfcMode (roaming) - setting=" + setting); } return setting; -- cgit v1.2.3