1 /* 2 * Copyright (C) 2018 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.settings.wifi.calling; 18 19 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; 20 21 import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; 22 import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI; 23 import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_URI; 24 25 import android.app.PendingIntent; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.res.Resources; 30 import android.net.Uri; 31 import android.os.PersistableBundle; 32 import android.provider.Settings; 33 import android.telephony.CarrierConfigManager; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.ims.ImsMmTelManager; 36 import android.text.TextUtils; 37 import android.util.Log; 38 39 import androidx.annotation.VisibleForTesting; 40 import androidx.core.graphics.drawable.IconCompat; 41 import androidx.slice.Slice; 42 import androidx.slice.builders.ListBuilder; 43 import androidx.slice.builders.ListBuilder.RowBuilder; 44 import androidx.slice.builders.SliceAction; 45 46 import com.android.settings.R; 47 import com.android.settings.Utils; 48 import com.android.settings.network.ims.WifiCallingQueryImsState; 49 import com.android.settings.slices.SliceBroadcastReceiver; 50 51 import java.util.concurrent.Callable; 52 import java.util.concurrent.ExecutionException; 53 import java.util.concurrent.ExecutorService; 54 import java.util.concurrent.Executors; 55 import java.util.concurrent.FutureTask; 56 import java.util.concurrent.TimeUnit; 57 import java.util.concurrent.TimeoutException; 58 59 /** 60 * Helper class to control slices for wifi calling settings. 61 */ 62 public class WifiCallingSliceHelper { 63 64 private static final String TAG = "WifiCallingSliceHelper"; 65 66 /** 67 * Settings slice path to wifi calling setting. 68 */ 69 public static final String PATH_WIFI_CALLING = "wifi_calling"; 70 71 /** 72 * Settings slice path to wifi calling preference setting. 73 */ 74 public static final String PATH_WIFI_CALLING_PREFERENCE = 75 "wifi_calling_preference"; 76 77 /** 78 * Action passed for changes to wifi calling slice (toggle). 79 */ 80 public static final String ACTION_WIFI_CALLING_CHANGED = 81 "com.android.settings.wifi.calling.action.WIFI_CALLING_CHANGED"; 82 83 /** 84 * Action passed when user selects wifi only preference. 85 */ 86 public static final String ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY = 87 "com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_WIFI_ONLY"; 88 /** 89 * Action passed when user selects wifi preferred preference. 90 */ 91 public static final String ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED = 92 "com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_WIFI_PREFERRED"; 93 /** 94 * Action passed when user selects cellular preferred preference. 95 */ 96 public static final String ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED = 97 "com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED"; 98 99 /** 100 * Action for Wifi calling Settings activity which 101 * allows setting configuration for Wifi calling 102 * related settings 103 */ 104 public static final String ACTION_WIFI_CALLING_SETTINGS_ACTIVITY = 105 "android.settings.WIFI_CALLING_SETTINGS"; 106 107 /** 108 * Timeout for querying wifi calling setting from ims manager. 109 */ 110 private static final int TIMEOUT_MILLIS = 2000; 111 112 private final Context mContext; 113 114 @VisibleForTesting WifiCallingSliceHelper(Context context)115 public WifiCallingSliceHelper(Context context) { 116 mContext = context; 117 } 118 119 /** 120 * Returns Slice object for wifi calling settings. 121 * 122 * If wifi calling is being turned on and if wifi calling activation is needed for the current 123 * carrier, this method will return Slice with instructions to go to Settings App. 124 * 125 * If wifi calling is not supported for the current carrier, this method will return slice with 126 * not supported message. 127 * 128 * If wifi calling setting can be changed, this method will return the slice to toggle wifi 129 * calling option with ACTION_WIFI_CALLING_CHANGED as endItem. 130 */ createWifiCallingSlice(Uri sliceUri)131 public Slice createWifiCallingSlice(Uri sliceUri) { 132 final int subId = getDefaultVoiceSubId(); 133 134 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 135 Log.d(TAG, "Invalid subscription Id"); 136 return null; 137 } 138 139 if (!queryImsState(subId).isWifiCallingProvisioned()) { 140 Log.d(TAG, "Wifi calling is either not provisioned or not enabled by Platform"); 141 return null; 142 } 143 144 final boolean isWifiCallingEnabled = isWifiCallingEnabled(); 145 final Intent activationAppIntent = 146 getWifiCallingCarrierActivityIntent(subId); 147 148 // Send this actionable wifi calling slice to toggle the setting 149 // only when there is no need for wifi calling activation with the server 150 if (activationAppIntent != null && !isWifiCallingEnabled) { 151 Log.d(TAG, "Needs Activation"); 152 // Activation needed for the next action of the user 153 // Give instructions to go to settings app 154 final Resources res = getResourcesForSubId(subId); 155 return getNonActionableWifiCallingSlice( 156 res.getText(R.string.wifi_calling_settings_title), 157 res.getText(R.string.wifi_calling_settings_activation_instructions), 158 sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); 159 } 160 return getWifiCallingSlice(sliceUri, isWifiCallingEnabled, subId); 161 } 162 isWifiCallingEnabled()163 private boolean isWifiCallingEnabled() { 164 final WifiCallingQueryImsState queryState = queryImsState(getDefaultVoiceSubId()); 165 return queryState.isEnabledByUser() && queryState.isAllowUserControl(); 166 } 167 168 /** 169 * Builds a toggle slice where the intent takes you to the wifi calling page and the toggle 170 * enables/disables wifi calling. 171 */ getWifiCallingSlice(Uri sliceUri, boolean isWifiCallingEnabled, int subId)172 private Slice getWifiCallingSlice(Uri sliceUri, boolean isWifiCallingEnabled, int subId) { 173 final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); 174 final Resources res = getResourcesForSubId(subId); 175 176 return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) 177 .setAccentColor(Utils.getColorAccentDefaultColor(mContext)) 178 .addRow(new RowBuilder() 179 .setTitle(res.getText(R.string.wifi_calling_settings_title)) 180 .addEndItem( 181 SliceAction.createToggle( 182 getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED, 183 isWifiCallingEnabled), 184 null /* actionTitle */, isWifiCallingEnabled)) 185 .setPrimaryAction(SliceAction.createDeeplink( 186 getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), 187 icon, 188 ListBuilder.ICON_IMAGE, 189 res.getText(R.string.wifi_calling_settings_title)))) 190 .build(); 191 } 192 193 /** 194 * Returns Slice object for wifi calling preference. 195 * 196 * If wifi calling is not turned on, this method will return a slice to turn on wifi calling. 197 * 198 * If wifi calling preference is not user editable, this method will return a slice to display 199 * appropriate message. 200 * 201 * If wifi calling preference can be changed, this method will return a slice with 3 or 4 rows: 202 * Header Row: current preference settings 203 * Row 1: wifi only option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY, if wifi only option 204 * is editable 205 * Row 2: wifi preferred option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED 206 * Row 3: cellular preferred option with ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED 207 */ createWifiCallingPreferenceSlice(Uri sliceUri)208 public Slice createWifiCallingPreferenceSlice(Uri sliceUri) { 209 final int subId = getDefaultVoiceSubId(); 210 211 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 212 Log.d(TAG, "Invalid Subscription Id"); 213 return null; 214 } 215 216 final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled( 217 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false); 218 final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled( 219 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true); 220 221 if (!isWifiCallingPrefEditable) { 222 Log.d(TAG, "Wifi calling preference is not editable"); 223 return null; 224 } 225 226 if (!queryImsState(subId).isWifiCallingProvisioned()) { 227 Log.d(TAG, "Wifi calling is either not provisioned or not enabled by platform"); 228 return null; 229 } 230 231 boolean isWifiCallingEnabled = false; 232 int wfcMode = -1; 233 try { 234 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 235 isWifiCallingEnabled = isWifiCallingEnabled(); 236 wfcMode = getWfcMode(imsMmTelManager); 237 } catch (InterruptedException | ExecutionException | TimeoutException e) { 238 Log.e(TAG, "Unable to get wifi calling preferred mode", e); 239 return null; 240 } 241 if (!isWifiCallingEnabled) { 242 // wifi calling is not enabled. Ask user to enable wifi calling 243 final Resources res = getResourcesForSubId(subId); 244 return getNonActionableWifiCallingSlice( 245 res.getText(R.string.wifi_calling_mode_title), 246 res.getText(R.string.wifi_calling_turn_on), 247 sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); 248 } 249 // Return the slice to change wifi calling preference 250 return getWifiCallingPreferenceSlice( 251 isWifiOnlySupported, wfcMode, sliceUri, subId); 252 } 253 254 /** 255 * Returns actionable wifi calling preference slice. 256 * 257 * @param isWifiOnlySupported adds row for wifi only if this is true 258 * @param currentWfcPref current Preference {@link ImsConfig} 259 * @param sliceUri sliceUri 260 * @param subId subscription id 261 * @return Slice for actionable wifi calling preference settings 262 */ getWifiCallingPreferenceSlice(boolean isWifiOnlySupported, int currentWfcPref, Uri sliceUri, int subId)263 private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported, 264 int currentWfcPref, 265 Uri sliceUri, 266 int subId) { 267 final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); 268 final Resources res = getResourcesForSubId(subId); 269 // Top row shows information on current preference state 270 final ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) 271 .setAccentColor(Utils.getColorAccentDefaultColor(mContext)); 272 final ListBuilder.HeaderBuilder headerBuilder = new ListBuilder.HeaderBuilder() 273 .setTitle(res.getText(R.string.wifi_calling_mode_title)) 274 .setPrimaryAction(SliceAction.createDeeplink( 275 getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), 276 icon, 277 ListBuilder.ICON_IMAGE, 278 res.getText(R.string.wifi_calling_mode_title))); 279 if (!Utils.isSettingsIntelligence(mContext)) { 280 headerBuilder.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref, subId)); 281 } 282 listBuilder.setHeader(headerBuilder); 283 284 if (isWifiOnlySupported) { 285 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 286 com.android.internal.R.string.wfc_mode_wifi_only_summary, 287 ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY, 288 currentWfcPref == ImsMmTelManager.WIFI_MODE_WIFI_ONLY, subId)); 289 } 290 291 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 292 com.android.internal.R.string.wfc_mode_wifi_preferred_summary, 293 ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED, 294 currentWfcPref == ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED, subId)); 295 296 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 297 com.android.internal.R.string.wfc_mode_cellular_preferred_summary, 298 ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED, 299 currentWfcPref == ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED, subId)); 300 301 return listBuilder.build(); 302 } 303 304 /** 305 * Returns RowBuilder for a new row containing specific wifi calling preference. 306 * 307 * @param listBuilder ListBuilder that will be the parent for this RowBuilder 308 * @param preferenceTitleResId resource Id for the preference row title 309 * @param action action to be added for the row 310 * @param subId subscription id 311 * @return RowBuilder for the row 312 */ wifiPreferenceRowBuilder(ListBuilder listBuilder, int preferenceTitleResId, String action, boolean checked, int subId)313 private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder, 314 int preferenceTitleResId, String action, boolean checked, int subId) { 315 final IconCompat icon = 316 IconCompat.createWithResource(mContext, R.drawable.radio_button_check); 317 final Resources res = getResourcesForSubId(subId); 318 return new RowBuilder() 319 .setTitle(res.getText(preferenceTitleResId)) 320 .setTitleItem(SliceAction.createToggle(getBroadcastIntent(action, checked), 321 icon, res.getText(preferenceTitleResId), checked)); 322 } 323 324 325 /** 326 * Returns the String describing wifi calling preference mentioned in wfcMode 327 * 328 * @param wfcMode ImsConfig constant for the preference {@link ImsConfig} 329 * @return summary/name of the wifi calling preference 330 */ getWifiCallingPreferenceSummary(int wfcMode, int subId)331 private CharSequence getWifiCallingPreferenceSummary(int wfcMode, int subId) { 332 final Resources res = getResourcesForSubId(subId); 333 switch (wfcMode) { 334 case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: 335 return res.getText( 336 com.android.internal.R.string.wfc_mode_wifi_only_summary); 337 case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: 338 return res.getText( 339 com.android.internal.R.string.wfc_mode_wifi_preferred_summary); 340 case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: 341 return res.getText( 342 com.android.internal.R.string.wfc_mode_cellular_preferred_summary); 343 default: 344 return null; 345 } 346 } 347 getImsMmTelManager(int subId)348 protected ImsMmTelManager getImsMmTelManager(int subId) { 349 return ImsMmTelManager.createForSubscriptionId(subId); 350 } 351 getWfcMode(ImsMmTelManager imsMmTelManager)352 private int getWfcMode(ImsMmTelManager imsMmTelManager) 353 throws InterruptedException, ExecutionException, TimeoutException { 354 final FutureTask<Integer> wfcModeTask = new FutureTask<>(new Callable<Integer>() { 355 @Override 356 public Integer call() { 357 return imsMmTelManager.getVoWiFiModeSetting(); 358 } 359 }); 360 final ExecutorService executor = Executors.newSingleThreadExecutor(); 361 executor.execute(wfcModeTask); 362 return wfcModeTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 363 } 364 365 /** 366 * Handles wifi calling setting change from wifi calling slice and posts notification. Should be 367 * called when intent action is ACTION_WIFI_CALLING_CHANGED. Executed in @WorkerThread 368 * 369 * @param intent action performed 370 */ handleWifiCallingChanged(Intent intent)371 public void handleWifiCallingChanged(Intent intent) { 372 final int subId = getDefaultVoiceSubId(); 373 374 if (SubscriptionManager.isValidSubscriptionId(subId) 375 && intent.hasExtra(EXTRA_TOGGLE_STATE)) { 376 final WifiCallingQueryImsState queryState = queryImsState(subId); 377 if (queryState.isWifiCallingProvisioned()) { 378 final boolean currentValue = isWifiCallingEnabled(); 379 final boolean newValue = !(intent.getBooleanExtra(EXTRA_TOGGLE_STATE, 380 currentValue)); 381 final Intent activationAppIntent = 382 getWifiCallingCarrierActivityIntent(subId); 383 // 1. If activationApp is not null, users only can turn off WFC, or 384 // 2. Turn on/off directly if there is no activationApp. 385 if ((newValue != currentValue) && (activationAppIntent == null || !newValue)) { 386 // If either the action is to turn off wifi calling setting 387 // or there is no activation involved - Update the setting 388 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 389 imsMmTelManager.setVoWiFiSettingEnabled(newValue); 390 } else { 391 Log.w(TAG, "action not taken: subId " + subId 392 + " from " + currentValue + " to " + newValue); 393 } 394 } else { 395 Log.w(TAG, "action not taken: subId " + subId + " needs provision"); 396 } 397 } else { 398 Log.w(TAG, "action not taken: subId " + subId); 399 } 400 401 // notify change in slice in any case to get re-queried. This would result in displaying 402 // appropriate message with the updated setting. 403 mContext.getContentResolver().notifyChange(WIFI_CALLING_URI, null); 404 } 405 406 /** 407 * Handles wifi calling preference Setting change from wifi calling preference Slice and posts 408 * notification for the change. Should be called when intent action is one of the below 409 * ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY 410 * ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED 411 * ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED 412 * 413 * @param intent intent 414 */ handleWifiCallingPreferenceChanged(Intent intent)415 public void handleWifiCallingPreferenceChanged(Intent intent) { 416 final int subId = getDefaultVoiceSubId(); 417 final int errorValue = -1; 418 419 if (SubscriptionManager.isValidSubscriptionId(subId)) { 420 final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled( 421 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false); 422 final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled( 423 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true); 424 425 final WifiCallingQueryImsState queryState = queryImsState(subId); 426 if (isWifiCallingPrefEditable 427 && queryState.isWifiCallingProvisioned() 428 && queryState.isEnabledByUser() 429 && queryState.isAllowUserControl()) { 430 // Change the preference only when wifi calling is enabled 431 // And when wifi calling preference is editable for the current carrier 432 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 433 final int currentValue = imsMmTelManager.getVoWiFiModeSetting(); 434 int newValue = errorValue; 435 switch (intent.getAction()) { 436 case ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY: 437 if (isWifiOnlySupported) { 438 // change to wifi_only when wifi_only is enabled. 439 newValue = ImsMmTelManager.WIFI_MODE_WIFI_ONLY; 440 } 441 break; 442 case ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED: 443 newValue = ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED; 444 break; 445 case ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED: 446 newValue = ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED; 447 break; 448 } 449 if (newValue != errorValue && newValue != currentValue) { 450 // Update the setting only when there is a valid update 451 imsMmTelManager.setVoWiFiModeSetting(newValue); 452 } 453 } 454 } 455 456 // notify change in slice in any case to get re-queried. This would result in displaying 457 // appropriate message. 458 mContext.getContentResolver().notifyChange(WIFI_CALLING_PREFERENCE_URI, null); 459 } 460 461 /** 462 * Returns Slice with the title and subtitle provided as arguments with wifi signal Icon. 463 * 464 * @param title Title of the slice 465 * @param subtitle Subtitle of the slice 466 * @param sliceUri slice uri 467 * @return Slice with title and subtitle 468 */ getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle, Uri sliceUri, PendingIntent primaryActionIntent)469 private Slice getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle, 470 Uri sliceUri, PendingIntent primaryActionIntent) { 471 final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); 472 final RowBuilder rowBuilder = new RowBuilder() 473 .setTitle(title) 474 .setPrimaryAction(SliceAction.createDeeplink( 475 primaryActionIntent, icon, ListBuilder.SMALL_IMAGE, 476 title)); 477 if (!Utils.isSettingsIntelligence(mContext)) { 478 rowBuilder.setSubtitle(subtitle); 479 } 480 return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) 481 .setAccentColor(Utils.getColorAccentDefaultColor(mContext)) 482 .addRow(rowBuilder) 483 .build(); 484 } 485 486 /** 487 * Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise. 488 */ isCarrierConfigManagerKeyEnabled(String key, int subId, boolean defaultValue)489 protected boolean isCarrierConfigManagerKeyEnabled(String key, int subId, 490 boolean defaultValue) { 491 final CarrierConfigManager configManager = getCarrierConfigManager(mContext); 492 boolean ret = false; 493 if (configManager != null) { 494 final PersistableBundle bundle = configManager.getConfigForSubId(subId); 495 if (bundle != null) { 496 ret = bundle.getBoolean(key, defaultValue); 497 } 498 } 499 return ret; 500 } 501 getCarrierConfigManager(Context mContext)502 protected CarrierConfigManager getCarrierConfigManager(Context mContext) { 503 return mContext.getSystemService(CarrierConfigManager.class); 504 } 505 506 /** 507 * Returns the current default voice subId obtained from SubscriptionManager 508 */ getDefaultVoiceSubId()509 protected int getDefaultVoiceSubId() { 510 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 511 } 512 513 /** 514 * Returns Intent of the activation app required to activate wifi calling or null if there is no 515 * need for activation. 516 */ getWifiCallingCarrierActivityIntent(int subId)517 protected Intent getWifiCallingCarrierActivityIntent(int subId) { 518 final CarrierConfigManager configManager = getCarrierConfigManager(mContext); 519 if (configManager == null) { 520 return null; 521 } 522 523 final PersistableBundle bundle = configManager.getConfigForSubId(subId); 524 if (bundle == null) { 525 return null; 526 } 527 528 final String carrierApp = bundle.getString( 529 CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING); 530 if (TextUtils.isEmpty(carrierApp)) { 531 return null; 532 } 533 534 final ComponentName componentName = ComponentName.unflattenFromString(carrierApp); 535 if (componentName == null) { 536 return null; 537 } 538 539 final Intent intent = new Intent(); 540 intent.setComponent(componentName); 541 return intent; 542 } 543 544 /** 545 * @return {@link PendingIntent} to the Settings home page. 546 */ getSettingsIntent(Context context)547 public static PendingIntent getSettingsIntent(Context context) { 548 final Intent intent = new Intent(Settings.ACTION_SETTINGS); 549 return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 550 PendingIntent.FLAG_IMMUTABLE); 551 } 552 553 /** 554 * Create PendingIntent for Slice. 555 * Note: SliceAction#createDeeplink() didn't support toggle status so far, 556 * therefore, embedding toggle status within PendingIntent. 557 * 558 * @param action Slice action 559 * @param isChecked Status when Slice created. 560 * @return PendingIntent 561 */ getBroadcastIntent(String action, boolean isChecked)562 private PendingIntent getBroadcastIntent(String action, boolean isChecked) { 563 final Intent intent = new Intent(action); 564 intent.setClass(mContext, SliceBroadcastReceiver.class); 565 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 566 intent.putExtra(EXTRA_TOGGLE_STATE, isChecked); 567 return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, 568 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); 569 } 570 571 /** 572 * Returns PendingIntent to start activity specified by action 573 */ getActivityIntent(String action)574 private PendingIntent getActivityIntent(String action) { 575 final Intent intent = new Intent(action); 576 intent.setPackage(SETTINGS_PACKAGE_NAME); 577 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 578 return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 579 PendingIntent.FLAG_IMMUTABLE); 580 } 581 getResourcesForSubId(int subId)582 private Resources getResourcesForSubId(int subId) { 583 return SubscriptionManager.getResourcesForSubId(mContext, subId); 584 } 585 586 @VisibleForTesting queryImsState(int subId)587 WifiCallingQueryImsState queryImsState(int subId) { 588 return new WifiCallingQueryImsState(mContext, subId); 589 } 590 } 591