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, boolean force)86 public void setWfcSetting(boolean enabled, boolean force) { 87 try { 88 if (force) { 89 mImsMmTelManager.setVoWiFiSettingEnabled(enabled); 90 } 91 } catch (RuntimeException e) { 92 // ignore this exception, possible exception should be NullPointerException or 93 // RemoteException. 94 } 95 } 96 97 /** Sets whether VoWiFi is provisioned. */ setVowifiProvisioned(boolean value)98 public void setVowifiProvisioned(boolean value) { 99 try { 100 mProvisioningManager.setProvisioningIntValue( 101 KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, value 102 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 103 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 104 } catch (RuntimeException e) { 105 // ignore this exception, possible exception should be NullPointerException or 106 // RemoteException. 107 } 108 } 109 110 /** Sets whether Volte is provisioned. */ setVolteProvisioned(boolean value)111 public void setVolteProvisioned(boolean value) { 112 try { 113 mProvisioningManager.setProvisioningIntValue( 114 KEY_VOLTE_PROVISIONING_STATUS, value 115 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 116 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 117 } catch (RuntimeException e) { 118 // ignore this exception, possible exception should be NullPointerException or 119 // RemoteException. 120 } 121 } 122 123 /** Sets whether SMSoIP is provisioned. */ setSmsoipProvisioned(boolean value)124 public void setSmsoipProvisioned(boolean value) { 125 try { 126 mProvisioningManager.setProvisioningIntValue( 127 KEY_SMS_OVER_IP_ENABLED, value 128 ? ProvisioningManager.PROVISIONING_VALUE_ENABLED 129 : ProvisioningManager.PROVISIONING_VALUE_DISABLED); 130 } catch (RuntimeException e) { 131 // ignore this exception, possible exception should be NullPointerException or 132 // RemoteException. 133 } 134 } 135 136 /** Disables WFC and reset WFC mode to carrier default value */ disableAndResetVoWiFiImsSettings()137 public void disableAndResetVoWiFiImsSettings() { 138 try { 139 disableWfc(); 140 141 // Reset WFC mode to carrier default value 142 if (mCarrierConfigManager != null) { 143 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mSubId); 144 if (b != null) { 145 mImsMmTelManager.setVoWiFiModeSetting( 146 b.getInt(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); 147 mImsMmTelManager.setVoWiFiRoamingModeSetting( 148 b.getInt( 149 CarrierConfigManager 150 .KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT)); 151 } 152 } 153 } catch (RuntimeException e) { 154 // ignore this exception, possible exception should be NullPointerException or 155 // RemoteException. 156 } 157 } 158 159 /** 160 * Returns {@link ImsMmTelManager} with specific subscription id. 161 * Returns {@code null} if provided subscription id invalid. 162 */ 163 @Nullable getImsMmTelManager(Context context, int subId)164 public static ImsMmTelManager getImsMmTelManager(Context context, int subId) { 165 try { 166 return ImsMmTelManager.createForSubscriptionId(subId); 167 } catch (IllegalArgumentException e) { 168 Log.e(TAG, "Can't get ImsMmTelManager, IllegalArgumentException: subId = " + subId); 169 } 170 171 return null; 172 } 173 174 /** 175 * Returns {@link ProvisioningManager} with specific subscription id. 176 * Returns {@code null} if provided subscription id invalid. 177 */ 178 @Nullable getProvisioningManager(int subId)179 public static ProvisioningManager getProvisioningManager(int subId) { 180 try { 181 return ProvisioningManager.createForSubscriptionId(subId); 182 } catch (IllegalArgumentException e) { 183 Log.e(TAG, "Can't get ProvisioningManager, IllegalArgumentException: subId = " + subId); 184 } 185 return null; 186 } 187 188 /** Returns whether WFC is enabled by user for current subId */ isWfcEnabledByUser()189 public boolean isWfcEnabledByUser() { 190 try { 191 return mImsMmTelManager.isVoWiFiSettingEnabled(); 192 } catch (RuntimeException e) { 193 // ignore this exception, possible exception should be NullPointerException or 194 // RemoteException. 195 } 196 return false; 197 } 198 199 /** Calls {@link #disableAndResetVoWiFiImsSettings()} in background thread. */ turnOffWfc(ImsUtils imsUtils, Runnable action)200 public static void turnOffWfc(ImsUtils imsUtils, Runnable action) { 201 new AsyncTask<Void, Void, Void>() { 202 @Override 203 protected Void doInBackground(Void... params) { 204 imsUtils.disableAndResetVoWiFiImsSettings(); 205 return null; // To satisfy compiler 206 } 207 208 @Override 209 protected void onPostExecute(Void result) { 210 action.run(); 211 } 212 }.execute(); 213 } 214 215 /** Disables WFC */ disableWfc()216 public void disableWfc() { 217 setWfcSetting(false, false); 218 } 219 } 220