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 /** A helper class for IMS relevant APIs with subscription id. */ 32 public class ImsUtils { 33 private static final String TAG = "IMSSE-ImsUtils"; 34 35 private final CarrierConfigManager mCarrierConfigManager; 36 private final ImsMmTelManager mImsMmTelManager; 37 private final ProvisioningManager mProvisioningManager; 38 private final int mSubId; 39 40 /** 41 * Turns Volte provisioning status ON/OFF. 42 * Value is in Integer format. ON (1), OFF(0). 43 * Key is from {@link ProvisioningManager#KEY_VOLTE_PROVISIONING_STATUS}. 44 */ 45 private static final int KEY_VOLTE_PROVISIONING_STATUS = 10; 46 47 /** 48 * Turns SMS over IP ON/OFF on the device. 49 * Value is in Integer format. ON (1), OFF(0). 50 * Key is from {@link ProvisioningManager#KEY_SMS_OVER_IP_ENABLED}. 51 */ 52 private static final int KEY_SMS_OVER_IP_ENABLED = 14; 53 54 /** 55 * Enable voice over wifi on device. 56 * Value is in Integer format. Enabled (1), or Disabled (0). 57 * Key is from {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE}. 58 */ 59 private static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; 60 61 // Cache subscription id associated {@link ImsUtils} objects for reusing. 62 @GuardedBy("ImsUtils.class") 63 private static SparseArray<ImsUtils> sInstances = new SparseArray<ImsUtils>(); 64 ImsUtils(Context context, int subId)65 private ImsUtils(Context context, int subId) { 66 mCarrierConfigManager = 67 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 68 mImsMmTelManager = getImsMmTelManager(context, subId); 69 mProvisioningManager = getProvisioningManager(subId); 70 this.mSubId = subId; 71 } 72 73 /** Returns {@link ImsUtils} instance. */ getInstance(Context context, int subId)74 public static synchronized ImsUtils getInstance(Context context, int subId) { 75 ImsUtils instance = sInstances.get(subId); 76 if (instance != null) { 77 return instance; 78 } 79 80 instance = new ImsUtils(context, subId); 81 sInstances.put(subId, instance); 82 return instance; 83 } 84 85 /** Changes persistent WFC enabled setting. */ setWfcSetting(boolean enabled)86 public void setWfcSetting(boolean enabled) { 87 try { 88 mImsMmTelManager.setVoWiFiSettingEnabled(enabled); 89 } catch (RuntimeException e) { 90 // ignore this exception, possible exception should be NullPointerException or 91 // RemoteException. 92 } 93 } 94 95 /** Sets whether VoWiFi is provisioned. */ setVowifiProvisioned(boolean value)96 public void setVowifiProvisioned(boolean value) { 97 try { 98 mProvisioningManager.setProvisioningIntValue( 99 KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, value 100 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 101 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 102 } catch (RuntimeException e) { 103 // ignore this exception, possible exception should be NullPointerException or 104 // RemoteException. 105 } 106 } 107 108 /** Sets whether Volte is provisioned. */ setVolteProvisioned(boolean value)109 public void setVolteProvisioned(boolean value) { 110 try { 111 mProvisioningManager.setProvisioningIntValue( 112 KEY_VOLTE_PROVISIONING_STATUS, value 113 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 114 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 115 } catch (RuntimeException e) { 116 // ignore this exception, possible exception should be NullPointerException or 117 // RemoteException. 118 } 119 } 120 121 /** Sets whether SMSoIP is provisioned. */ setSmsoipProvisioned(boolean value)122 public void setSmsoipProvisioned(boolean value) { 123 try { 124 mProvisioningManager.setProvisioningIntValue( 125 KEY_SMS_OVER_IP_ENABLED, value 126 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 127 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 128 } catch (RuntimeException e) { 129 // ignore this exception, possible exception should be NullPointerException or 130 // RemoteException. 131 } 132 } 133 134 /** Disables WFC and reset WFC mode to carrier default value */ disableAndResetVoWiFiImsSettings()135 public void disableAndResetVoWiFiImsSettings() { 136 try { 137 disableWfc(); 138 139 // Reset WFC mode to carrier default value 140 if (mCarrierConfigManager != null) { 141 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mSubId); 142 if (b != null) { 143 mImsMmTelManager.setVoWiFiModeSetting( 144 b.getInt(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); 145 mImsMmTelManager.setVoWiFiRoamingModeSetting( 146 b.getInt( 147 CarrierConfigManager 148 .KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); 149 } 150 } 151 } catch (RuntimeException e) { 152 // ignore this exception, possible exception should be NullPointerException or 153 // RemoteException. 154 } 155 } 156 157 /** 158 * Returns {@link ImsMmTelManager} with specific subscription id. 159 * Returns {@code null} if provided subscription id invalid. 160 */ 161 @Nullable getImsMmTelManager(Context context, int subId)162 public static ImsMmTelManager getImsMmTelManager(Context context, int subId) { 163 try { 164 return ImsMmTelManager.createForSubscriptionId(subId); 165 } catch (IllegalArgumentException e) { 166 Log.e(TAG, "Can't get ImsMmTelManager, IllegalArgumentException: subId = " + subId); 167 } 168 169 return null; 170 } 171 172 /** 173 * Returns {@link ProvisioningManager} with specific subscription id. 174 * Returns {@code null} if provided subscription id invalid. 175 */ 176 @Nullable getProvisioningManager(int subId)177 public static ProvisioningManager getProvisioningManager(int subId) { 178 try { 179 return ProvisioningManager.createForSubscriptionId(subId); 180 } catch (IllegalArgumentException e) { 181 Log.e(TAG, "Can't get ProvisioningManager, IllegalArgumentException: subId = " + subId); 182 } 183 return null; 184 } 185 186 /** Returns whether WFC is enabled by user for current subId */ isWfcEnabledByUser()187 public boolean isWfcEnabledByUser() { 188 try { 189 return mImsMmTelManager.isVoWiFiSettingEnabled(); 190 } catch (RuntimeException e) { 191 // ignore this exception, possible exception should be NullPointerException or 192 // RemoteException. 193 } 194 return false; 195 } 196 197 /** Calls {@link #disableAndResetVoWiFiImsSettings()} in background thread. */ turnOffWfc(ImsUtils imsUtils, Runnable action)198 public static void turnOffWfc(ImsUtils imsUtils, Runnable action) { 199 new AsyncTask<Void, Void, Void>() { 200 @Override 201 protected Void doInBackground(Void... params) { 202 imsUtils.disableAndResetVoWiFiImsSettings(); 203 return null; // To satisfy compiler 204 } 205 206 @Override 207 protected void onPostExecute(Void result) { 208 action.run(); 209 } 210 }.execute(); 211 } 212 213 /** Disables WFC */ disableWfc()214 public void disableWfc() { 215 setWfcSetting(false); 216 } 217 } 218