diff options
author | Brad Ebinger <breadley@google.com> | 2019-12-19 15:14:40 -0800 |
---|---|---|
committer | Brad Ebinger <breadley@google.com> | 2020-01-08 15:47:02 -0800 |
commit | c7771d8ad1479b3ca8b3ca2f5a085df0f5230359 (patch) | |
tree | 8e35a75f483088e12555195574a8812f7e761c0b /rcs/rcsservice/src | |
parent | 674766afb2abbe00a26a3265cbcb5d9d3a298263 (diff) | |
download | ims-c7771d8ad1479b3ca8b3ca2f5a085df0f5230359.tar.gz |
Remove dependencies on library (2/2)
Moves all RcsService dependencies into app code and only
leaves impl agnostic code in lib.
One dependency left: RcsStackAdaptor should not be modifying
tasks for resquestPublication, that should be done inside
of PresencePublication because we need to move this code
to Telephony.
Test: Manual testing contact add/rm and verify vt status
Change-Id: I4bef16c1e2aba257054b8d1208e82c5385bd4713
Diffstat (limited to 'rcs/rcsservice/src')
20 files changed, 1132 insertions, 730 deletions
diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/AlarmBroadcastReceiver.java b/rcs/rcsservice/src/com/android/service/ims/AlarmBroadcastReceiver.java index f191186..e06b4a4 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/AlarmBroadcastReceiver.java +++ b/rcs/rcsservice/src/com/android/service/ims/AlarmBroadcastReceiver.java @@ -26,25 +26,19 @@ * DAMAGE. */ -package com.android.service.ims.presence; +package com.android.service.ims; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import com.android.ims.internal.Logger; -import com.android.service.ims.RcsStackAdaptor; -import com.android.service.ims.TaskManager; +import com.android.service.ims.presence.PresenceCapabilityTask; +import com.android.service.ims.presence.PresencePublication; public class AlarmBroadcastReceiver extends BroadcastReceiver{ private Logger logger = Logger.getLogger(this.getClass().getName()); - public static final String ACTION_RETRY_ALARM = "com.android.service.ims.presence.retry"; - private static final String ACTION_TASK_TIMEOUT_ALARM = - PresenceCapabilityTask.ACTION_TASK_TIMEOUT_ALARM; - private static final String ACTION_RETRY_PUBLISH_ALARM = - PresencePublication.ACTION_RETRY_PUBLISH_ALARM; - @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -58,15 +52,13 @@ public class AlarmBroadcastReceiver extends BroadcastReceiver{ return; } - if(ACTION_RETRY_ALARM.equals(action)) { + if(RcsStackAdaptor.ACTION_RETRY_ALARM.equals(action)) { int times = intent.getIntExtra("times", -1); rcsStackAdaptor.startInitThread(times); - }else if(ACTION_TASK_TIMEOUT_ALARM.equals(action)){ + }else if(PresenceCapabilityTask.ACTION_TASK_TIMEOUT_ALARM.equals(action)){ int taskId = intent.getIntExtra("taskId", -1); TaskManager.getDefault().onTimeout(taskId); - } else if(ACTION_RETRY_PUBLISH_ALARM.equals(action)) { - // default retry is for 888 - int sipCode = intent.getIntExtra("sipCode", 888); + } else if(PresencePublication.ACTION_RETRY_PUBLISH_ALARM.equals(action)) { PresencePublication publication = PresencePublication.getPresencePublication(); if(publication != null) { publication.retryPublish(); diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceInfoParser.java b/rcs/rcsservice/src/com/android/service/ims/PresenceInfoParser.java index 1b3d795..5edb9a1 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceInfoParser.java +++ b/rcs/rcsservice/src/com/android/service/ims/PresenceInfoParser.java @@ -26,7 +26,10 @@ * DAMAGE. */ -package com.android.service.ims.presence; +package com.android.service.ims; + +import android.net.Uri; +import android.telephony.ims.RcsContactUceCapability; import java.lang.String; import java.util.ArrayList; @@ -39,6 +42,7 @@ import com.android.ims.internal.uce.presence.PresResInstanceInfo; import com.android.ims.RcsPresenceInfo; import com.android.ims.RcsPresenceInfo.ServiceType; import com.android.ims.RcsPresenceInfo.ServiceState; +import com.android.service.ims.presence.PresenceUtils; public class PresenceInfoParser{ /* @@ -166,8 +170,8 @@ public class PresenceInfoParser{ (ServiceState.ONLINE == presenceInfoTmp.getServiceState( ServiceType.VT_CALL)))?ServiceState.ONLINE: presenceInfoTmp.getServiceState(ServiceType.VT_CALL), - presenceInfoTmp.getServiceContact(ServiceType.VOLTE_CALL), - presenceInfoTmp.getTimeStamp(ServiceType.VOLTE_CALL))); + presenceInfoTmp.getServiceContact(ServiceType.VT_CALL), + presenceInfoTmp.getTimeStamp(ServiceType.VT_CALL))); return; } } @@ -268,4 +272,39 @@ public class PresenceInfoParser{ return number; } + + public static RcsContactUceCapability getUceCapability(RcsPresenceInfo info) { + RcsContactUceCapability.Builder result = new RcsContactUceCapability.Builder( + PresenceUtils.convertContactNumber(info.getContactNumber())); + if (ServiceState.ONLINE == info.getServiceState(ServiceType.VOLTE_CALL)) { + result.add(RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL, + PresenceUtils.convertContactNumber( + info.getServiceContact(ServiceType.VOLTE_CALL))); + } + if (ServiceState.ONLINE == info.getServiceState(ServiceType.VT_CALL)) { + result.add(RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL, + PresenceUtils.convertContactNumber( + info.getServiceContact(ServiceType.VT_CALL))); + } + return result.build(); + } + + public static RcsPresenceInfo getRcsPresenceInfo(RcsContactUceCapability capability) { + int volteCapable = capability.isCapable(RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL) ? + ServiceState.ONLINE : ServiceState.OFFLINE; + int vtCapable = capability.isCapable(RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL) ? + ServiceState.ONLINE : ServiceState.OFFLINE; + return new RcsPresenceInfo(capability.getContactUri().getSchemeSpecificPart(), + // Not sure what the difference is, just track voice capable. + (volteCapable == ServiceState.ONLINE) ? RcsPresenceInfo.VolteStatus.VOLTE_ENABLED : + RcsPresenceInfo.VolteStatus.VOLTE_DISABLED, volteCapable, + PresenceUtils.getNumber(capability.getServiceUri( + RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL)), + // We always use system current time instead of time from server + System.currentTimeMillis(), vtCapable, + PresenceUtils.getNumber(capability.getServiceUri( + RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL)), + // We always use system current time instead of time from server + System.currentTimeMillis()); + } } diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsService.java b/rcs/rcsservice/src/com/android/service/ims/RcsService.java index 78708da..f80e2e5 100644 --- a/rcs/rcsservice/src/com/android/service/ims/RcsService.java +++ b/rcs/rcsservice/src/com/android/service/ims/RcsService.java @@ -29,6 +29,7 @@ package com.android.service.ims; import android.app.Service; +import android.content.ComponentName; import android.content.Intent; import android.database.ContentObserver; import android.net.ConnectivityManager; @@ -44,20 +45,26 @@ import android.telephony.SubscriptionManager; import android.telephony.ims.ImsException; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.RegistrationManager; import android.telephony.ims.feature.MmTelFeature; import com.android.ims.IRcsPresenceListener; -import com.android.ims.RcsManager.ResultCode; +import com.android.ims.RcsPresenceInfo; +import com.android.ims.ResultCode; +import com.android.ims.RcsPresence; import com.android.ims.internal.IRcsPresence; import com.android.ims.internal.IRcsService; import com.android.ims.internal.Logger; -import com.android.internal.telephony.IccCardConstants; import com.android.service.ims.R; +import com.android.service.ims.presence.ContactCapabilityResponse; +import com.android.service.ims.presence.PresenceBase; import com.android.service.ims.presence.PresencePublication; import com.android.service.ims.presence.PresenceSubscriber; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class RcsService extends Service { @@ -83,6 +90,78 @@ public class RcsService extends Service { } }; + private class CapabilityResultListener implements ContactCapabilityResponse { + + private final IRcsPresenceListener mListener; + + public CapabilityResultListener(IRcsPresenceListener listener) { + mListener = listener; + } + + @Override + public void onSuccess(int reqId) { + try { + mListener.onSuccess(reqId); + } catch (RemoteException e) { + logger.warn("CapabilityResultListener: onSuccess exception = " + e.getMessage()); + } + } + + @Override + public void onError(int reqId, int resultCode) { + try { + mListener.onError(reqId, resultCode); + } catch (RemoteException e) { + logger.warn("CapabilityResultListener: onError exception = " + e.getMessage()); + } + } + + @Override + public void onFinish(int reqId) { + try { + mListener.onFinish(reqId); + } catch (RemoteException e) { + logger.warn("CapabilityResultListener: onFinish exception = " + e.getMessage()); + } + } + + @Override + public void onTimeout(int reqId) { + try { + mListener.onTimeout(reqId); + } catch (RemoteException e) { + logger.warn("CapabilityResultListener: onTimeout exception = " + e.getMessage()); + } + } + + @Override + public void onCapabilitiesUpdated(List<RcsContactUceCapability> contactCapabilities, + boolean updateLastTimestamp) { + ArrayList<RcsPresenceInfo> presenceInfoList = contactCapabilities.stream().map( + PresenceInfoParser::getRcsPresenceInfo).collect( + Collectors.toCollection(ArrayList::new)); + + logger.debug("capabilities updated:"); + for (RcsPresenceInfo info : presenceInfoList) { + logger.debug("capabilities updated: info -" + info); + } + // For some reason it uses an intent to send this info back instead of just using the + // active binder... + Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED); + intent.putParcelableArrayListExtra(RcsPresence.EXTRA_PRESENCE_INFO_LIST, + presenceInfoList); + intent.putExtra("updateLastTimestamp", updateLastTimestamp); + launchPersistService(intent); + } + } + + private void launchPersistService(Intent intent) { + ComponentName component = new ComponentName("com.android.service.ims.presence", + "com.android.service.ims.presence.PersistService"); + intent.setComponent(component); + startService(intent); + } + @Override public void onCreate() { super.onCreate(); @@ -266,7 +345,8 @@ public class RcsService extends Service { return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; } - return mSubscriber.requestCapability(contactsNumber, listener); + return mSubscriber.requestCapability(contactsNumber, + new CapabilityResultListener(listener)); } /** @@ -287,7 +367,8 @@ public class RcsService extends Service { } // check availability cache (in RAM). - return mSubscriber.requestAvailability(contactNumber, listener, false); + return mSubscriber.requestAvailability(contactNumber, + new CapabilityResultListener(listener), false); } /** @@ -309,11 +390,12 @@ public class RcsService extends Service { } // check availability cache (in RAM). - return mSubscriber.requestAvailability(contactNumber, listener, true); + return mSubscriber.requestAvailability(contactNumber, + new CapabilityResultListener(listener), true); } public int getPublishState() throws RemoteException { - return mPublication.getPublishState(); + return publisherPublishStateToPublishState(mPublication.getPublishState()); } }; @@ -448,5 +530,24 @@ public class RcsService extends Service { mPublication.onFeatureCapabilityChanged(mNetworkRegistrationType, capabilities); } }; + + private static int publisherPublishStateToPublishState(int publisherPublishState) { + switch(publisherPublishState) { + case PresenceBase.PUBLISH_STATE_200_OK: + return RcsPresence.PublishState.PUBLISH_STATE_200_OK; + case PresenceBase.PUBLISH_STATE_NOT_PUBLISHED: + return RcsPresence.PublishState.PUBLISH_STATE_NOT_PUBLISHED; + case PresenceBase.PUBLISH_STATE_VOLTE_PROVISION_ERROR: + return RcsPresence.PublishState.PUBLISH_STATE_VOLTE_PROVISION_ERROR; + case PresenceBase.PUBLISH_STATE_RCS_PROVISION_ERROR: + return RcsPresence.PublishState.PUBLISH_STATE_RCS_PROVISION_ERROR; + case PresenceBase.PUBLISH_STATE_REQUEST_TIMEOUT: + return RcsPresence.PublishState.PUBLISH_STATE_REQUEST_TIMEOUT; + case PresenceBase.PUBLISH_STATE_OTHER_ERROR: + return RcsPresence.PublishState.PUBLISH_STATE_OTHER_ERROR; + + } + return PresenceBase.PUBLISH_STATE_OTHER_ERROR; + } } diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsSettingUtils.java b/rcs/rcsservice/src/com/android/service/ims/RcsSettingUtils.java index 40fb709..f5f893e 100644 --- a/rcs/rcsservice/src/com/android/service/ims/RcsSettingUtils.java +++ b/rcs/rcsservice/src/com/android/service/ims/RcsSettingUtils.java @@ -31,82 +31,131 @@ package com.android.service.ims; import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.ims.ProvisioningManager; +import android.telephony.ims.feature.MmTelFeature; +import android.telephony.ims.stub.ImsRegistrationImplBase; -import com.android.ims.ImsConfig; -import com.android.ims.ImsException; -import com.android.ims.ImsManager; import com.android.ims.internal.Logger; -public class RcsSettingUtils{ - /* - * The logger - */ +import java.util.List; + +public class RcsSettingUtils { static private Logger logger = Logger.getLogger("RcsSettingUtils"); - public RcsSettingUtils() { + // Values taken from ImsConfig - Should define in @SystemApi as well. + /** + * SIP T1 timer value in milliseconds. See RFC 3261 for definition. + * Value is in Integer format. + */ + private static final int SIP_T1_TIMER = 7; + /** + * Whether or not capability discovery is provisioned. + */ + private static final int CAPABILITY_DISCOVERY_ENABLED = 17; + /** + * period of time the availability information of a contact is cached on device. + * Value is in Integer format. + */ + private static final int AVAILABILITY_CACHE_EXPIRATION = 19; + /** + * Minimum time between two published messages from the device. + * Value is in Integer format. + */ + private static final int SOURCE_THROTTLE_PUBLISH = 21; + /** + * The Maximum number of MDNs contained in one Request Contained List. + * Value is in Integer format. + */ + private static final int MAX_NUMENTRIES_IN_RCL = 22; + /** + * Expiration timer for subscription of a Request Contained List, used in capability + * polling. + * Value is in Integer format. + */ + private static final int CAPAB_POLL_LIST_SUB_EXP = 23; + /** + * Provisioning status for Enhanced Address Book (EAB) + * Value is in Integer format. + */ + private static final int EAB_SETTING_ENABLED = 25; + /** + * Whether or not mobile data is enabled currently. + */ + private static final int MOBILE_DATA_ENABLED = 29; + + public static boolean isVowifiProvisioned(Context context) { + try { + boolean isProvisioned; + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + isProvisioned = manager.getProvisioningStatusForCapability( + MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, + ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN); + logger.debug("isVowifiProvisioned=" + isProvisioned); + return isProvisioned; + } catch (Exception e) { + logger.debug("isVowifiProvisioned, exception = " + e.getMessage()); + return false; + } } - public static boolean isFeatureProvisioned(Context context, - int featureId, boolean defaultValue) { + public static boolean isLvcProvisioned(Context context) { + try { + boolean isProvisioned; + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + isProvisioned = manager.getProvisioningStatusForCapability( + MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, + ImsRegistrationImplBase.REGISTRATION_TECH_LTE); + logger.debug("isLvcProvisioned=" + isProvisioned); + return isProvisioned; + } catch (Exception e) { + logger.debug("isLvcProvisioned, exception = " + e.getMessage()); + return false; + } + } + + public static boolean isEabProvisioned(Context context) { + boolean isProvisioned = false; + int subId = getDefaultSubscriptionId(context); + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + logger.debug("isEabProvisioned: no valid subscriptions!"); + return false; + } CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); - // Don't need provision. if (configManager != null) { - PersistableBundle config = configManager.getConfig(); + PersistableBundle config = configManager.getConfigForSubId(subId); if (config != null && !config.getBoolean( CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONED_BOOL)) { + // If we don't need provisioning, just return true. return true; } } - - boolean provisioned = defaultValue; - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - provisioned = imsConfig.getProvisionedValue(featureId) - == ImsConfig.FeatureValueConstants.ON; - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); + isProvisioned = manager.getProvisioningIntValue(EAB_SETTING_ENABLED) + == ProvisioningManager.PROVISIONING_VALUE_ENABLED; + } catch (Exception e) { + logger.debug("isEabProvisioned: exception=" + e.getMessage()); } - - logger.debug("featureId=" + featureId + " provisioned=" + provisioned); - return provisioned; - } - - public static boolean isVowifiProvisioned(Context context) { - return isFeatureProvisioned(context, - ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED, false); - } - - public static boolean isLvcProvisioned(Context context) { - return isFeatureProvisioned(context, - ImsConfig.ConfigConstants.LVC_SETTING_ENABLED, false); - } - - public static boolean isEabProvisioned(Context context) { - return isFeatureProvisioned(context, - ImsConfig.ConfigConstants.EAB_SETTING_ENABLED, false); + logger.debug("isEabProvisioned=" + isProvisioned); + return isProvisioned; } public static int getSIPT1Timer(Context context) { int sipT1Timer = 0; - - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - sipT1Timer = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.SIP_T1_TIMER); - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + sipT1Timer = manager.getProvisioningIntValue(SIP_T1_TIMER); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("getSIPT1Timer: exception=" + e.getMessage()); } - - logger.debug("sipT1Timer=" + sipT1Timer); + logger.debug("getSIPT1Timer=" + sipT1Timer); return sipT1Timer; } @@ -115,20 +164,15 @@ public class RcsSettingUtils{ */ public static boolean getCapabilityDiscoveryEnabled(Context context) { boolean capabilityDiscoveryEnabled = false; - - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - capabilityDiscoveryEnabled = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.CAPABILITY_DISCOVERY_ENABLED) - == ImsConfig.FeatureValueConstants.ON; - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + capabilityDiscoveryEnabled = manager.getProvisioningIntValue(CAPABILITY_DISCOVERY_ENABLED) + == ProvisioningManager.PROVISIONING_VALUE_ENABLED; + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("capabilityDiscoveryEnabled: exception=" + e.getMessage()); } - logger.debug("capabilityDiscoveryEnabled=" + capabilityDiscoveryEnabled); return capabilityDiscoveryEnabled; } @@ -138,20 +182,15 @@ public class RcsSettingUtils{ */ public static int getMaxNumbersInRCL(Context context) { int maxNumbersInRCL = 100; - - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - maxNumbersInRCL = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.MAX_NUMENTRIES_IN_RCL); - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + maxNumbersInRCL = manager.getProvisioningIntValue(MAX_NUMENTRIES_IN_RCL); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("getMaxNumbersInRCL: exception=" + e.getMessage()); } - - logger.debug("maxNumbersInRCL=" + maxNumbersInRCL); + logger.debug("getMaxNumbersInRCL=" + maxNumbersInRCL); return maxNumbersInRCL; } @@ -160,98 +199,100 @@ public class RcsSettingUtils{ */ public static int getCapabPollListSubExp(Context context) { int capabPollListSubExp = 30; - - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - capabPollListSubExp = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.CAPAB_POLL_LIST_SUB_EXP); - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + capabPollListSubExp = manager.getProvisioningIntValue(CAPAB_POLL_LIST_SUB_EXP); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("getCapabPollListSubExp: exception=" + e.getMessage()); } - - logger.debug("capabPollListSubExp=" + capabPollListSubExp); + logger.debug("getCapabPollListSubExp=" + capabPollListSubExp); return capabPollListSubExp; } /** - * Peiod of time the availability information of a contact is cached on device. + * Period of time the availability information of a contact is cached on device. */ public static int getAvailabilityCacheExpiration(Context context) { int availabilityCacheExpiration = 30; - - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - availabilityCacheExpiration = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.AVAILABILITY_CACHE_EXPIRATION); - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + availabilityCacheExpiration = manager.getProvisioningIntValue( + AVAILABILITY_CACHE_EXPIRATION); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("getAvailabilityCacheExpiration: exception=" + e.getMessage()); } - - logger.debug("availabilityCacheExpiration=" + availabilityCacheExpiration); + logger.debug("getAvailabilityCacheExpiration=" + availabilityCacheExpiration); return availabilityCacheExpiration; } public static boolean isMobileDataEnabled(Context context) { boolean mobileDataEnabled = false; - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - mobileDataEnabled = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.MOBILE_DATA_ENABLED) - == ImsConfig.FeatureValueConstants.ON; - } - } catch (ImsException ex) { - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + mobileDataEnabled = manager.getProvisioningIntValue(MOBILE_DATA_ENABLED) + == ProvisioningManager.PROVISIONING_VALUE_ENABLED; + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("isMobileDataEnabled: exception=" + e.getMessage()); } - logger.debug("mobileDataEnabled=" + mobileDataEnabled); return mobileDataEnabled; } public static void setMobileDataEnabled(Context context, boolean mobileDataEnabled) { logger.debug("mobileDataEnabled=" + mobileDataEnabled); - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - imsConfig.setProvisionedValue( - ImsConfig.ConfigConstants.MOBILE_DATA_ENABLED, mobileDataEnabled? - ImsConfig.FeatureValueConstants.ON:ImsConfig.FeatureValueConstants.OFF); - } - } catch (ImsException ex) { - logger.debug("ImsException", ex); - } + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + manager.setProvisioningIntValue(MOBILE_DATA_ENABLED, mobileDataEnabled ? + ProvisioningManager.PROVISIONING_VALUE_ENABLED : + ProvisioningManager.PROVISIONING_VALUE_DISABLED); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("mobileDataEnabled: exception=" + e.getMessage()); } } public static int getPublishThrottle(Context context) { + // Default int publishThrottle = 60000; + try { + ProvisioningManager manager = ProvisioningManager.createForSubscriptionId( + getDefaultSubscriptionId(context)); + publishThrottle = manager.getProvisioningIntValue(SOURCE_THROTTLE_PUBLISH); + } catch (Exception e) { + // If there is no active subscriptions, this will throw an exception. + logger.debug("publishThrottle: exception=" + e.getMessage()); + } + logger.debug("publishThrottle=" + publishThrottle); + return publishThrottle; + } - ImsManager imsManager = ImsManager.getInstance(context, 0); - if (imsManager != null) { - try { - ImsConfig imsConfig = imsManager.getConfigInterface(); - if (imsConfig != null) { - publishThrottle = imsConfig.getProvisionedValue( - ImsConfig.ConfigConstants.SOURCE_THROTTLE_PUBLISH); + private static int getDefaultSubscriptionId(Context context) { + SubscriptionManager sm = context.getSystemService(SubscriptionManager.class); + List<SubscriptionInfo> infos = sm.getActiveSubscriptionInfoList(); + if (infos == null || infos.isEmpty()) { + // There are no active subscriptions right now. + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + // This code does not support MSIM unfortunately, so only provide presence on the default + // subscription that the user chose. + int defaultSub = SubscriptionManager.getDefaultSubscriptionId(); + // If the user has no default set, just pick the first as backup. + if (defaultSub == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + for (SubscriptionInfo info : infos) { + if (!info.isOpportunistic()) { + defaultSub = info.getSubscriptionId(); + break; } - } catch (ImsException ex) { } } - - logger.debug("publishThrottle=" + publishThrottle); - return publishThrottle; + return defaultSub; } } diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java b/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java index eb2edd7..4f1df37 100644 --- a/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java +++ b/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java @@ -44,12 +44,11 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.ims.RcsContactUceCapability; +import android.text.TextUtils; -import com.android.ims.IRcsPresenceListener; -import com.android.ims.RcsManager.ResultCode; +import com.android.ims.ResultCode; import com.android.ims.RcsPresence; -import com.android.ims.RcsPresence.PublishState; -import com.android.ims.RcsPresenceInfo; import com.android.ims.internal.ContactNumberUtils; import com.android.ims.internal.Logger; import com.android.ims.internal.uce.common.CapInfo; @@ -59,18 +58,23 @@ import com.android.ims.internal.uce.presence.IPresenceService; import com.android.ims.internal.uce.presence.PresCapInfo; import com.android.ims.internal.uce.uceservice.IUceService; import com.android.ims.internal.uce.uceservice.ImsUceManager; -import com.android.service.ims.presence.AlarmBroadcastReceiver; -import com.android.service.ims.presence.PresenceInfoParser; -import com.android.service.ims.presence.PresencePublication; -import com.android.service.ims.presence.StackListener; +import com.android.service.ims.presence.PresenceBase; +import com.android.service.ims.presence.PresencePublisher; +import com.android.service.ims.presence.SubscribePublisher; -public class RcsStackAdaptor{ +public class RcsStackAdaptor implements PresencePublisher, SubscribePublisher { private static final boolean DEBUG = true; private static final String PERSIST_SERVICE_NAME = "com.android.service.ims.presence.PersistService"; private static final String PERSIST_SERVICE_PACKAGE = "com.android.service.ims.presence"; + /** + * PendingIntent action used to retry getting the UCE service. Need an associated + * BroadcastReceiver. + */ + public static final String ACTION_RETRY_ALARM = "com.android.service.ims.presence.retry"; + // The logger private Logger logger = Logger.getLogger(this.getClass().getName()); @@ -83,7 +87,7 @@ public class RcsStackAdaptor{ // provision status can be set by both subscribe and pubilish // for unprovisioned for 403 or 404 - private volatile int mPublishingState = PublishState.PUBLISH_STATE_NOT_PUBLISHED; + private volatile int mPublishingState = PresenceBase.PUBLISH_STATE_NOT_PUBLISHED; // It is initializing the stack presence service. private volatile boolean mIsIniting = false; @@ -186,7 +190,8 @@ public class RcsStackAdaptor{ return mListenerHandler; } - public int checkStackAndPublish(){ + @Override + public int getStackStatusForCapabilityRequest() { if (!RcsSettingUtils.getCapabilityDiscoveryEnabled(mContext)) { logger.error("getCapabilityDiscoveryEnabled = false"); return ResultCode.ERROR_SERVICE_NOT_ENABLED; @@ -199,16 +204,15 @@ public class RcsStackAdaptor{ } if (!isPublished()) { - logger.error( - "checkStackAndPublish ERROR_SERVICE_NOT_PUBLISHED"); + logger.error("checkStackAndPublish ERROR_SERVICE_NOT_PUBLISHED"); return ResultCode.ERROR_SERVICE_NOT_PUBLISHED; } return ResultCode.SUCCESS; } - private boolean isPublished(){ - if(getPublishState() != PublishState.PUBLISH_STATE_200_OK){ + private boolean isPublished() { + if (getPublisherState() != PresenceBase.PUBLISH_STATE_200_OK) { logger.error("Didnt' publish properly"); return false; } @@ -216,33 +220,30 @@ public class RcsStackAdaptor{ return true; } - public void setPublishState(int publishState) { + @Override + public void updatePublisherState(@PresenceBase.PresencePublishState int publishState) { synchronized (mSyncObj) { logger.print("mPublishingState=" + mPublishingState + " publishState=" + publishState); - if (mPublishingState != publishState) { - // save it for recovery when PresenceService crash. - SystemProperties.set("rcs.publish.status", - String.valueOf(publishState)); - - Intent publishIntent = new Intent(RcsPresence.ACTION_PUBLISH_STATE_CHANGED); - publishIntent.putExtra(RcsPresence.EXTRA_PUBLISH_STATE, publishState); - // Start PersistService and broadcast to other receivers that are listening - // dynamically. - mContext.sendStickyBroadcast(publishIntent); - launchPersistService(publishIntent); - } - mPublishingState = publishState; } + // save it for recovery when PresenceService crash. + SystemProperties.set("rcs.publish.status", String.valueOf(publishState)); + Intent publishIntent = new Intent(RcsPresence.ACTION_PUBLISH_STATE_CHANGED); + publishIntent.putExtra(RcsPresence.EXTRA_PUBLISH_STATE, publishState); + // Start PersistService and broadcast to other receivers that are listening + // dynamically. + mContext.sendStickyBroadcast(publishIntent); + launchPersistService(publishIntent); } - public int getPublishState(){ + @Override + public @PresenceBase.PresencePublishState int getPublisherState() { synchronized (mSyncObj) { return mPublishingState; } } - public int checkStackStatus(){ + private int checkStackStatus() { synchronized (mSyncObj) { if (!RcsSettingUtils.isEabProvisioned(mContext)) { logger.error("Didn't get EAB provisioned by DM"); @@ -275,19 +276,20 @@ public class RcsStackAdaptor{ return ResultCode.SUCCESS; } - public int requestCapability(String[] formatedContacts, int taskId){ - logger.print("requestCapability formatedContacts=" + formatedContacts); + @Override + public int requestCapability(String[] formattedContacts, int taskId) { + logger.print("requestCapability formattedContacts=" + formattedContacts); int ret = ResultCode.SUCCESS; try { synchronized (mSyncObj) { StatusCode retCode; - if (formatedContacts.length == 1) { + if (formattedContacts.length == 1) { retCode = mStackPresService.getContactCap( - mStackPresenceServiceHandle, formatedContacts[0], taskId); + mStackPresenceServiceHandle, formattedContacts[0], taskId); } else { retCode = mStackPresService.getContactListCap( - mStackPresenceServiceHandle, formatedContacts, taskId); + mStackPresenceServiceHandle, formattedContacts, taskId); } logger.print("GetContactListCap retCode=" + retCode); @@ -304,14 +306,15 @@ public class RcsStackAdaptor{ return ret; } - public int requestAvailability(String formatedContact, int taskId){ + @Override + public int requestAvailability(String formattedContact, int taskId) { logger.debug("requestAvailability ..."); int ret = ResultCode.SUCCESS; try{ synchronized (mSyncObj) { StatusCode retCode = mStackPresService.getContactCap( - mStackPresenceServiceHandle, formatedContact, taskId); + mStackPresenceServiceHandle, formattedContact, taskId); logger.print("getContactCap retCode=" + retCode); ret = RcsUtils.statusCodeToResultCode(retCode.getStatusCode()); @@ -325,7 +328,8 @@ public class RcsStackAdaptor{ return ret; } - public int requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener) { + @Override + public int requestPublication(RcsContactUceCapability capabilities) { logger.debug("requestPublication ..."); // Don't use checkStackAndPublish() @@ -338,15 +342,15 @@ public class RcsStackAdaptor{ TelephonyManager teleMgr = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); - if(teleMgr == null){ + if (teleMgr == null) { logger.error("teleMgr = null"); - return PresencePublication.PUBLISH_GENIRIC_FAILURE; + return ResultCode.PUBLISH_GENERIC_FAILURE; } String myNumUri = null; String myDomain = teleMgr.getIsimDomain(); logger.debug("myDomain=" + myDomain); - if(myDomain != null && myDomain.length() !=0){ + if (myDomain != null && !TextUtils.isEmpty(myDomain)) { String[] impu = teleMgr.getIsimImpu(); if(impu !=null){ @@ -363,34 +367,32 @@ public class RcsStackAdaptor{ String myNumber = PresenceInfoParser.getPhoneFromUri(myNumUri); - if(myNumber == null){ + if (myNumber == null) { myNumber = ContactNumberUtils.getDefault().format(teleMgr.getLine1Number()); - if(myDomain != null && myDomain.length() !=0){ + if (myDomain != null && !TextUtils.isEmpty(myDomain)) { myNumUri = "sip:" + myNumber + "@" + myDomain; - }else{ + } else { myNumUri = "tel:" + myNumber; } } logger.print("myNumUri=" + myNumUri + " myNumber=" + myNumber); - if(myNumUri == null || myNumber == null){ + if (myNumUri == null || myNumber == null) { logger.error("Didn't find number or impu."); - return PresencePublication.PUBLISH_GENIRIC_FAILURE; + return ResultCode.PUBLISH_GENERIC_FAILURE; } - int taskId = TaskManager.getDefault().addPublishTask(myNumber, listener); - try{ + int taskId = TaskManager.getDefault().addPublishTask(myNumber); + try { PresCapInfo pMyCapInfo = new PresCapInfo(); // Fill cap info pMyCapInfo.setContactUri(myNumUri); CapInfo capInfo = new CapInfo(); - capInfo.setIpVoiceSupported(presenceInfo.getServiceState( - RcsPresenceInfo.ServiceType.VOLTE_CALL) - == RcsPresenceInfo.ServiceState.ONLINE); - capInfo.setIpVideoSupported(presenceInfo.getServiceState( - RcsPresenceInfo.ServiceType.VT_CALL) - == RcsPresenceInfo.ServiceState.ONLINE); + capInfo.setIpVoiceSupported(capabilities.isCapable( + RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL)); + capInfo.setIpVideoSupported(capabilities.isCapable( + RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL)); capInfo.setCdViaPresenceSupported(true); capInfo.setFtSupported(false); // TODO: support FT @@ -413,12 +415,12 @@ public class RcsStackAdaptor{ } logger.debug("requestPublication ret=" + ret); - if(ret != ResultCode.SUCCESS){ + if (ret != ResultCode.SUCCESS) { logger.error("requestPublication remove taskId=" + taskId); TaskManager.getDefault().removeTask(taskId); return ret; } - }catch(RemoteException e){ + } catch (RemoteException e) { e.printStackTrace(); logger.error("Exception when call mStackPresService.getContactCap"); logger.error("requestPublication remove taskId=" + taskId); @@ -608,6 +610,12 @@ public class RcsStackAdaptor{ initImsUceService(); setInPowerDown(false); + try { + // Restore the previous value in case the process has crashed. + updatePublisherState(Integer.parseInt(SystemProperties.get("rcs.publish.status", "1"))); + } catch (NumberFormatException e) { + // do nothing and use the default. + } logger.debug("init finished"); } @@ -626,9 +634,9 @@ public class RcsStackAdaptor{ mIsIniting = true; - Intent intent = new Intent(AlarmBroadcastReceiver.ACTION_RETRY_ALARM); + Intent intent = new Intent(ACTION_RETRY_ALARM); intent.putExtra("times", times); - intent.setClass(mContext, AlarmBroadcastReceiver.class); + intent.setPackage(mContext.getPackageName()); mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java b/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java index 22e156e..0e05e7f 100644 --- a/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java +++ b/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java @@ -28,18 +28,10 @@ package com.android.service.ims; -import com.android.ims.RcsManager.ResultCode; -import com.android.ims.internal.Logger; +import com.android.ims.ResultCode; import com.android.ims.internal.uce.common.StatusCode; -public class RcsUtils{ - /* - * The logger - */ - static private Logger logger = Logger.getLogger("RcsUtils"); - - public RcsUtils() { - } +public class RcsUtils { static public int statusCodeToResultCode(int sipStatusCode){ if(sipStatusCode == StatusCode.UCE_SUCCESS || @@ -83,21 +75,5 @@ public class RcsUtils{ return ResultCode.SUBSCRIBE_GENERIC; } - - static public String toContactString(String[] contacts) { - if(contacts == null) { - return null; - } - - String result = ""; - for(int i=0; i<contacts.length; i++) { - result += contacts[i]; - if(i != contacts.length -1) { - result += ";"; - } - } - - return result; - } } diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java b/rcs/rcsservice/src/com/android/service/ims/StackListener.java index ae1d415..7edf080 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java +++ b/rcs/rcsservice/src/com/android/service/ims/StackListener.java @@ -26,7 +26,7 @@ * DAMAGE. */ -package com.android.service.ims.presence; +package com.android.service.ims; import android.content.Context; import android.content.Intent; @@ -35,9 +35,12 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.RemoteException; +import android.telephony.ims.RcsContactUceCapability; +import android.text.TextUtils; import android.util.Log; import com.android.ims.RcsManager; +import com.android.ims.RcsPresenceInfo; import com.android.ims.internal.Logger; import com.android.ims.internal.uce.common.StatusCode; import com.android.ims.internal.uce.presence.IPresenceListener; @@ -47,8 +50,12 @@ import com.android.ims.internal.uce.presence.PresPublishTriggerType; import com.android.ims.internal.uce.presence.PresResInfo; import com.android.ims.internal.uce.presence.PresRlmiInfo; import com.android.ims.internal.uce.presence.PresSipResponse; +import com.android.ims.internal.uce.presence.PresSubscriptionState; import com.android.ims.internal.uce.presence.PresTupleInfo; -import com.android.service.ims.RcsStackAdaptor; +import com.android.service.ims.presence.PresencePublication; +import com.android.service.ims.presence.PresenceSubscriber; + +import java.util.ArrayList; public class StackListener extends Handler{ /* @@ -82,7 +89,7 @@ public class StackListener extends Handler{ mContext = context; } - public void setPresencePublication(PresencePublication presencePublication){ + public void setPresencePublication(PresencePublication presencePublication) { mPresencePublication = presencePublication; } @@ -111,7 +118,8 @@ public class StackListener extends Handler{ return; } - mPresencePublication.invokePublish(val); + mPresencePublication.onStackPublishRequested( + convertToStackPublishTriggerType(val.getPublishTrigeerType())); break; } @@ -119,13 +127,16 @@ public class StackListener extends Handler{ case PRESENCE_IMS_UNSOL_PUBLISH_CMDSTATUS: { PresCmdStatus pCmdStatus = (PresCmdStatus) msg.obj; - if(mPresencePublication == null || pCmdStatus == null){ + if(mPresencePublication == null || pCmdStatus == null) { logger.error("mPresencePublication=" + mPresencePublication + " pCmdStatus=" + pCmdStatus); return; } - mPresencePublication.handleCmdStatus(pCmdStatus); + int commandResult = RcsUtils.statusCodeToResultCode( + pCmdStatus.getStatus().getStatusCode()); + mPresencePublication.onCommandStatusUpdated(pCmdStatus.getUserData(), + pCmdStatus.getRequestId(), commandResult); } break; @@ -138,8 +149,10 @@ public class StackListener extends Handler{ " pCmdStatus=" + pCmdStatus); return; } - - mPresenceSubscriber.handleCmdStatus(pCmdStatus); + int commandResult = RcsUtils.statusCodeToResultCode( + pCmdStatus.getStatus().getStatusCode()); + mPresenceSubscriber.onCommandStatusUpdated(pCmdStatus.getUserData(), + pCmdStatus.getRequestId(), commandResult); break; } @@ -147,13 +160,14 @@ public class StackListener extends Handler{ case PRESENCE_IMS_UNSOL_PUBLISH_SIPRESPONSE: { PresSipResponse pSipResponse = (PresSipResponse) msg.obj; - if(mPresencePublication == null || pSipResponse == null){ + if(mPresencePublication == null || pSipResponse == null) { logger.error("mPresencePublication=" + mPresencePublication + "pSipResponse=" +pSipResponse); return; } - mPresencePublication.handleSipResponse(pSipResponse); + mPresencePublication.onSipResponse(pSipResponse.getRequestId(), + pSipResponse.getSipResponseCode(), pSipResponse.getReasonPhrase()); break; } @@ -167,7 +181,8 @@ public class StackListener extends Handler{ return; } - mPresenceSubscriber.handleSipResponse(pSipResponse); + mPresenceSubscriber.onSipResponse(pSipResponse.getRequestId(), + pSipResponse.getSipResponseCode(), pSipResponse.getReasonPhrase()); break; } @@ -180,9 +195,16 @@ public class StackListener extends Handler{ " notifyData=" + notifyData); return; } - - mPresenceSubscriber.updatePresence(notifyData.getUri(), - notifyData.getTupleInfo()); + RcsPresenceInfo rcsPresenceInfo = PresenceInfoParser.getPresenceInfoFromTuple( + notifyData.getUri(), notifyData.getTupleInfo()); + if(rcsPresenceInfo == null || TextUtils.isEmpty( + rcsPresenceInfo.getContactNumber())){ + logger.error("rcsPresenceInfo is null or " + + "TextUtils.isEmpty(rcsPresenceInfo.getContactNumber()"); + return; + } + mPresenceSubscriber.updatePresence( + PresenceInfoParser.getUceCapability(rcsPresenceInfo)); break; } @@ -196,8 +218,40 @@ public class StackListener extends Handler{ return; } - mPresenceSubscriber.updatePresences(notifyListData.getRlmiInfo(), - notifyListData.getResInfo()); + RcsPresenceInfo[] rcsPresenceInfos = PresenceInfoParser. + getPresenceInfosFromPresenceRes(notifyListData.getRlmiInfo(), + notifyListData.getResInfo()); + if(rcsPresenceInfos == null){ + logger.error("updatePresences: rcsPresenceInfos == null"); + return; + } + + PresRlmiInfo info = notifyListData.getRlmiInfo(); + boolean isTerminated = false; + if (info.getPresSubscriptionState() != null) { + if (info.getPresSubscriptionState().getPresSubscriptionStateValue() == + PresSubscriptionState.UCE_PRES_SUBSCRIPTION_STATE_TERMINATED) { + isTerminated = true; + } + } + + ArrayList<RcsContactUceCapability> capabilities = new ArrayList<>(); + + for (int i=0; i < rcsPresenceInfos.length; i++) { + if(rcsPresenceInfos[i] != null && TextUtils.isEmpty( + rcsPresenceInfos[i].getContactNumber())){ + continue; + } + RcsContactUceCapability capability = PresenceInfoParser.getUceCapability( + rcsPresenceInfos[i]); + if(capability != null && (capability.getContactUri() != null)){ + logger.debug("capability=" + capability); + capabilities.add(capability); + } + } + + mPresenceSubscriber.updatePresences(info.getRequestId(), capabilities, isTerminated, + info.getSubscriptionTerminatedReason()); break; } @@ -353,11 +407,9 @@ public class StackListener extends Handler{ } // Handle the cached trigger which got from stack - if(mPresencePublication != null && mPresencePublication.getHasCachedTrigger()){ + if(mPresencePublication != null) { logger.debug("publish for cached trigger"); - - mPresencePublication.invokePublish( - PresencePublication.PublishType.PRES_PUBLISH_TRIGGER_CACHED_TRIGGER); + mPresencePublication.onStackAvailable(); } Intent intent = new Intent(RcsManager.ACTION_RCS_SERVICE_AVAILABLE); @@ -518,5 +570,30 @@ public class StackListener extends Handler{ logger.debug("unpublishMessageSent()"); } }; + + @PresencePublication.StackPublishTriggerType + private static int convertToStackPublishTriggerType(int presPublishTriggerType) { + switch (presPublishTriggerType) { + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_WLAN: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_WLAN; + case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN: + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN; + } + return PresencePublication.UCE_PRES_PUBLISH_TRIGGER_UNKNOWN; + } } diff --git a/rcs/rcsservice/src/com/android/service/ims/Task.java b/rcs/rcsservice/src/com/android/service/ims/Task.java index eb36a5f..61e85b4 100644 --- a/rcs/rcsservice/src/com/android/service/ims/Task.java +++ b/rcs/rcsservice/src/com/android/service/ims/Task.java @@ -28,8 +28,8 @@ package com.android.service.ims; -import com.android.ims.IRcsPresenceListener; import com.android.ims.internal.Logger; +import com.android.service.ims.presence.ContactCapabilityResponse; /** * Task @@ -51,21 +51,6 @@ public class Task{ // QRCS_PRES_CMD_SETNEWFEATURETAG public int mCmdId; - // filled after IQPresListener_CMDStatus - // QRCS_STATUSCODE, possible values are: - // QRCS_SUCCESS - // QRCS_FAILURE - // QRCS_SUCCESS_ASYC_UPDATE - // QRCS_INVALID_SERVICE_HANDLE - // QRCS_INVALID_LISTENER_HANDLE - // QRCS_INVALID_PARAM - // QRCS_FETCH_ERROR - // QRCS_REQUEST_TIMEOUT - // QRCS_INSUFFICIENT_MEMORY - // QRCS_LOST_NET - // QRCS_NOT_SUPPORTED - // QRCS_NOT_FOUND - // Note: have converted it to ResultCode. public int mCmdStatus; //filled after IQPresListener_CMDStatus @@ -77,10 +62,9 @@ public class Task{ // filled after IQPresListener_SipResponseReceived public String mSipReasonPhrase; - // filled before send the request - public IRcsPresenceListener mListener; + public ContactCapabilityResponse mListener; - public Task(int taskId, int cmdId, IRcsPresenceListener listener){ + public Task(int taskId, int cmdId, ContactCapabilityResponse listener) { mTaskId = taskId; mCmdId = cmdId; mListener = listener; diff --git a/rcs/rcsservice/src/com/android/service/ims/TaskManager.java b/rcs/rcsservice/src/com/android/service/ims/TaskManager.java index a643861..076a244 100644 --- a/rcs/rcsservice/src/com/android/service/ims/TaskManager.java +++ b/rcs/rcsservice/src/com/android/service/ims/TaskManager.java @@ -35,8 +35,8 @@ import android.os.Looper; import android.os.Message; import android.telephony.PhoneNumberUtils; -import com.android.ims.IRcsPresenceListener; import com.android.ims.internal.Logger; +import com.android.service.ims.presence.ContactCapabilityResponse; import com.android.service.ims.presence.PresenceAvailabilityTask; import com.android.service.ims.presence.PresenceCapabilityTask; import com.android.service.ims.presence.PresenceTask; @@ -109,7 +109,7 @@ public class TaskManager{ } public int addCapabilityTask(Context context, String[] contacts, - IRcsPresenceListener listener, long timeout){ + ContactCapabilityResponse listener, long timeout){ int taskId = TaskManager.getDefault().generateTaskId(); synchronized (mSyncObj){ Task task = new PresenceCapabilityTask(context, taskId, TASK_TYPE_GET_CAPABILITY, @@ -120,7 +120,7 @@ public class TaskManager{ return taskId; } - public int addAvailabilityTask(String contact, IRcsPresenceListener listener){ + public int addAvailabilityTask(String contact, ContactCapabilityResponse listener){ int taskId = TaskManager.getDefault().generateTaskId(); synchronized (mSyncObj){ String[] contacts = new String[1]; @@ -133,12 +133,12 @@ public class TaskManager{ return taskId; } - public int addPublishTask(String contact, IRcsPresenceListener listener){ + public int addPublishTask(String contact){ int taskId = TaskManager.getDefault().generateTaskId(); synchronized (mSyncObj){ String[] contacts = new String[1]; contacts[0] = contact; - Task task = new PresenceTask(taskId, TASK_TYPE_PUBLISH, listener, contacts); + Task task = new PresenceTask(taskId, TASK_TYPE_PUBLISH, null /*listener*/, contacts); putTaskInternal(taskId, task); } @@ -162,6 +162,32 @@ public class TaskManager{ } } + public Task getTaskForSingleContactQuery(String contact) { + synchronized (mSyncObj){ + Set<String> keys= mTaskMap.keySet(); + if(keys == null){ + logger.debug("getTaskByContact keys=null"); + return null; + } + + for(String key:keys){ + Task task = mTaskMap.get(key); + if(task == null){ + continue; + } + + if (task instanceof PresenceTask) { + PresenceTask presenceTask = (PresenceTask) task; + if(presenceTask.mContacts.length == 1 && + PhoneNumberUtils.compare(contact, presenceTask.mContacts[0])){ + return task; + } + } + } + } + return null; + } + public Task getTaskByRequestId(int sipRequestId){ synchronized (mSyncObj){ Set<String> keys= mTaskMap.keySet(); diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/ContactCapabilityResponse.java b/rcs/rcsservice/src/com/android/service/ims/presence/ContactCapabilityResponse.java new file mode 100644 index 0000000..5eb3154 --- /dev/null +++ b/rcs/rcsservice/src/com/android/service/ims/presence/ContactCapabilityResponse.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of The Android Open Source Project nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +package com.android.service.ims.presence; + +import android.telephony.ims.RcsContactUceCapability; + +import java.util.List; + +public interface ContactCapabilityResponse { + + /** + * Called when a capability request returns a "200 OK" (means capable) or "404 xxxx" for SIP + * request of single contact number (means not capable). + * + * @param reqId the request ID which is returned by requestCapability or + * requestAvailability + */ + void onSuccess(int reqId); + + /** + * Called when a local error is generated a SIP error is generated from the network. + * + * @param reqId the request ID which is returned by requestCapability or + * requestAvailability + * @param resultCode the result code which is defined in RcsManager.ResultCode. + */ + void onError(int reqId, int resultCode); + + /** + * Called when the request returns a "terminated notify" indication from the network. + * The presence service will not receive any more notifications for the request after this + * indication is received. + * + * @param reqId the request ID which is returned by requestCapability or + * requestAvailability + */ + void onFinish(int reqId); + + /** + * Called when there is a timeout waiting for the "terminated notify" indication from the + * network. + * + * @param reqId the request ID which is returned by requestCapability or + * requestAvailability. + */ + void onTimeout(int reqId); + + /** + * Called when there is an update to the capabilities from the network. On error, the + * capabilities will also be updates as not capable. + */ + void onCapabilitiesUpdated(List<RcsContactUceCapability> contactCapabilities, + boolean updateLastTimestamp); +} diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceAvailabilityTask.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceAvailabilityTask.java index a008589..08a5b32 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceAvailabilityTask.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceAvailabilityTask.java @@ -28,7 +28,6 @@ package com.android.service.ims.presence; -import com.android.ims.IRcsPresenceListener; import com.android.ims.internal.Logger; /** @@ -45,7 +44,7 @@ public class PresenceAvailabilityTask extends PresenceTask{ // Time when get the notify. Used to check the 60s expires. private long mNotifyTimeStamp = 0; - public PresenceAvailabilityTask(int taskId, int cmdId, IRcsPresenceListener listener, + public PresenceAvailabilityTask(int taskId, int cmdId, ContactCapabilityResponse listener, String[] contacts){ super(taskId, cmdId, listener, contacts); diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceBase.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceBase.java index abe6fd7..9ffcba1 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceBase.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceBase.java @@ -28,61 +28,110 @@ package com.android.service.ims.presence; +import android.annotation.IntDef; import android.content.Context; -import android.os.RemoteException; import android.content.Intent; -import com.android.ims.internal.uce.presence.PresCmdStatus; -import com.android.ims.internal.uce.presence.PresSipResponse; -import com.android.ims.RcsManager.ResultCode; -import com.android.ims.RcsPresence.PublishState; +import com.android.ims.ResultCode; import com.android.ims.internal.Logger; import com.android.internal.telephony.TelephonyIntents; import com.android.service.ims.Task; -import com.android.service.ims.RcsUtils; import com.android.service.ims.TaskManager; -public abstract class PresenceBase{ - /* - * The logger - */ +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class PresenceBase { static private Logger logger = Logger.getLogger("PresenceBase"); - protected Context mContext = null; + protected Context mContext; + + /** + * The phone is PUBLISH_STATE_200_OK when + * the response of the last publish is "200 OK" + */ + public static final int PUBLISH_STATE_200_OK = 0; + + /** + * The phone didn't publish after power on. + * the phone didn't get any publish response yet. + */ + public static final int PUBLISH_STATE_NOT_PUBLISHED = 1; + + /** + * The phone is PUBLISH_STATE_VOLTE_PROVISION_ERROR when the response is one of items + * in config_volte_provision_error_on_publish_response for PUBLISH or + * in config_volte_provision_error_on_subscribe_response for SUBSCRIBE. + */ + public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 2; + + /** + * The phone is PUBLISH_STATE_RCS_PROVISION_ERROR when the response is one of items + * in config_rcs_provision_error_on_publish_response for PUBLISH or + * in config_rcs_provision_error_on_subscribe_response for SUBSCRIBE.Publ + */ + public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 3; - public PresenceBase() { + /** + * The phone is PUBLISH_STATE_REQUEST_TIMEOUT when + * The response of the last publish is "408 Request Timeout". + */ + public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 4; + + /** + * The phone is PUBLISH_STATE_OTHER_ERROR when + * the response of the last publish is other temp error. Such as + * 503 Service Unavailable + * Device shall retry with exponential back-off + * + * 423 Interval Too Short. Requested expiry interval too short and server rejects it + * Device shall re-attempt subscription after changing the expiration interval in + * the Expires header field to be equal to or greater than the expiration interval + * within the Min-Expires header field of the 423 response. + */ + public static final int PUBLISH_STATE_OTHER_ERROR = 5; + + @IntDef(value = { + PUBLISH_STATE_200_OK, + PUBLISH_STATE_NOT_PUBLISHED, + PUBLISH_STATE_VOLTE_PROVISION_ERROR, + PUBLISH_STATE_RCS_PROVISION_ERROR, + PUBLISH_STATE_REQUEST_TIMEOUT, + PUBLISH_STATE_OTHER_ERROR + }, prefix="PUBLISH_STATE_") + @Retention(RetentionPolicy.SOURCE) + public @interface PresencePublishState {} + + public PresenceBase(Context context) { + mContext = context; } - protected void handleCallback(Task task, int resultCode, boolean forCmdStatus){ - if(task == null){ + protected void handleCallback(Task task, int resultCode, boolean forCmdStatus) { + if (task == null) { logger.debug("task == null"); return; } - if(task.mListener != null){ - try{ - if(resultCode >= ResultCode.SUCCESS){ - if(!forCmdStatus){ - task.mListener.onSuccess(task.mTaskId); - } - }else{ - task.mListener.onError(task.mTaskId, resultCode); + if (task.mListener != null) { + if(resultCode >= ResultCode.SUCCESS){ + if(!forCmdStatus){ + task.mListener.onSuccess(task.mTaskId); } - }catch(RemoteException e){ - logger.debug("Failed to send the status to client."); + }else{ + task.mListener.onError(task.mTaskId, resultCode); } } // remove task when error // remove task when SIP response success. // For list capability polling we will waiting for the terminated notify or timeout. - if(resultCode != ResultCode.SUCCESS){ + if (resultCode != ResultCode.SUCCESS) { if(task instanceof PresencePublishTask){ PresencePublishTask publishTask = (PresencePublishTask) task; logger.debug("handleCallback for publishTask=" + publishTask); - if(resultCode == PublishState.PUBLISH_STATE_VOLTE_PROVISION_ERROR) { + if(resultCode == PUBLISH_STATE_VOLTE_PROVISION_ERROR) { // retry 3 times for "403 Not Authorized for Presence". - if(publishTask.getRetryCount() >= 3) { + if (publishTask.getRetryCount() >= 3) { //remove capability after try 3 times by PresencePolling logger.debug("handleCallback remove task=" + task); TaskManager.getDefault().removeTask(task.mTaskId); @@ -121,16 +170,10 @@ public abstract class PresenceBase{ } } - public void handleCmdStatus(PresCmdStatus pCmdStatus){ - if(pCmdStatus == null){ - logger.error("handleCallbackForCmdStatus pCmdStatus=null"); - return; - } - - Task task = TaskManager.getDefault().getTask(pCmdStatus.getUserData()); - int resultCode = RcsUtils.statusCodeToResultCode(pCmdStatus.getStatus().getStatusCode()); - if(task != null){ - task.mSipRequestId = pCmdStatus.getRequestId(); + public void onCommandStatusUpdated(int taskId, int requestId, int resultCode) { + Task task = TaskManager.getDefault().getTask(taskId); + if (task != null){ + task.mSipRequestId = requestId; task.mCmdStatus = resultCode; TaskManager.getDefault().putTask(task.mTaskId, task); } @@ -167,7 +210,5 @@ public abstract class PresenceBase{ } return false; } - - abstract public void handleSipResponse(PresSipResponse pSipResponse); } diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceCapabilityTask.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceCapabilityTask.java index ff69915..e94e51a 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceCapabilityTask.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceCapabilityTask.java @@ -32,11 +32,9 @@ import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.os.RemoteException; import android.os.SystemClock; import com.android.ims.internal.Logger; -import com.android.ims.IRcsPresenceListener; import com.android.service.ims.TaskManager; /** @@ -48,6 +46,9 @@ public class PresenceCapabilityTask extends PresenceTask{ */ private Logger logger = Logger.getLogger(this.getClass().getName()); + /** + * PendingIntent Action that will be scheduled via AlarmManager as a task timeout. + */ public static final String ACTION_TASK_TIMEOUT_ALARM = "com.android.service.ims.presence.task.timeout"; @@ -70,7 +71,7 @@ public class PresenceCapabilityTask extends PresenceTask{ private long mTimeout; public PresenceCapabilityTask(Context context, int taskId, int cmdId, - IRcsPresenceListener listener, String[] contacts, + ContactCapabilityResponse listener, String[] contacts, long timeout){ super(taskId, cmdId, listener, contacts); mContext = context; @@ -105,7 +106,7 @@ public class PresenceCapabilityTask extends PresenceTask{ } Intent intent = new Intent(ACTION_TASK_TIMEOUT_ALARM); - intent.setClass(mContext, AlarmBroadcastReceiver.class); + intent.setPackage(mContext.getPackageName()); intent.putExtra("taskId", mTaskId); PendingIntent mAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); @@ -133,14 +134,9 @@ public class PresenceCapabilityTask extends PresenceTask{ public void onTimeout(){ logger.debug("onTimeout, taskId=" + mTaskId); - try{ - if(mListener != null){ - mListener.onTimeout(mTaskId); - } - }catch (RemoteException e){ - logger.error("RemoteException", e); + if(mListener != null){ + mListener.onTimeout(mTaskId); } - TaskManager.getDefault().removeTask(mTaskId); } @@ -159,12 +155,8 @@ public class PresenceCapabilityTask extends PresenceTask{ } cancelTimer(); - try{ - if(mListener != null){ - mListener.onFinish(mTaskId); - } - }catch (RemoteException e){ - logger.error("RemoteException", e); + if(mListener != null){ + mListener.onFinish(mTaskId); } TaskManager.getDefault().removeTask(mTaskId); diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java index f827622..62c5091 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java @@ -28,46 +28,40 @@ package com.android.service.ims.presence; -import java.util.Arrays; - +import android.annotation.IntDef; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import com.android.internal.telephony.Phone; +import android.content.IntentFilter; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; import android.provider.Settings; -import android.os.SystemProperties; -import android.content.BroadcastReceiver; +import android.telecom.PhoneAccount; +import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; - -import android.telecom.TelecomManager; -import android.content.IntentFilter; -import android.app.PendingIntent; -import android.app.AlarmManager; -import android.os.SystemClock; -import android.os.Message; -import android.os.Handler; +import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.feature.MmTelFeature; - -import com.android.ims.ImsManager; -import com.android.ims.ImsServiceClass; import com.android.ims.ImsConfig; +import com.android.ims.ImsManager; +import com.android.ims.ResultCode; import com.android.ims.internal.Logger; -import com.android.ims.internal.uce.presence.PresPublishTriggerType; -import com.android.ims.internal.uce.presence.PresSipResponse; -import com.android.ims.internal.uce.presence.PresCmdStatus; -import com.android.ims.RcsPresenceInfo; -import com.android.ims.IRcsPresenceListener; -import com.android.ims.RcsManager.ResultCode; -import com.android.ims.RcsPresence.PublishState; import com.android.internal.telephony.IccCardConstants; +import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyIntents; import com.android.service.ims.RcsSettingUtils; -import com.android.service.ims.RcsStackAdaptor; import com.android.service.ims.Task; import com.android.service.ims.TaskManager; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public class PresencePublication extends PresenceBase { private Logger logger = Logger.getLogger(this.getClass().getName()); @@ -88,37 +82,11 @@ public class PresencePublication extends PresenceBase { volatile PublishRequest mPublishedRequest = null; /* - * Message to notify for a publish - */ - public static final int MESSAGE_RCS_PUBLISH_REQUEST = 1; - - /** - * Publisher Error base - */ - public static final int PUBLISH_ERROR_CODE_START = ResultCode.SUBSCRIBER_ERROR_CODE_END; - - /** - * All publish errors not covered by specific errors - */ - public static final int PUBLISH_GENIRIC_FAILURE = PUBLISH_ERROR_CODE_START - 1; - - /** - * Responding for 403 - not authorized + * Message sent to mMsgHandler when there is a new request to Publish capabilities. */ - public static final int PUBLISH_NOT_AUTHORIZED_FOR_PRESENCE = PUBLISH_ERROR_CODE_START - 2; + private static final int MESSAGE_RCS_PUBLISH_REQUEST = 1; - /** - * Responding for 404 error code. The subscriber is not provisioned. - * The Client should not send any EAB traffic after get this error. - */ - public static final int PUBLISH_NOT_PROVISIONED = PUBLISH_ERROR_CODE_START - 3; - - /** - * Responding for 200 - OK - */ - public static final int PUBLISH_SUCESS = ResultCode.SUCCESS; - - private RcsStackAdaptor mRcsStackAdaptor = null; + private PresencePublisher mPresencePublisher; private PresenceSubscriber mSubscriber = null; static private PresencePublication sPresencePublication = null; private BroadcastReceiver mReceiver = null; @@ -135,7 +103,43 @@ public class PresencePublication extends PresenceBase { private final String[] mConfigVolteProvisionErrorOnPublishResponse; private final String[] mConfigRcsProvisionErrorOnPublishResponse; - public class PublishType{ + /** ETag expired. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED = 0; + /** Move to LTE with VoPS disabled. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; + /** Move to LTE with VoPS enabled. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; + /** Move to eHRPD. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD = 3; + /** Move to HSPA+. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS = 4; + /** Move to 3G. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G = 5; + /** Move to 2G. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G = 6; + /** Move to WLAN */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_WLAN = 7; + /** Move to IWLAN */ + public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN = 8; + /** Trigger is unknown. */ + public static final int UCE_PRES_PUBLISH_TRIGGER_UNKNOWN = 9; + + @IntDef(value = { + UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_WLAN, + UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN, + UCE_PRES_PUBLISH_TRIGGER_UNKNOWN + }, prefix="UCE_PRES_PUBLISH_TRIGGER_") + @Retention(RetentionPolicy.SOURCE) + public @interface StackPublishTriggerType {} + + public class PublishType { public static final int PRES_PUBLISH_TRIGGER_DATA_CHANGED = 0; // the lower layer should send trigger when enable volte // the lower layer should unpublish when disable volte @@ -147,17 +151,12 @@ public class PresencePublication extends PresenceBase { public static final int PRES_PUBLISH_TRIGGER_FEATURE_AVAILABILITY_CHANGED = 5; }; - /** - * @param rcsStackAdaptor - * @param context - */ - public PresencePublication(RcsStackAdaptor rcsStackAdaptor, Context context, + public PresencePublication(PresencePublisher presencePublisher, Context context, String[] configVolteProvisionErrorOnPublishResponse, String[] configRcsProvisionErrorOnPublishResponse) { - super(); + super(context); logger.debug("PresencePublication constrcuct"); - this.mRcsStackAdaptor = rcsStackAdaptor; - this.mContext = context; + this.mPresencePublisher = presencePublisher; mConfigVolteProvisionErrorOnPublishResponse = configVolteProvisionErrorOnPublishResponse; mConfigRcsProvisionErrorOnPublishResponse = configRcsProvisionErrorOnPublishResponse; @@ -176,12 +175,6 @@ public class PresencePublication extends PresenceBase { Phone.TTY_MODE_OFF); logger.debug("The current TTY mode is: " + mPreferredTtyMode); - if(mRcsStackAdaptor != null){ - mRcsStackAdaptor.setPublishState( - SystemProperties.getInt("rcs.publish.status", - PublishState.PUBLISH_STATE_NOT_PUBLISHED)); - } - mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -214,7 +207,7 @@ public class PresencePublication extends PresenceBase { // treate hot SIM hot swap as power on. mDonotRetryUntilPowerCycle = false; if(mHasCachedTrigger) { - invokePublish(PresencePublication.PublishType. + requestLocalPublish(PublishType. PRES_PUBLISH_TRIGGER_CACHED_TRIGGER); } break; @@ -235,16 +228,14 @@ public class PresencePublication extends PresenceBase { // only reset when the SIM gets absent. reset(); mSimLoaded = false; - setPublishState( - PublishState.PUBLISH_STATE_NOT_PUBLISHED); + setPublishState(PUBLISH_STATE_NOT_PUBLISHED); } }else if(Intent.ACTION_AIRPLANE_MODE_CHANGED.equalsIgnoreCase(intent.getAction())){ boolean airplaneMode = intent.getBooleanExtra("state", false); if(airplaneMode){ logger.print("Airplane mode, set to PUBLISH_STATE_NOT_PUBLISHED"); reset(); - setPublishState( - PublishState.PUBLISH_STATE_NOT_PUBLISHED); + setPublishState(PUBLISH_STATE_NOT_PUBLISHED); } }else if(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED.equalsIgnoreCase( intent.getAction())){ @@ -261,7 +252,7 @@ public class PresencePublication extends PresenceBase { if (mIsTtyEnabled != isTtyEnabled) { logger.print("ttyEnabled status changed from " + mIsTtyEnabled + " to " + isTtyEnabled); - invokePublish(PresencePublication.PublishType. + requestLocalPublish(PublishType. PRES_PUBLISH_TRIGGER_TTY_ENABLE_STATUS); } } else if(ImsConfig.ACTION_IMS_FEATURE_CHANGED.equalsIgnoreCase( @@ -421,7 +412,7 @@ public class PresencePublication extends PresenceBase { logger.debug("provisioned, set mDonotRetryUntilPowerCycle to false"); mDonotRetryUntilPowerCycle = false; if(mHasCachedTrigger) { - invokePublish(PresencePublication.PublishType.PRES_PUBLISH_TRIGGER_CACHED_TRIGGER); + requestLocalPublish(PublishType.PRES_PUBLISH_TRIGGER_CACHED_TRIGGER); } } } @@ -445,8 +436,7 @@ public class PresencePublication extends PresenceBase { mDataEnabled = value; RcsSettingUtils.setMobileDataEnabled(mContext, mDataEnabled); - invokePublish( - PresencePublication.PublishType.PRES_PUBLISH_TRIGGER_DATA_CHANGED); + requestLocalPublish(PublishType.PRES_PUBLISH_TRIGGER_DATA_CHANGED); } } @@ -455,11 +445,16 @@ public class PresencePublication extends PresenceBase { if(mVtEnabled != enabled) { mVtEnabled = enabled; - invokePublish(PresencePublication.PublishType. - PRES_PUBLISH_TRIGGER_VTCALL_CHANGED); + requestLocalPublish(PublishType.PRES_PUBLISH_TRIGGER_VTCALL_CHANGED); } } + @Override + public void onCommandStatusUpdated(int taskId, int requestId, int resultCode) { + logger.info("onCommandStatusUpdated: resultCode= " + resultCode); + super.onCommandStatusUpdated(taskId, requestId, resultCode); + } + /** * @return return true if it had been PUBLISHED. */ @@ -471,36 +466,30 @@ public class PresencePublication extends PresenceBase { (System.currentTimeMillis() - mPublishingRequest.getTimestamp() <= publishThreshold); - return (getPublishState() == PublishState.PUBLISH_STATE_200_OK || publishing); + return (getPublishState() == PUBLISH_STATE_200_OK || publishing); } /** - * @return the Publish State + * @return The result of the last Publish request. */ - public int getPublishState() { - if(mRcsStackAdaptor == null){ - return PublishState.PUBLISH_STATE_NOT_PUBLISHED; + public @PresenceBase.PresencePublishState int getPublishState() { + if (mPresencePublisher != null) { + return mPresencePublisher.getPublisherState(); } - - return mRcsStackAdaptor.getPublishState(); + return PUBLISH_STATE_NOT_PUBLISHED; } /** - * @param mPublishState the publishState to set + * @param publishState The result of the last publish request. */ public void setPublishState(int publishState) { - if(mRcsStackAdaptor != null){ - mRcsStackAdaptor.setPublishState(publishState); + if (mPresencePublisher != null) { + mPresencePublisher.updatePublisherState(publishState); } } - public boolean getHasCachedTrigger(){ - return mHasCachedTrigger; - } - - // Tiggered by framework. - public int invokePublish(int trigger){ - int ret; + // Trigger a local publish based off of state changes in the framework. + private void requestLocalPublish(int trigger) { // if the value is true then it will call stack to send the PUBLISH // though the previous publish had the same capability @@ -553,26 +542,26 @@ public class PresencePublication extends PresenceBase { if(mGotTriggerFromStack == false){ // Waiting for RCS stack get ready. logger.print("Didn't get trigger from stack yet, discard framework trigger."); - return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; + return; } if (mDonotRetryUntilPowerCycle) { logger.print("Don't publish until next power cycle"); - return ResultCode.SUCCESS; + return; } if(!mSimLoaded){ //need to read some information from SIM to publish logger.print("invokePublish cache the trigger since the SIM is not ready"); mHasCachedTrigger = true; - return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; + return; } //the provision status didn't be read from modem yet if(!RcsSettingUtils.isEabProvisioned(mContext)) { logger.print("invokePublish cache the trigger, not provision yet"); mHasCachedTrigger = true; - return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; + return; } PublishRequest publishRequest = new PublishRequest( @@ -580,25 +569,20 @@ public class PresencePublication extends PresenceBase { requestPublication(publishRequest); - return ResultCode.SUCCESS; + return; } - public int invokePublish(PresPublishTriggerType val) { - int ret; - + public void onStackPublishRequested(@StackPublishTriggerType int publishTriggerType) { mGotTriggerFromStack = true; - // Always send the PUBLISH when we got the trigger from stack. - // This can avoid any issue when switch the phone between IWLAN and LTE. - boolean bForceToNetwork = true; - switch (val.getPublishTrigeerType()) + switch (publishTriggerType) { - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED: + case UCE_PRES_PUBLISH_TRIGGER_ETAG_EXPIRED: { logger.print("PUBLISH_TRIGGER_ETAG_EXPIRED"); break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED: { logger.print("PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED"); mMovedToLTE = true; @@ -609,7 +593,7 @@ public class PresencePublication extends PresenceBase { mImsRegistered = true; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED: { logger.print("PUBLISH_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED"); mMovedToLTE = true; @@ -620,7 +604,7 @@ public class PresencePublication extends PresenceBase { mImsRegistered = true; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN: { logger.print("QRCS_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN"); mMovedToLTE = false; @@ -631,7 +615,7 @@ public class PresencePublication extends PresenceBase { mImsRegistered = true; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_EHRPD: { logger.print("PUBLISH_TRIGGER_MOVE_TO_EHRPD"); mMovedToLTE = false; @@ -642,7 +626,7 @@ public class PresencePublication extends PresenceBase { mImsRegistered = true; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS: { logger.print("PUBLISH_TRIGGER_MOVE_TO_HSPAPLUS"); mMovedToLTE = false; @@ -650,7 +634,7 @@ public class PresencePublication extends PresenceBase { mMovedToIWLAN = false; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_2G: { logger.print("PUBLISH_TRIGGER_MOVE_TO_2G"); mMovedToLTE = false; @@ -658,7 +642,7 @@ public class PresencePublication extends PresenceBase { mMovedToIWLAN = false; break; } - case PresPublishTriggerType.UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G: + case UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_3G: { logger.print("PUBLISH_TRIGGER_MOVE_TO_3G"); mMovedToLTE = false; @@ -672,29 +656,38 @@ public class PresencePublication extends PresenceBase { if (mDonotRetryUntilPowerCycle) { logger.print("Don't publish until next power cycle"); - return ResultCode.SUCCESS; + return; } if(!mSimLoaded){ //need to read some information from SIM to publish logger.print("invokePublish cache the trigger since the SIM is not ready"); mHasCachedTrigger = true; - return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; + return; } //the provision status didn't be read from modem yet if(!RcsSettingUtils.isEabProvisioned(mContext)) { logger.print("invokePublish cache the trigger, not provision yet"); mHasCachedTrigger = true; - return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; + return; } + // Always send the PUBLISH when we got the trigger from stack. + // This can avoid any issue when switch the phone between IWLAN and LTE. PublishRequest publishRequest = new PublishRequest( - bForceToNetwork, System.currentTimeMillis()); + true /*forceToNetwork*/, System.currentTimeMillis()); requestPublication(publishRequest); + } - return ResultCode.SUCCESS; + /** + * Trigger a publish when the stack becomes available and we have a cached trigger waiting. + */ + public void onStackAvailable() { + if (mHasCachedTrigger) { + requestLocalPublish(PublishType.PRES_PUBLISH_TRIGGER_CACHED_TRIGGER); + } } public class PublishRequest { @@ -835,8 +828,8 @@ public class PresencePublication extends PresenceBase { return; } - if (mRcsStackAdaptor == null) { - logger.error("mRcsStackAdaptor == null"); + if (mPresencePublisher == null) { + logger.error("mPresencePublisher == null"); return; } @@ -861,7 +854,7 @@ public class PresencePublication extends PresenceBase { (publishRequest.hasSamePublishContent(mPublishingRequest) || (mPublishingRequest == null) && publishRequest.hasSamePublishContent(mPublishedRequest)) && - (getPublishState() != PublishState.PUBLISH_STATE_NOT_PUBLISHED)) { + (getPublishState() != PUBLISH_STATE_NOT_PUBLISHED)) { logger.print("Don't need publish since the capability didn't change publishRequest " + publishRequest + " getPublishState()=" + getPublishState()); return; @@ -897,7 +890,7 @@ public class PresencePublication extends PresenceBase { // we need send PUBLISH once even the volte is off when power on the phone. // That will tell other phone that it has no volte/vt capability. if(!getImsManager().isEnhanced4gLteModeSettingEnabledByUser() && - getPublishState() != PublishState.PUBLISH_STATE_NOT_PUBLISHED) { + getPublishState() != PUBLISH_STATE_NOT_PUBLISHED) { // volte was not enabled. // or it is turnning off volte. lower layer should unpublish reset(); @@ -906,37 +899,35 @@ public class PresencePublication extends PresenceBase { TelephonyManager teleMgr = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); - if(teleMgr ==null) { - logger.debug("teleMgr=null"); + if (teleMgr == null) { + logger.error("TelephonyManager not available."); return; - } + } + Uri contactUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, teleMgr.getLine1Number(), null); - RcsPresenceInfo presenceInfo = new RcsPresenceInfo(teleMgr.getLine1Number(), - RcsPresenceInfo.VolteStatus.VOLTE_UNKNOWN, - publishRequest.getVolteCapable()?RcsPresenceInfo.ServiceState.ONLINE: - RcsPresenceInfo.ServiceState.OFFLINE, null, System.currentTimeMillis(), - publishRequest.getVtCapable()?RcsPresenceInfo.ServiceState.ONLINE: - RcsPresenceInfo.ServiceState.OFFLINE, null, - System.currentTimeMillis()); + RcsContactUceCapability.Builder presenceInfoBuilder = + new RcsContactUceCapability.Builder(contactUri); + if (publishRequest.getVolteCapable()) { + presenceInfoBuilder.add(RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL); + } + if (publishRequest.getVtCapable()) { + presenceInfoBuilder.add(RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL); + } synchronized(mSyncObj) { mPublishingRequest = publishRequest; mPublishingRequest.setTimestamp(System.currentTimeMillis()); } - int ret = mRcsStackAdaptor.requestPublication(presenceInfo, null); - if(ret == ResultCode.ERROR_SERVICE_NOT_AVAILABLE){ + int ret = mPresencePublisher.requestPublication(presenceInfoBuilder.build()); + if (ret == ResultCode.ERROR_SERVICE_NOT_AVAILABLE) { mHasCachedTrigger = true; - }else{ + } else { //reset the cached trigger mHasCachedTrigger = false; } } - public void handleCmdStatus(PresCmdStatus cmdStatus) { - super.handleCmdStatus(cmdStatus); - } - private PendingIntent mRetryAlarmIntent = null; public static final String ACTION_RETRY_PUBLISH_ALARM = "com.android.service.ims.presence.retry.publish"; @@ -959,7 +950,7 @@ public class PresencePublication extends PresenceBase { mCancelRetry = false; Intent intent = new Intent(ACTION_RETRY_PUBLISH_ALARM); - intent.setClass(mContext, AlarmBroadcastReceiver.class); + intent.setPackage(mContext.getPackageName()); mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); @@ -981,28 +972,23 @@ public class PresencePublication extends PresenceBase { return; } - invokePublish(PublishType.PRES_PUBLISH_TRIGGER_RETRY); + requestLocalPublish(PublishType.PRES_PUBLISH_TRIGGER_RETRY); } - public void handleSipResponse(PresSipResponse pSipResponse) { - logger.print( "Publish response code = " + pSipResponse.getSipResponseCode() - +"Publish response reason phrase = " + pSipResponse.getReasonPhrase()); + public void onSipResponse(int requestId, int responseCode, String reasonPhrase) { + logger.print( "Publish response code = " + responseCode + +"Publish response reason phrase = " + reasonPhrase); synchronized(mSyncObj) { mPublishedRequest = mPublishingRequest; mPublishingRequest = null; } - if(pSipResponse == null){ - logger.debug("handlePublishResponse pSipResponse = null"); - return; - } - int sipCode = pSipResponse.getSipResponseCode(); - if(isInConfigList(sipCode, pSipResponse.getReasonPhrase(), + if (isInConfigList(responseCode, reasonPhrase, mConfigVolteProvisionErrorOnPublishResponse)) { - logger.print("volte provision error. sipCode=" + sipCode + " phrase=" + - pSipResponse.getReasonPhrase()); - setPublishState(PublishState.PUBLISH_STATE_VOLTE_PROVISION_ERROR); + logger.print("volte provision error. sipCode=" + responseCode + " phrase=" + + reasonPhrase); + setPublishState(PUBLISH_STATE_VOLTE_PROVISION_ERROR); mDonotRetryUntilPowerCycle = true; notifyDm(); @@ -1010,49 +996,47 @@ public class PresencePublication extends PresenceBase { return; } - if(isInConfigList(sipCode, pSipResponse.getReasonPhrase(), - mConfigRcsProvisionErrorOnPublishResponse)) { - logger.print("rcs provision error.sipCode=" + sipCode + " phrase=" + - pSipResponse.getReasonPhrase()); - setPublishState(PublishState.PUBLISH_STATE_RCS_PROVISION_ERROR); + if (isInConfigList(responseCode, reasonPhrase, mConfigRcsProvisionErrorOnPublishResponse)) { + logger.print("rcs provision error.sipCode=" + responseCode + " phrase=" + reasonPhrase); + setPublishState(PUBLISH_STATE_RCS_PROVISION_ERROR); mDonotRetryUntilPowerCycle = true; return; } - switch (sipCode) { + switch (responseCode) { case 999: logger.debug("Publish ignored - No capability change"); break; case 200: - setPublishState(PublishState.PUBLISH_STATE_200_OK); + setPublishState(PUBLISH_STATE_200_OK); if(mSubscriber != null) { mSubscriber.retryToGetAvailability(); } break; case 408: - setPublishState(PublishState.PUBLISH_STATE_REQUEST_TIMEOUT); + setPublishState(PUBLISH_STATE_REQUEST_TIMEOUT); break; default: // Generic Failure - if ((sipCode < 100) || (sipCode > 699)) { - logger.debug("Ignore internal response code, sipCode=" + sipCode); + if ((responseCode < 100) || (responseCode > 699)) { + logger.debug("Ignore internal response code, sipCode=" + responseCode); // internal error // 0- PERMANENT ERROR: UI should not retry immediately // 888- TEMP ERROR: UI Can retry immediately // 999- NO CHANGE: No Publish needs to be sent - if(sipCode == 888) { + if(responseCode == 888) { // retry per 2 minutes scheduleRetryPublish(120000); } else { - logger.debug("Ignore internal response code, sipCode=" + sipCode); + logger.debug("Ignore internal response code, sipCode=" + responseCode); } } else { logger.debug( "Generic Failure"); - setPublishState(PublishState.PUBLISH_STATE_OTHER_ERROR); + setPublishState(PUBLISH_STATE_OTHER_ERROR); - if ((sipCode>=400) && (sipCode <= 699)) { + if ((responseCode>=400) && (responseCode <= 699)) { // 4xx/5xx/6xx, No retry, no impact on subsequent publish logger.debug( "No Retry in OEM"); } @@ -1061,11 +1045,10 @@ public class PresencePublication extends PresenceBase { } // Suppose the request ID had been set when IQPresListener_CMDStatus - Task task = TaskManager.getDefault().getTaskByRequestId( - pSipResponse.getRequestId()); + Task task = TaskManager.getDefault().getTaskByRequestId(requestId); if(task != null){ - task.mSipResponseCode = pSipResponse.getSipResponseCode(); - task.mSipReasonPhrase = pSipResponse.getReasonPhrase(); + task.mSipResponseCode = responseCode; + task.mSipReasonPhrase = reasonPhrase; } handleCallback(task, getPublishState(), false); @@ -1154,7 +1137,7 @@ public class PresencePublication extends PresenceBase { if(isOnIWLAN()) { // will check duplicated PUBLISH in requestPublication by invokePublish - invokePublish(PresencePublication.PublishType. + requestLocalPublish(PublishType. PRES_PUBLISH_TRIGGER_FEATURE_AVAILABILITY_CHANGED); } } else { diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublishTask.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublishTask.java index 73ae4ca..24d1ada 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublishTask.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublishTask.java @@ -28,23 +28,16 @@ package com.android.service.ims.presence; -import com.android.ims.internal.Logger; -import com.android.ims.IRcsPresenceListener; - /** * PresencePublishTask */ public class PresencePublishTask extends PresenceTask{ - /* - * The logger - */ - private Logger logger = Logger.getLogger(this.getClass().getName()); private long mCreateTimestamp = 0; private int mRetryCount = 0; - public PresencePublishTask(int taskId, int cmdId, IRcsPresenceListener listener, + public PresencePublishTask(int taskId, int cmdId, ContactCapabilityResponse listener, String[] contacts){ super(taskId, cmdId, listener, contacts); diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublisher.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublisher.java new file mode 100644 index 0000000..4b6eb89 --- /dev/null +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublisher.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of The Android Open Source Project nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +package com.android.service.ims.presence; + +import android.telephony.ims.RcsContactUceCapability; + +public interface PresencePublisher { + + /** + * Notify the stack of the last publish request result. + */ + @PresenceBase.PresencePublishState int getPublisherState(); + + /** + * Request that the specified capabilities are published to the network. + * @param capabilities The capabilities to publish. + * @return the result of requesting that the capabilities are published. + */ + int requestPublication(RcsContactUceCapability capabilities); + + /** + * Notify the stack of the last publish or subscribe request result. + */ + void updatePublisherState(@PresenceBase.PresencePublishState int publishState); +} diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java index ccd4cae..9a7e6f9 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java @@ -28,43 +28,24 @@ package com.android.service.ims.presence; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.telephony.TelephonyManager; +import android.telephony.ims.RcsContactUceCapability; import android.text.TextUtils; -import com.android.ims.IRcsPresenceListener; -import com.android.ims.RcsManager.ResultCode; -import com.android.ims.RcsPresence; -import com.android.ims.RcsPresence.PublishState; -import com.android.ims.RcsPresenceInfo; +import com.android.ims.ResultCode; import com.android.ims.internal.ContactNumberUtils; import com.android.ims.internal.Logger; -import com.android.ims.internal.uce.presence.PresCmdStatus; -import com.android.ims.internal.uce.presence.PresResInfo; -import com.android.ims.internal.uce.presence.PresRlmiInfo; -import com.android.ims.internal.uce.presence.PresSipResponse; -import com.android.ims.internal.uce.presence.PresSubscriptionState; -import com.android.ims.internal.uce.presence.PresTupleInfo; import com.android.service.ims.RcsSettingUtils; -import com.android.service.ims.RcsStackAdaptor; -import com.android.service.ims.RcsUtils; import com.android.service.ims.Task; import com.android.service.ims.TaskManager; - import java.util.ArrayList; import java.util.List; -public class PresenceSubscriber extends PresenceBase{ - /* - * The logger - */ +public class PresenceSubscriber extends PresenceBase { private Logger logger = Logger.getLogger(this.getClass().getName()); - private RcsStackAdaptor mRcsStackAdaptor = null; - - private static PresenceSubscriber sSubsriber = null; + private SubscribePublisher mSubscriber; private String mAvailabilityRetryNumber = null; @@ -74,11 +55,11 @@ public class PresenceSubscriber extends PresenceBase{ /* * Constructor */ - public PresenceSubscriber(RcsStackAdaptor rcsStackAdaptor, Context context, + public PresenceSubscriber(SubscribePublisher subscriber, Context context, String[] configVolteProvisionErrorOnSubscribeResponse, String[] configRcsProvisionErrorOnSubscribeResponse){ - mRcsStackAdaptor = rcsStackAdaptor; - mContext = context; + super(context); + mSubscriber = subscriber; mConfigVolteProvisionErrorOnSubscribeResponse = configVolteProvisionErrorOnSubscribeResponse; mConfigRcsProvisionErrorOnSubscribeResponse = configRcsProvisionErrorOnSubscribeResponse; @@ -111,10 +92,10 @@ public class PresenceSubscriber extends PresenceBase{ } public int requestCapability(List<String> contactsNumber, - IRcsPresenceListener listener){ + ContactCapabilityResponse listener) { - int ret = mRcsStackAdaptor.checkStackAndPublish(); - if(ret < ResultCode.SUCCESS){ + int ret = mSubscriber.getStackStatusForCapabilityRequest(); + if (ret < ResultCode.SUCCESS) { logger.error("requestCapability ret=" + ret); return ret; } @@ -132,10 +113,10 @@ public class PresenceSubscriber extends PresenceBase{ } String[] formatedNumbers = ContactNumberUtils.getDefault().format(contactsNumber); - ret = ContactNumberUtils.getDefault().validate(formatedNumbers); - if(ret != ContactNumberUtils.NUMBER_VALID){ - logger.error("requestCapability ret=" + ret); - return ret; + int formatResult = ContactNumberUtils.getDefault().validate(formatedNumbers); + if (formatResult != ContactNumberUtils.NUMBER_VALID) { + logger.error("requestCapability formatResult=" + formatResult); + return ResultCode.SUBSCRIBE_INVALID_PARAM; } String[] formatedContacts = new String[formatedNumbers.length]; @@ -153,13 +134,13 @@ public class PresenceSubscriber extends PresenceBase{ timeout += 3000; logger.print("add to task manager, formatedNumbers=" + - RcsUtils.toContactString(formatedNumbers)); + PresenceUtils.toContactString(formatedNumbers)); int taskId = TaskManager.getDefault().addCapabilityTask(mContext, formatedNumbers, listener, timeout); logger.print("taskId=" + taskId); - ret = mRcsStackAdaptor.requestCapability(formatedContacts, taskId); - if(ret < ResultCode.SUCCESS){ + ret = mSubscriber.requestCapability(formatedContacts, taskId); + if(ret < ResultCode.SUCCESS) { logger.error("requestCapability ret=" + ret + " remove taskId=" + taskId); TaskManager.getDefault().removeTask(taskId); } @@ -169,8 +150,8 @@ public class PresenceSubscriber extends PresenceBase{ return ret; } - public int requestAvailability(String contactNumber, IRcsPresenceListener listener, - boolean forceToNetwork){ + public int requestAvailability(String contactNumber, ContactCapabilityResponse listener, + boolean forceToNetwork) { String formatedContact = ContactNumberUtils.getDefault().format(contactNumber); int ret = ContactNumberUtils.getDefault().validate(formatedContact); @@ -212,8 +193,8 @@ public class PresenceSubscriber extends PresenceBase{ return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; } - ret = mRcsStackAdaptor.checkStackAndPublish(); - if(ret < ResultCode.SUCCESS){ + ret = mSubscriber.getStackStatusForCapabilityRequest(); + if (ret < ResultCode.SUCCESS) { logger.error("requestAvailability=" + ret); return ret; } @@ -226,19 +207,18 @@ public class PresenceSubscriber extends PresenceBase{ logger.print("addAvailabilityTask formatedContact=" + formatedContact); - ret = mRcsStackAdaptor.requestAvailability(formatedContact, taskId); - if(ret < ResultCode.SUCCESS){ + ret = mSubscriber.requestAvailability(formatedContact, taskId); + if (ret < ResultCode.SUCCESS) { logger.error("requestAvailability ret=" + ret + " remove taskId=" + taskId); TaskManager.getDefault().removeTask(taskId); } ret = taskId; - return ret; + return ret; } - private int translateResponse403(PresSipResponse pSipResponse){ - String reasonPhrase = pSipResponse.getReasonPhrase(); + private int translateResponse403(String reasonPhrase){ if(reasonPhrase == null){ // No retry. The PS provisioning has not occurred correctly. UX Decision to show errror. return ResultCode.SUBSCRIBE_GENIRIC_FAILURE; @@ -260,26 +240,24 @@ public class PresenceSubscriber extends PresenceBase{ return ResultCode.SUBSCRIBE_FORBIDDEN; } - private int translateResponseCode(PresSipResponse pSipResponse){ + private int translateResponseCode(int responseCode, String reasonPhrase) { // pSipResponse should not be null. - logger.debug("translateResponseCode getSipResponseCode=" + - pSipResponse.getSipResponseCode()); + logger.debug("translateResponseCode getSipResponseCode=" +responseCode); int ret = ResultCode.SUBSCRIBE_GENIRIC_FAILURE; - int sipCode = pSipResponse.getSipResponseCode(); - if(sipCode < 100 || sipCode > 699){ - logger.debug("internal error code sipCode=" + sipCode); + if(responseCode < 100 || responseCode > 699){ + logger.debug("internal error code sipCode=" + responseCode); ret = ResultCode.SUBSCRIBE_TEMPORARY_ERROR; //it is internal issue. ignore it. return ret; } - switch(sipCode){ + switch(responseCode){ case 200: ret = ResultCode.SUCCESS; break; case 403: - ret = translateResponse403(pSipResponse); + ret = translateResponse403(reasonPhrase); break; case 404: @@ -340,32 +318,26 @@ public class PresenceSubscriber extends PresenceBase{ return ret; } - public void handleSipResponse(PresSipResponse pSipResponse){ - if(pSipResponse == null){ - logger.debug("handleSipResponse pSipResponse = null"); - return; - } - - int sipCode = pSipResponse.getSipResponseCode(); - String phrase = pSipResponse.getReasonPhrase(); - if(isInConfigList(sipCode, phrase, mConfigVolteProvisionErrorOnSubscribeResponse)) { - logger.print("volte provision sipCode=" + sipCode + " phrase=" + phrase); - mRcsStackAdaptor.setPublishState(PublishState.PUBLISH_STATE_VOLTE_PROVISION_ERROR); + public void onSipResponse(int requestId, int responseCode, String reasonPhrase) { + if(isInConfigList(responseCode, reasonPhrase, + mConfigVolteProvisionErrorOnSubscribeResponse)) { + logger.print("volte provision sipCode=" + responseCode + " phrase=" + reasonPhrase); + mSubscriber.updatePublisherState(PUBLISH_STATE_VOLTE_PROVISION_ERROR); notifyDm(); - } else if(isInConfigList(sipCode, phrase, mConfigRcsProvisionErrorOnSubscribeResponse)) { - logger.print("rcs provision sipCode=" + sipCode + " phrase=" + phrase); - mRcsStackAdaptor.setPublishState(PublishState.PUBLISH_STATE_RCS_PROVISION_ERROR); + } else if(isInConfigList(responseCode, reasonPhrase, + mConfigRcsProvisionErrorOnSubscribeResponse)) { + logger.print("rcs proRcsPresence.vision sipCode=" + responseCode + " phrase=" + reasonPhrase); + mSubscriber.updatePublisherState(PUBLISH_STATE_RCS_PROVISION_ERROR); } - int errorCode = translateResponseCode(pSipResponse); + int errorCode = translateResponseCode(responseCode, reasonPhrase); logger.print("handleSipResponse errorCode=" + errorCode); if(errorCode == ResultCode.SUBSCRIBE_NOT_REGISTERED){ logger.debug("setPublishState to unknown" + " for subscribe error 403 not registered"); - mRcsStackAdaptor.setPublishState( - PublishState.PUBLISH_STATE_OTHER_ERROR); + mSubscriber.updatePublisherState(PUBLISH_STATE_OTHER_ERROR); } if(errorCode == ResultCode.SUBSCRIBE_NOT_AUTHORIZED_FOR_PRESENCE) { @@ -377,12 +349,11 @@ public class PresenceSubscriber extends PresenceBase{ } // Suppose the request ID had been set when IQPresListener_CMDStatus - Task task = TaskManager.getDefault().getTaskByRequestId( - pSipResponse.getRequestId()); + Task task = TaskManager.getDefault().getTaskByRequestId(requestId); logger.debug("handleSipResponse task=" + task); if(task != null){ - task.mSipResponseCode = sipCode; - task.mSipReasonPhrase = phrase; + task.mSipResponseCode = responseCode; + task.mSipReasonPhrase = reasonPhrase; TaskManager.getDefault().putTask(task.mTaskId, task); } @@ -400,27 +371,19 @@ public class PresenceSubscriber extends PresenceBase{ if(errorCode == ResultCode.SUBSCRIBE_NOT_FOUND && task != null && ((PresenceTask)task).mContacts != null) { String[] contacts = ((PresenceTask)task).mContacts; - ArrayList<RcsPresenceInfo> presenceInfoList = new ArrayList<RcsPresenceInfo>(); + ArrayList<RcsContactUceCapability> contactCapabilities = new ArrayList<>(); for(int i=0; i<contacts.length; i++){ if(TextUtils.isEmpty(contacts[i])){ continue; } - - RcsPresenceInfo presenceInfo = new RcsPresenceInfo(contacts[i], - RcsPresenceInfo.VolteStatus.VOLTE_DISABLED, - RcsPresenceInfo.ServiceState.OFFLINE, null, System.currentTimeMillis(), - RcsPresenceInfo.ServiceState.OFFLINE, null, System.currentTimeMillis()); - presenceInfoList.add(presenceInfo); + logger.debug("onSipResponse: contact= " + contacts[i] + ", not found."); + // Build contacts with no capabilities. + contactCapabilities.add(new RcsContactUceCapability.Builder( + PresenceUtils.convertContactNumber(contacts[i])).build()); } + handleCapabilityUpdate(task, contactCapabilities, true); - // Notify presence information changed. - logger.debug("notify presence changed for 404 error"); - Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED); - intent.putParcelableArrayListExtra(RcsPresence.EXTRA_PRESENCE_INFO_LIST, - presenceInfoList); - intent.putExtra("updateLastTimestamp", true); - launchPersistService(intent); } else if(errorCode == ResultCode.SUBSCRIBE_GENIRIC_FAILURE) { updateAvailabilityToUnknown(task); } @@ -428,11 +391,13 @@ public class PresenceSubscriber extends PresenceBase{ handleCallback(task, errorCode, false); } - private void launchPersistService(Intent intent) { - ComponentName component = new ComponentName("com.android.service.ims.presence", - "com.android.service.ims.presence.PersistService"); - intent.setComponent(component); - mContext.startService(intent); + private void handleCapabilityUpdate(Task task, List<RcsContactUceCapability> capabilities, + boolean updateLastTimestamp) { + if (task == null || task.mListener == null ) { + logger.warn("handleCapabilityUpdate, invalid listener!"); + return; + } + task.mListener.onCapabilitiesUpdated(capabilities, updateLastTimestamp); } public void retryToGetAvailability() { @@ -444,104 +409,52 @@ public class PresenceSubscriber extends PresenceBase{ mAvailabilityRetryNumber = null; } - public void updatePresence(String pPresentityUri, PresTupleInfo[] pTupleInfo){ + public void updatePresence(RcsContactUceCapability capabilities) { if(mContext == null){ logger.error("updatePresence mContext == null"); return; } - RcsPresenceInfo rcsPresenceInfo = PresenceInfoParser.getPresenceInfoFromTuple( - pPresentityUri, pTupleInfo); - if(rcsPresenceInfo == null || TextUtils.isEmpty( - rcsPresenceInfo.getContactNumber())){ - logger.error("rcsPresenceInfo is null or " + - "TextUtils.isEmpty(rcsPresenceInfo.getContactNumber()"); - return; - } - - ArrayList<RcsPresenceInfo> rcsPresenceInfoList = new ArrayList<RcsPresenceInfo>(); - rcsPresenceInfoList.add(rcsPresenceInfo); + ArrayList<RcsContactUceCapability> presenceInfos = new ArrayList<>(); + presenceInfos.add(capabilities); + String contactNumber = capabilities.getContactUri().getSchemeSpecificPart(); // For single contact number we got 1 NOTIFY only. So regard it as terminated. - TaskManager.getDefault().onTerminated(rcsPresenceInfo.getContactNumber()); + TaskManager.getDefault().onTerminated(contactNumber); PresenceAvailabilityTask availabilityTask = TaskManager.getDefault(). - getAvailabilityTaskByContact(rcsPresenceInfo.getContactNumber()); - if(availabilityTask != null){ + getAvailabilityTaskByContact(contactNumber); + if (availabilityTask != null) { availabilityTask.updateNotifyTimestamp(); } - - // Notify presence information changed. - Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED); - intent.putParcelableArrayListExtra(RcsPresence.EXTRA_PRESENCE_INFO_LIST, - rcsPresenceInfoList); - intent.putExtra("updateLastTimestamp", true); - launchPersistService(intent); + Task task = TaskManager.getDefault().getTaskForSingleContactQuery(contactNumber); + handleCapabilityUpdate(task, presenceInfos, true); } - public void updatePresences(PresRlmiInfo pRlmiInfo, PresResInfo[] pRcsPresenceInfo) { + public void updatePresences(int requestId, List<RcsContactUceCapability> contactsCapabilities, + boolean isTerminated, String terminatedReason) { if(mContext == null){ logger.error("updatePresences: mContext == null"); return; } - RcsPresenceInfo[] rcsPresenceInfos = PresenceInfoParser. - getPresenceInfosFromPresenceRes(pRlmiInfo, pRcsPresenceInfo); - if(rcsPresenceInfos == null){ - logger.error("updatePresences: rcsPresenceInfos == null"); - return; + if (isTerminated) { + TaskManager.getDefault().onTerminated(requestId, terminatedReason); } - ArrayList<RcsPresenceInfo> rcsPresenceInfoList = new ArrayList<RcsPresenceInfo>(); - - for (int i=0; i < rcsPresenceInfos.length; i++) { - RcsPresenceInfo rcsPresenceInfo = rcsPresenceInfos[i]; - if(rcsPresenceInfo != null && !TextUtils.isEmpty(rcsPresenceInfo.getContactNumber())){ - logger.debug("rcsPresenceInfo=" + rcsPresenceInfo); - - rcsPresenceInfoList.add(rcsPresenceInfo); - } - } - - boolean isTerminated = false; - if(pRlmiInfo.getPresSubscriptionState() != null){ - if(pRlmiInfo.getPresSubscriptionState().getPresSubscriptionStateValue() == - PresSubscriptionState.UCE_PRES_SUBSCRIPTION_STATE_TERMINATED){ - isTerminated = true; - } - } - - if(isTerminated){ - TaskManager.getDefault().onTerminated(pRlmiInfo.getRequestId(), - pRlmiInfo.getSubscriptionTerminatedReason()); - } - - if (rcsPresenceInfoList.size() > 0) { - // Notify presence changed - Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED); - intent.putParcelableArrayListExtra(RcsPresence.EXTRA_PRESENCE_INFO_LIST, - rcsPresenceInfoList); - logger.debug("broadcast ACTION_PRESENCE_CHANGED, rcsPresenceInfo=" + - rcsPresenceInfoList); - intent.putExtra("updateLastTimestamp", true); - launchPersistService(intent); + Task task = TaskManager.getDefault().getTaskByRequestId(requestId); + if (contactsCapabilities.size() > 0 || task != null) { + handleCapabilityUpdate(task, contactsCapabilities, true); } } - public void handleCmdStatus(PresCmdStatus pCmdStatus){ - if(pCmdStatus == null){ - logger.error("handleCallbackForCmdStatus pCmdStatus=null"); - return; - } - - - Task taskTmp = TaskManager.getDefault().getTask(pCmdStatus.getUserData()); - int resultCode = RcsUtils.statusCodeToResultCode(pCmdStatus.getStatus().getStatusCode()); + public void onCommandStatusUpdated(int taskId, int requestId, int resultCode) { + Task taskTmp = TaskManager.getDefault().getTask(taskId); logger.print("handleCmdStatus resultCode=" + resultCode); PresenceTask task = null; if(taskTmp != null && (taskTmp instanceof PresenceTask)){ task = (PresenceTask)taskTmp; - task.mSipRequestId = pCmdStatus.getRequestId(); + task.mSipRequestId = requestId; task.mCmdStatus = resultCode; TaskManager.getDefault().putTask(task.mTaskId, task); @@ -579,30 +492,18 @@ public class PresenceSubscriber extends PresenceBase{ return; } - ArrayList<RcsPresenceInfo> presenceInfoList = new ArrayList<RcsPresenceInfo>(); - for(int i = 0; i< task.mContacts.length; i++){ - if(task.mContacts[i] == null || task.mContacts[i].length() == 0){ + ArrayList<RcsContactUceCapability> presenceInfoList = new ArrayList<>(); + for (int i = 0; i< task.mContacts.length; i++) { + if(TextUtils.isEmpty(task.mContacts[i])){ continue; } - - RcsPresenceInfo presenceInfo = new RcsPresenceInfo( - PresenceInfoParser.getPhoneFromUri(task.mContacts[i]), - RcsPresenceInfo.VolteStatus.VOLTE_UNKNOWN, - RcsPresenceInfo.ServiceState.UNKNOWN, null, System.currentTimeMillis(), - RcsPresenceInfo.ServiceState.UNKNOWN, null, System.currentTimeMillis()); - presenceInfoList.add(presenceInfo); + // Add each contacts with no capabilities. + presenceInfoList.add(new RcsContactUceCapability.Builder( + PresenceUtils.convertContactNumber(task.mContacts[i])).build()); } if(presenceInfoList.size() > 0) { - // Notify presence information changed. - logger.debug("notify presence changed for cmd error"); - Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED); - intent.putParcelableArrayListExtra(RcsPresence.EXTRA_PRESENCE_INFO_LIST, - presenceInfoList); - - // don't update timestamp so it can be subscribed soon. - intent.putExtra("updateLastTimestamp", false); - launchPersistService(intent); + handleCapabilityUpdate(task, presenceInfoList, false); } } } diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceTask.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceTask.java index ed8afdf..5465e10 100644 --- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceTask.java +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceTask.java @@ -28,34 +28,28 @@ package com.android.service.ims.presence; -import com.android.ims.IRcsPresenceListener; -import com.android.ims.internal.Logger; -import com.android.service.ims.RcsUtils; import com.android.service.ims.Task; /** * PresenceTask */ -public class PresenceTask extends Task{ - /* - * The logger - */ - private Logger logger = Logger.getLogger(this.getClass().getName()); +public class PresenceTask extends Task { // filled before send the request to stack public String[] mContacts; - public PresenceTask(int taskId, int cmdId, IRcsPresenceListener listener, String[] contacts){ + public PresenceTask(int taskId, int cmdId, ContactCapabilityResponse listener, + String[] contacts){ super(taskId, cmdId, listener); mContacts = contacts; mListener = listener; } - public String toString(){ + public String toString() { return "PresenceTask: mTaskId=" + mTaskId + " mCmdId=" + mCmdId + - " mContacts=" + RcsUtils.toContactString(mContacts) + + " mContacts=" + PresenceUtils.toContactString(mContacts) + " mCmdStatus=" + mCmdStatus + " mSipRequestId=" + mSipRequestId + " mSipResponseCode=" + mSipResponseCode + diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceUtils.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceUtils.java new file mode 100644 index 0000000..088f52b --- /dev/null +++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceUtils.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of The Android Open Source Project nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +package com.android.service.ims.presence; + +import android.net.Uri; +import android.text.TextUtils; + +public class PresenceUtils { + + public static final String LOG_TAG_PREFIX = "rcs_lib"; + + private static final String TEL_SCHEME = "tel:"; + + public static String toContactString(String[] contacts) { + if(contacts == null) { + return null; + } + + String result = ""; + for(int i=0; i<contacts.length; i++) { + result += contacts[i]; + if(i != contacts.length -1) { + result += ";"; + } + } + + return result; + } + + public static Uri convertContactNumber(String number) { + if (TextUtils.isEmpty(number)) return null; + Uri possibleNumber = Uri.parse(number); + // already in the correct format + if (TEL_SCHEME.equals(possibleNumber.getScheme())) { + return possibleNumber; + } + // need to append tel scheme + return Uri.fromParts(TEL_SCHEME, number, null); + } + + public static String getNumber(Uri numberUri) { + if (numberUri == null) return null; + return numberUri.getSchemeSpecificPart(); + } +} diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/SubscribePublisher.java b/rcs/rcsservice/src/com/android/service/ims/presence/SubscribePublisher.java new file mode 100644 index 0000000..b3eb46d --- /dev/null +++ b/rcs/rcsservice/src/com/android/service/ims/presence/SubscribePublisher.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of The Android Open Source Project nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +package com.android.service.ims.presence; + +public interface SubscribePublisher { + + /** + * Request the Capabilities for the requested contacts associated with a taskId. + */ + int requestCapability(String[] formatedContacts, int taskId); + + /** + * Request the Capabilities for the requested contacts associated with a taskId. + */ + int requestAvailability(String formattedContact, int taskId); + + /** + * @return the current state of the RCS stack. + */ + int getStackStatusForCapabilityRequest(); + + /**== + * Notify the stack of the last publish or subscribe request result. + */ + void updatePublisherState(@PresenceBase.PresencePublishState int publishState); + +} |