/* * Copyright (c) 2015, Motorola Mobility LLC * 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 Motorola Mobility 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; import android.content.Context; import android.os.PersistableBundle; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.ims.ImsException; import android.telephony.ims.ImsManager; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsRcsManager; import android.telephony.ims.ProvisioningManager; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import com.android.ims.internal.Logger; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; public class RcsSettingUtils { static private Logger logger = Logger.getLogger("RcsSettingUtils"); private static final int TIMEOUT_GET_CONFIGURATION_MS = 5000; // Default number of entries for getMaxNumbersInRCL private static final int DEFAULT_NUM_ENTRIES_IN_RCL = 100; // Default for getCapabPollListSubExp in seconds. private static final int DEFAULT_CAPABILITY_POLL_LIST_SUB_EXPIRATION_SEC = 30; // Default for getAvailabilityCacheExpiration in seconds. private static final int DEFAULT_AVAILABILITY_CACHE_EXPIRATION_SEC = 30; // Default for getPublishThrottle in milliseconds private static final int DEFAULT_PUBLISH_THROTTLE_MS = 60000; public static boolean isVoLteProvisioned(int subId) { try { boolean isProvisioned; ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); isProvisioned = manager.getProvisioningStatusForCapability( MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, ImsRegistrationImplBase.REGISTRATION_TECH_LTE); logger.debug("isVoLteProvisioned=" + isProvisioned); return isProvisioned; } catch (Exception e) { logger.debug("isVoLteProvisioned, exception = " + e.getMessage()); return false; } } public static boolean isVowifiProvisioned(int subId) { try { boolean isProvisioned; ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); 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 isLvcProvisioned(int subId) { try { boolean isProvisioned; ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); 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, int subId) { boolean isProvisioned = false; if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { logger.debug("isEabProvisioned: no valid subscriptions!"); return false; } CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager != null) { 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; } } try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); isProvisioned = manager.getProvisioningIntValue( ProvisioningManager.KEY_EAB_PROVISIONING_STATUS) == ProvisioningManager.PROVISIONING_VALUE_ENABLED; } catch (Exception e) { logger.debug("isEabProvisioned: exception=" + e.getMessage()); } logger.debug("isEabProvisioned=" + isProvisioned); return isProvisioned; } public static boolean hasUserEnabledContactDiscovery(Context context, int subId) { if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { logger.debug("hasUserEnabledContactDiscovery: no valid subscriptions!"); return false; } try { ImsManager imsManager = context.getSystemService(ImsManager.class); ImsRcsManager rcsManager = imsManager.getImsRcsManager(subId); return rcsManager.getUceAdapter().isUceSettingEnabled(); } catch (Exception e) { logger.warn("hasUserEnabledContactDiscovery: Exception = " + e.getMessage()); return false; } } public static int getSIPT1Timer(int subId) { int sipT1Timer = 0; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); sipT1Timer = manager.getProvisioningIntValue(ProvisioningManager.KEY_T1_TIMER_VALUE_MS); } catch (Exception e) { // If there is no active subscriptions, this will throw an exception. logger.debug("getSIPT1Timer: exception=" + e.getMessage()); } logger.debug("getSIPT1Timer=" + sipT1Timer); return sipT1Timer; } /** * Capability discovery status of Enabled (1), or Disabled (0). */ public static boolean getCapabilityDiscoveryEnabled(int subId) { boolean capabilityDiscoveryEnabled = false; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); capabilityDiscoveryEnabled = manager.getProvisioningIntValue( ProvisioningManager.KEY_RCS_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; } /** * The Maximum number of MDNs contained in one Request Contained List. */ public static int getMaxNumbersInRCL(int subId) { int maxNumbersInRCL = DEFAULT_NUM_ENTRIES_IN_RCL; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); maxNumbersInRCL = manager.getProvisioningIntValue( ProvisioningManager.KEY_RCS_MAX_NUM_ENTRIES_IN_RCL); } catch (Exception e) { // If there is no active subscriptions, this will throw an exception. logger.debug("getMaxNumbersInRCL: exception=" + e.getMessage()); } logger.debug("getMaxNumbersInRCL=" + maxNumbersInRCL); return maxNumbersInRCL; } /** * Expiration timer for subscription of a Request Contained List, used in capability polling. */ public static int getCapabPollListSubExp(int subId) { int capabPollListSubExp = DEFAULT_CAPABILITY_POLL_LIST_SUB_EXPIRATION_SEC; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); capabPollListSubExp = manager.getProvisioningIntValue( ProvisioningManager.KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC); } catch (Exception e) { // If there is no active subscriptions, this will throw an exception. logger.debug("getCapabPollListSubExp: exception=" + e.getMessage()); } logger.debug("getCapabPollListSubExp=" + capabPollListSubExp); return capabPollListSubExp; } /** * Period of time the availability information of a contact is cached on device. */ public static int getAvailabilityCacheExpiration(int subId) { int availabilityCacheExpiration = DEFAULT_AVAILABILITY_CACHE_EXPIRATION_SEC; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); availabilityCacheExpiration = manager.getProvisioningIntValue( ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC); } catch (Exception e) { // If there is no active subscriptions, this will throw an exception. logger.debug("getAvailabilityCacheExpiration: exception=" + e.getMessage()); } logger.debug("getAvailabilityCacheExpiration=" + availabilityCacheExpiration); return availabilityCacheExpiration; } public static int getPublishThrottle(int subId) { // Default int publishThrottle = DEFAULT_PUBLISH_THROTTLE_MS; try { ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId); publishThrottle = manager.getProvisioningIntValue( ProvisioningManager.KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS); } 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; } public static boolean isVtEnabledByUser(int subId) { try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); return mmTelManager.isVtSettingEnabled(); } catch (Exception e) { logger.warn("isVtEnabledByUser exception = " + e.getMessage()); return false; } } public static boolean isWfcEnabledByUser(int subId) { try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); return mmTelManager.isVoWiFiSettingEnabled(); } catch (Exception e) { logger.warn("isWfcEnabledByUser exception = " + e.getMessage()); return false; } } public static boolean isAdvancedCallingEnabledByUser(int subId) { try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); return mmTelManager.isAdvancedCallingSettingEnabled(); } catch (Exception e) { logger.warn("isAdvancedCallingEnabledByUser exception = " + e.getMessage()); return false; } } public static boolean isVoLteSupported(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { return false; } LinkedBlockingQueue resultQueue = new LinkedBlockingQueue<>(1); try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); mmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Runnable::run, resultQueue::offer); } catch (ImsException e) { logger.warn("isVoLteSupported: ImsException = " + e.getMessage()); return false; } try { Boolean result = resultQueue.poll(TIMEOUT_GET_CONFIGURATION_MS, TimeUnit.MILLISECONDS); return (result != null) ? result : false; } catch (InterruptedException e) { logger.warn("isVoLteSupported, InterruptedException=" + e.getMessage()); return false; } } public static boolean isVoWiFiSupported(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { return false; } LinkedBlockingQueue resultQueue = new LinkedBlockingQueue<>(1); try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); mmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, Runnable::run, resultQueue::offer); } catch (ImsException e) { logger.warn("isVoWiFiSupported: ImsException = " + e.getMessage()); return false; } try { Boolean result = resultQueue.poll(TIMEOUT_GET_CONFIGURATION_MS, TimeUnit.MILLISECONDS); return (result != null) ? result : false; } catch (InterruptedException e) { logger.warn("isVoWiFiSupported, InterruptedException=" + e.getMessage()); return false; } } public static boolean isVtSupported(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { return false; } LinkedBlockingQueue resultQueue = new LinkedBlockingQueue<>(1); try { ImsMmTelManager mmTelManager = ImsMmTelManager.createForSubscriptionId(subId); mmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Runnable::run, resultQueue::offer); } catch (ImsException e) { logger.warn("isVoWiFiSupported: ImsException = " + e.getMessage()); return false; } try { Boolean result = resultQueue.poll(TIMEOUT_GET_CONFIGURATION_MS, TimeUnit.MILLISECONDS); return (result != null) ? result : false; } catch (InterruptedException e) { logger.warn("isVtSupported, InterruptedException=" + e.getMessage()); return false; } } public static int getDefaultSubscriptionId(Context context) { SubscriptionManager sm = context.getSystemService(SubscriptionManager.class); if (sm == null) return SubscriptionManager.INVALID_SUBSCRIPTION_ID; List 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 // voice subscription that the user chose. int defaultSub = SubscriptionManager.getDefaultVoiceSubscriptionId(); if (!SubscriptionManager.isValidSubscriptionId(defaultSub)) { // The voice sub may not have been specified, in this case, use the default data. defaultSub = SubscriptionManager.getDefaultDataSubscriptionId(); } // If the user has no default set, just pick the first as backup. if (!SubscriptionManager.isValidSubscriptionId(defaultSub)) { for (SubscriptionInfo info : infos) { if (!info.isOpportunistic()) { defaultSub = info.getSubscriptionId(); break; } } } return defaultSub; } }