1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.imsserviceentitlement.utils; 18 19 import android.content.Context; 20 import android.os.AsyncTask; 21 import android.os.PersistableBundle; 22 import android.telephony.CarrierConfigManager; 23 import android.telephony.ims.ImsMmTelManager; 24 import android.telephony.ims.ProvisioningManager; 25 import android.util.Log; 26 import android.util.SparseArray; 27 28 import androidx.annotation.GuardedBy; 29 import androidx.annotation.Nullable; 30 31 import com.google.common.annotations.VisibleForTesting; 32 33 /** A helper class for IMS relevant APIs with subscription id. */ 34 public class ImsUtils { 35 private static final String TAG = "IMSSE-ImsUtils"; 36 37 @Nullable private final PersistableBundle mCarrierConfigs; 38 private final ImsMmTelManager mImsMmTelManager; 39 private final ProvisioningManager mProvisioningManager; 40 41 /** 42 * Turns Volte provisioning status ON/OFF. 43 * Value is in Integer format. ON (1), OFF(0). 44 * Key is from {@link ProvisioningManager#KEY_VOLTE_PROVISIONING_STATUS}. 45 */ 46 private static final int KEY_VOLTE_PROVISIONING_STATUS = 10; 47 48 /** 49 * Turns SMS over IP ON/OFF on the device. 50 * Value is in Integer format. ON (1), OFF(0). 51 * Key is from {@link ProvisioningManager#KEY_SMS_OVER_IP_ENABLED}. 52 */ 53 private static final int KEY_SMS_OVER_IP_ENABLED = 14; 54 55 /** 56 * Enable voice over wifi on device. 57 * Value is in Integer format. Enabled (1), or Disabled (0). 58 * Key is from {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE}. 59 */ 60 private static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; 61 62 // Cache subscription id associated {@link ImsUtils} objects for reusing. 63 @GuardedBy("ImsUtils.class") 64 private static SparseArray<ImsUtils> sInstances = new SparseArray<ImsUtils>(); 65 ImsUtils(Context context, int subId)66 private ImsUtils(Context context, int subId) { 67 this( 68 context.getSystemService(CarrierConfigManager.class).getConfigForSubId(subId), 69 getImsMmTelManager(subId), 70 getProvisioningManager(subId)); 71 } 72 73 @VisibleForTesting ImsUtils( PersistableBundle carrierConfigs, ImsMmTelManager imsMmTelManager, ProvisioningManager provisioningManager)74 ImsUtils( 75 PersistableBundle carrierConfigs, 76 ImsMmTelManager imsMmTelManager, 77 ProvisioningManager provisioningManager) { 78 mCarrierConfigs = carrierConfigs; 79 mImsMmTelManager = imsMmTelManager; 80 mProvisioningManager = provisioningManager; 81 } 82 83 /** Returns {@link ImsUtils} instance. */ getInstance(Context context, int subId)84 public static synchronized ImsUtils getInstance(Context context, int subId) { 85 ImsUtils instance = sInstances.get(subId); 86 if (instance != null) { 87 return instance; 88 } 89 90 instance = new ImsUtils(context, subId); 91 sInstances.put(subId, instance); 92 return instance; 93 } 94 95 /** Changes persistent WFC enabled setting. */ setWfcSetting(boolean enabled)96 private void setWfcSetting(boolean enabled) { 97 try { 98 mImsMmTelManager.setVoWiFiSettingEnabled(enabled); 99 } catch (RuntimeException e) { 100 // ignore this exception, possible exception should be NullPointerException or 101 // RemoteException. 102 } 103 } 104 105 /** Sets whether VoWiFi is provisioned. */ setVowifiProvisioned(boolean value)106 public void setVowifiProvisioned(boolean value) { 107 try { 108 mProvisioningManager.setProvisioningIntValue( 109 KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, value 110 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 111 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 112 } catch (RuntimeException e) { 113 // ignore this exception, possible exception should be NullPointerException or 114 // RemoteException. 115 } 116 } 117 118 /** Sets whether Volte is provisioned. */ setVolteProvisioned(boolean value)119 public void setVolteProvisioned(boolean value) { 120 try { 121 mProvisioningManager.setProvisioningIntValue( 122 KEY_VOLTE_PROVISIONING_STATUS, value 123 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 124 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 125 } catch (RuntimeException e) { 126 // ignore this exception, possible exception should be NullPointerException or 127 // RemoteException. 128 } 129 } 130 131 /** Sets whether SMSoIP is provisioned. */ setSmsoipProvisioned(boolean value)132 public void setSmsoipProvisioned(boolean value) { 133 try { 134 mProvisioningManager.setProvisioningIntValue( 135 KEY_SMS_OVER_IP_ENABLED, value 136 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 137 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 138 } catch (RuntimeException e) { 139 // ignore this exception, possible exception should be NullPointerException or 140 // RemoteException. 141 } 142 } 143 144 /** Disables WFC and reset WFC mode to carrier default value */ 145 @VisibleForTesting disableAndResetVoWiFiImsSettings()146 void disableAndResetVoWiFiImsSettings() { 147 try { 148 disableWfc(); 149 150 // Reset WFC mode to carrier default value 151 if (mCarrierConfigs != null) { 152 mImsMmTelManager.setVoWiFiModeSetting( 153 mCarrierConfigs.getInt( 154 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); 155 mImsMmTelManager.setVoWiFiRoamingModeSetting( 156 mCarrierConfigs.getInt( 157 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); 158 } 159 } catch (RuntimeException e) { 160 // ignore this exception, possible exception should be NullPointerException or 161 // RemoteException. 162 } 163 } 164 165 /** 166 * Returns {@link ImsMmTelManager} with specific subscription id. 167 * Returns {@code null} if provided subscription id invalid. 168 */ 169 @Nullable getImsMmTelManager(int subId)170 private static ImsMmTelManager getImsMmTelManager(int subId) { 171 try { 172 return ImsMmTelManager.createForSubscriptionId(subId); 173 } catch (IllegalArgumentException e) { 174 Log.e(TAG, "Can't get ImsMmTelManager, IllegalArgumentException: subId = " + subId); 175 } 176 177 return null; 178 } 179 180 /** 181 * Returns {@link ProvisioningManager} with specific subscription id. 182 * Returns {@code null} if provided subscription id invalid. 183 */ 184 @Nullable getProvisioningManager(int subId)185 private static ProvisioningManager getProvisioningManager(int subId) { 186 try { 187 return ProvisioningManager.createForSubscriptionId(subId); 188 } catch (IllegalArgumentException e) { 189 Log.e(TAG, "Can't get ProvisioningManager, IllegalArgumentException: subId = " + subId); 190 } 191 return null; 192 } 193 194 /** Returns whether WFC is enabled by user for current subId */ isWfcEnabledByUser()195 public boolean isWfcEnabledByUser() { 196 try { 197 return mImsMmTelManager.isVoWiFiSettingEnabled(); 198 } catch (RuntimeException e) { 199 // ignore this exception, possible exception should be NullPointerException or 200 // RemoteException. 201 } 202 return false; 203 } 204 205 /** Calls {@link #disableAndResetVoWiFiImsSettings()} in background thread. */ turnOffWfc(Runnable action)206 public void turnOffWfc(Runnable action) { 207 new AsyncTask<Void, Void, Void>() { 208 @Override 209 protected Void doInBackground(Void... params) { 210 disableAndResetVoWiFiImsSettings(); 211 return null; // To satisfy compiler 212 } 213 214 @Override 215 protected void onPostExecute(Void result) { 216 action.run(); 217 } 218 }.execute(); 219 } 220 221 /** Disables WFC */ disableWfc()222 public void disableWfc() { 223 setWfcSetting(false); 224 } 225 } 226