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 null /* actionTitle */, isWifiCallingEnabled)) 184 .setPrimaryAction(SliceAction.createDeeplink( 185 getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), 186 icon, 187 ListBuilder.ICON_IMAGE, 188 res.getText(R.string.wifi_calling_settings_title)))) 189 .build(); 190 } 191 192 /** 193 * Returns Slice object for wifi calling preference. 194 * 195 * If wifi calling is not turned on, this method will return a slice to turn on wifi calling. 196 * 197 * If wifi calling preference is not user editable, this method will return a slice to display 198 * appropriate message. 199 * 200 * If wifi calling preference can be changed, this method will return a slice with 3 or 4 rows: 201 * Header Row: current preference settings 202 * Row 1: wifi only option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY, if wifi only option 203 * is editable 204 * Row 2: wifi preferred option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED 205 * Row 3: cellular preferred option with ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED 206 */ createWifiCallingPreferenceSlice(Uri sliceUri)207 public Slice createWifiCallingPreferenceSlice(Uri sliceUri) { 208 final int subId = getDefaultVoiceSubId(); 209 210 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 211 Log.d(TAG, "Invalid Subscription Id"); 212 return null; 213 } 214 215 final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled( 216 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false); 217 final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled( 218 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true); 219 220 if (!isWifiCallingPrefEditable) { 221 Log.d(TAG, "Wifi calling preference is not editable"); 222 return null; 223 } 224 225 if (!queryImsState(subId).isWifiCallingProvisioned()) { 226 Log.d(TAG, "Wifi calling is either not provisioned or not enabled by platform"); 227 return null; 228 } 229 230 boolean isWifiCallingEnabled = false; 231 int wfcMode = -1; 232 try { 233 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 234 isWifiCallingEnabled = isWifiCallingEnabled(); 235 wfcMode = getWfcMode(imsMmTelManager); 236 } catch (InterruptedException | ExecutionException | TimeoutException e) { 237 Log.e(TAG, "Unable to get wifi calling preferred mode", e); 238 return null; 239 } 240 if (!isWifiCallingEnabled) { 241 // wifi calling is not enabled. Ask user to enable wifi calling 242 final Resources res = getResourcesForSubId(subId); 243 return getNonActionableWifiCallingSlice( 244 res.getText(R.string.wifi_calling_mode_title), 245 res.getText(R.string.wifi_calling_turn_on), 246 sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); 247 } 248 // Return the slice to change wifi calling preference 249 return getWifiCallingPreferenceSlice( 250 isWifiOnlySupported, wfcMode, sliceUri, subId); 251 } 252 253 /** 254 * Returns actionable wifi calling preference slice. 255 * 256 * @param isWifiOnlySupported adds row for wifi only if this is true 257 * @param currentWfcPref current Preference {@link ImsConfig} 258 * @param sliceUri sliceUri 259 * @param subId subscription id 260 * @return Slice for actionable wifi calling preference settings 261 */ getWifiCallingPreferenceSlice(boolean isWifiOnlySupported, int currentWfcPref, Uri sliceUri, int subId)262 private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported, 263 int currentWfcPref, 264 Uri sliceUri, 265 int subId) { 266 final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); 267 final Resources res = getResourcesForSubId(subId); 268 // Top row shows information on current preference state 269 final ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) 270 .setAccentColor(Utils.getColorAccentDefaultColor(mContext)); 271 final ListBuilder.HeaderBuilder headerBuilder = new ListBuilder.HeaderBuilder() 272 .setTitle(res.getText(R.string.wifi_calling_mode_title)) 273 .setPrimaryAction(SliceAction.createDeeplink( 274 getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), 275 icon, 276 ListBuilder.ICON_IMAGE, 277 res.getText(R.string.wifi_calling_mode_title))); 278 if (!Utils.isSettingsIntelligence(mContext)) { 279 headerBuilder.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref, subId)); 280 } 281 listBuilder.setHeader(headerBuilder); 282 283 if (isWifiOnlySupported) { 284 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 285 com.android.internal.R.string.wfc_mode_wifi_only_summary, 286 ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY, 287 currentWfcPref == ImsMmTelManager.WIFI_MODE_WIFI_ONLY, subId)); 288 } 289 290 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 291 com.android.internal.R.string.wfc_mode_wifi_preferred_summary, 292 ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED, 293 currentWfcPref == ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED, subId)); 294 295 listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, 296 com.android.internal.R.string.wfc_mode_cellular_preferred_summary, 297 ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED, 298 currentWfcPref == ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED, subId)); 299 300 return listBuilder.build(); 301 } 302 303 /** 304 * Returns RowBuilder for a new row containing specific wifi calling preference. 305 * 306 * @param listBuilder ListBuilder that will be the parent for this RowBuilder 307 * @param preferenceTitleResId resource Id for the preference row title 308 * @param action action to be added for the row 309 * @param subId subscription id 310 * @return RowBuilder for the row 311 */ wifiPreferenceRowBuilder(ListBuilder listBuilder, int preferenceTitleResId, String action, boolean checked, int subId)312 private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder, 313 int preferenceTitleResId, String action, boolean checked, int subId) { 314 final IconCompat icon = 315 IconCompat.createWithResource(mContext, R.drawable.radio_button_check); 316 final Resources res = getResourcesForSubId(subId); 317 return new RowBuilder() 318 .setTitle(res.getText(preferenceTitleResId)) 319 .setTitleItem(SliceAction.createToggle(getBroadcastIntent(action), 320 icon, res.getText(preferenceTitleResId), checked)); 321 } 322 323 324 /** 325 * Returns the String describing wifi calling preference mentioned in wfcMode 326 * 327 * @param wfcMode ImsConfig constant for the preference {@link ImsConfig} 328 * @return summary/name of the wifi calling preference 329 */ getWifiCallingPreferenceSummary(int wfcMode, int subId)330 private CharSequence getWifiCallingPreferenceSummary(int wfcMode, int subId) { 331 final Resources res = getResourcesForSubId(subId); 332 switch (wfcMode) { 333 case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: 334 return res.getText( 335 com.android.internal.R.string.wfc_mode_wifi_only_summary); 336 case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: 337 return res.getText( 338 com.android.internal.R.string.wfc_mode_wifi_preferred_summary); 339 case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: 340 return res.getText( 341 com.android.internal.R.string.wfc_mode_cellular_preferred_summary); 342 default: 343 return null; 344 } 345 } 346 getImsMmTelManager(int subId)347 protected ImsMmTelManager getImsMmTelManager(int subId) { 348 return ImsMmTelManager.createForSubscriptionId(subId); 349 } 350 getWfcMode(ImsMmTelManager imsMmTelManager)351 private int getWfcMode(ImsMmTelManager imsMmTelManager) 352 throws InterruptedException, ExecutionException, TimeoutException { 353 final FutureTask<Integer> wfcModeTask = new FutureTask<>(new Callable<Integer>() { 354 @Override 355 public Integer call() { 356 return imsMmTelManager.getVoWiFiModeSetting(); 357 } 358 }); 359 final ExecutorService executor = Executors.newSingleThreadExecutor(); 360 executor.execute(wfcModeTask); 361 return wfcModeTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 362 } 363 364 /** 365 * Handles wifi calling setting change from wifi calling slice and posts notification. Should be 366 * called when intent action is ACTION_WIFI_CALLING_CHANGED. Executed in @WorkerThread 367 * 368 * @param intent action performed 369 */ handleWifiCallingChanged(Intent intent)370 public void handleWifiCallingChanged(Intent intent) { 371 final int subId = getDefaultVoiceSubId(); 372 373 if (SubscriptionManager.isValidSubscriptionId(subId)) { 374 final WifiCallingQueryImsState queryState = queryImsState(subId); 375 if (queryState.isWifiCallingProvisioned()) { 376 final boolean currentValue = queryState.isEnabledByUser() 377 && queryState.isAllowUserControl(); 378 final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, 379 currentValue); 380 final Intent activationAppIntent = 381 getWifiCallingCarrierActivityIntent(subId); 382 if (!newValue || activationAppIntent == null) { 383 // If either the action is to turn off wifi calling setting 384 // or there is no activation involved - Update the setting 385 if (newValue != currentValue) { 386 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 387 imsMmTelManager.setVoWiFiSettingEnabled(newValue); 388 } 389 } 390 } 391 } 392 // notify change in slice in any case to get re-queried. This would result in displaying 393 // appropriate message with the updated setting. 394 mContext.getContentResolver().notifyChange(WIFI_CALLING_URI, null); 395 } 396 397 /** 398 * Handles wifi calling preference Setting change from wifi calling preference Slice and posts 399 * notification for the change. Should be called when intent action is one of the below 400 * ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY 401 * ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED 402 * ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED 403 * 404 * @param intent intent 405 */ handleWifiCallingPreferenceChanged(Intent intent)406 public void handleWifiCallingPreferenceChanged(Intent intent) { 407 final int subId = getDefaultVoiceSubId(); 408 final int errorValue = -1; 409 410 if (SubscriptionManager.isValidSubscriptionId(subId)) { 411 final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled( 412 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false); 413 final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled( 414 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true); 415 416 final WifiCallingQueryImsState queryState = queryImsState(subId); 417 if (isWifiCallingPrefEditable 418 && queryState.isWifiCallingProvisioned() 419 && queryState.isEnabledByUser() 420 && queryState.isAllowUserControl()) { 421 // Change the preference only when wifi calling is enabled 422 // And when wifi calling preference is editable for the current carrier 423 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId); 424 final int currentValue = imsMmTelManager.getVoWiFiModeSetting(); 425 int newValue = errorValue; 426 switch (intent.getAction()) { 427 case ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY: 428 if (isWifiOnlySupported) { 429 // change to wifi_only when wifi_only is enabled. 430 newValue = ImsMmTelManager.WIFI_MODE_WIFI_ONLY; 431 } 432 break; 433 case ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED: 434 newValue = ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED; 435 break; 436 case ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED: 437 newValue = ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED; 438 break; 439 } 440 if (newValue != errorValue && newValue != currentValue) { 441 // Update the setting only when there is a valid update 442 imsMmTelManager.setVoWiFiModeSetting(newValue); 443 } 444 } 445 } 446 447 // notify change in slice in any case to get re-queried. This would result in displaying 448 // appropriate message. 449 mContext.getContentResolver().notifyChange(WIFI_CALLING_PREFERENCE_URI, null); 450 } 451 452 /** 453 * Returns Slice with the title and subtitle provided as arguments with wifi signal Icon. 454 * 455 * @param title Title of the slice 456 * @param subtitle Subtitle of the slice 457 * @param sliceUri slice uri 458 * @return Slice with title and subtitle 459 */ getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle, Uri sliceUri, PendingIntent primaryActionIntent)460 private Slice getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle, 461 Uri sliceUri, PendingIntent primaryActionIntent) { 462 final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); 463 final RowBuilder rowBuilder = new RowBuilder() 464 .setTitle(title) 465 .setPrimaryAction(SliceAction.createDeeplink( 466 primaryActionIntent, icon, ListBuilder.SMALL_IMAGE, 467 title)); 468 if (!Utils.isSettingsIntelligence(mContext)) { 469 rowBuilder.setSubtitle(subtitle); 470 } 471 return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) 472 .setAccentColor(Utils.getColorAccentDefaultColor(mContext)) 473 .addRow(rowBuilder) 474 .build(); 475 } 476 477 /** 478 * Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise. 479 */ isCarrierConfigManagerKeyEnabled(String key, int subId, boolean defaultValue)480 protected boolean isCarrierConfigManagerKeyEnabled(String key, int subId, 481 boolean defaultValue) { 482 final CarrierConfigManager configManager = getCarrierConfigManager(mContext); 483 boolean ret = false; 484 if (configManager != null) { 485 final PersistableBundle bundle = configManager.getConfigForSubId(subId); 486 if (bundle != null) { 487 ret = bundle.getBoolean(key, defaultValue); 488 } 489 } 490 return ret; 491 } 492 getCarrierConfigManager(Context mContext)493 protected CarrierConfigManager getCarrierConfigManager(Context mContext) { 494 return mContext.getSystemService(CarrierConfigManager.class); 495 } 496 497 /** 498 * Returns the current default voice subId obtained from SubscriptionManager 499 */ getDefaultVoiceSubId()500 protected int getDefaultVoiceSubId() { 501 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 502 } 503 504 /** 505 * Returns Intent of the activation app required to activate wifi calling or null if there is no 506 * need for activation. 507 */ getWifiCallingCarrierActivityIntent(int subId)508 protected Intent getWifiCallingCarrierActivityIntent(int subId) { 509 final CarrierConfigManager configManager = getCarrierConfigManager(mContext); 510 if (configManager == null) { 511 return null; 512 } 513 514 final PersistableBundle bundle = configManager.getConfigForSubId(subId); 515 if (bundle == null) { 516 return null; 517 } 518 519 final String carrierApp = bundle.getString( 520 CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING); 521 if (TextUtils.isEmpty(carrierApp)) { 522 return null; 523 } 524 525 final ComponentName componentName = ComponentName.unflattenFromString(carrierApp); 526 if (componentName == null) { 527 return null; 528 } 529 530 final Intent intent = new Intent(); 531 intent.setComponent(componentName); 532 return intent; 533 } 534 535 /** 536 * @return {@link PendingIntent} to the Settings home page. 537 */ getSettingsIntent(Context context)538 public static PendingIntent getSettingsIntent(Context context) { 539 final Intent intent = new Intent(Settings.ACTION_SETTINGS); 540 return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 541 PendingIntent.FLAG_IMMUTABLE); 542 } 543 getBroadcastIntent(String action)544 private PendingIntent getBroadcastIntent(String action) { 545 final Intent intent = new Intent(action); 546 intent.setClass(mContext, SliceBroadcastReceiver.class); 547 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 548 return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, 549 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); 550 } 551 552 /** 553 * Returns PendingIntent to start activity specified by action 554 */ getActivityIntent(String action)555 private PendingIntent getActivityIntent(String action) { 556 final Intent intent = new Intent(action); 557 intent.setPackage(SETTINGS_PACKAGE_NAME); 558 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 559 return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 560 PendingIntent.FLAG_IMMUTABLE); 561 } 562 getResourcesForSubId(int subId)563 private Resources getResourcesForSubId(int subId) { 564 return SubscriptionManager.getResourcesForSubId(mContext, subId); 565 } 566 567 @VisibleForTesting queryImsState(int subId)568 WifiCallingQueryImsState queryImsState(int subId) { 569 return new WifiCallingQueryImsState(mContext, subId); 570 } 571 } 572