• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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