Add Wifi calling Preference slice and other cleanup

WifiCallingPreference Slice Provider:
  1. If Wifi calling is not enabled - display message to user
     to enable Wifi calling
  2. Else if Wifi preference is not editable - return a null
     Slice
  3. Else provide a slice with rows - first row giving current pref
     information, followed by preference items (in each row).
     wifi_only is displayed only when it is allowed to display it.
     Each row with preference item has specific intent action.
WifiCallingPreference Slice BroadcastReceiver:
   1. If only Wifi calling is enabled & Wifi preference is editable &
      there is a change in current value modify wifi pref setting
   2. And Ask to re-query the slice in one second to display
      updated settings if 1 is valid or display appropriate message.
Clean-up:
   1. Return null instead of non-actionable slices.
   2. Use getText to get string resources.
   3. Remove unnecessary extra variables.

Bug: 79548264
Test: Use support-slices-demos-debug.apk to test on device
Change-Id: I186f19be2007c2331eaf6195e70b4a9c635adf9e
This commit is contained in:
Naina Nalluri
2018-05-21 11:53:24 -07:00
parent 606222da7f
commit 6b1869351a
7 changed files with 552 additions and 91 deletions

View File

@@ -211,6 +211,11 @@ public class SettingsSliceProvider extends SliceProvider {
.getSlicesFeatureProvider()
.getNewEnhanced4gLteSliceHelper(getContext())
.createEnhanced4gLteSlice(sliceUri);
} else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingPreferenceSlice(sliceUri);
}
SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);

View File

@@ -25,6 +25,9 @@ import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLAT
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED;
import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED;
import static com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED;
import android.app.slice.Slice;
import android.content.BroadcastReceiver;
@@ -91,6 +94,14 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
.getNewEnhanced4gLteSliceHelper(context)
.handleEnhanced4gLteChanged(intent);
break;
case ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY:
case ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED:
case ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED:
FeatureFactory.getFactory(context)
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(context)
.handleWifiCallingPreferenceChanged(intent);
break;
default:
final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
if (!TextUtils.isEmpty(uriString)) {

View File

@@ -35,11 +35,14 @@ import android.util.Log;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -65,12 +68,34 @@ public class WifiCallingSliceHelper {
*/
public static final String PATH_WIFI_CALLING = "wifi_calling";
/**
* Settings slice path to wifi calling preference setting.
*/
public static final String PATH_WIFI_CALLING_PREFERENCE =
"wifi_calling_preference";
/**
* Action passed for changes to wifi calling slice (toggle).
*/
public static final String ACTION_WIFI_CALLING_CHANGED =
"com.android.settings.wifi.calling.action.WIFI_CALLING_CHANGED";
/**
* Action passed when user selects wifi only preference.
*/
public static final String ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY =
"com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_WIFI_ONLY";
/**
* Action passed when user selects wifi preferred preference.
*/
public static final String ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED =
"com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_WIFI_PREFERRED";
/**
* Action passed when user selects cellular preferred preference.
*/
public static final String ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED =
"com.android.settings.slice.action.WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED";
/**
* Action for Wifi calling Settings activity which
* allows setting configuration for Wifi calling
@@ -88,12 +113,20 @@ public class WifiCallingSliceHelper {
.appendPath(PATH_WIFI_CALLING)
.build();
/**
* Full {@link Uri} for the Wifi Calling Preference Slice.
*/
public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_WIFI_CALLING_PREFERENCE)
.build();
/**
* Timeout for querying wifi calling setting from ims manager.
*/
private static final int TIMEOUT_MILLIS = 2000;
protected SubscriptionManager mSubscriptionManager;
private final Context mContext;
@VisibleForTesting
@@ -115,14 +148,10 @@ public class WifiCallingSliceHelper {
*/
public Slice createWifiCallingSlice(Uri sliceUri) {
final int subId = getDefaultVoiceSubId();
final String carrierName = getSimCarrierName();
if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(TAG, "Invalid subscription Id");
return getNonActionableWifiCallingSlice(
mContext.getString(R.string.wifi_calling_settings_title),
mContext.getString(R.string.wifi_calling_not_supported, carrierName),
sliceUri, getSettingsIntent(mContext));
return null;
}
final ImsManager imsManager = getImsManager(subId);
@@ -130,10 +159,7 @@ public class WifiCallingSliceHelper {
if (!imsManager.isWfcEnabledByPlatform()
|| !imsManager.isWfcProvisionedOnDevice()) {
Log.d(TAG, "Wifi calling is either not provisioned or not enabled by Platform");
return getNonActionableWifiCallingSlice(
mContext.getString(R.string.wifi_calling_settings_title),
mContext.getString(R.string.wifi_calling_not_supported, carrierName),
sliceUri, getSettingsIntent(mContext));
return null;
}
try {
@@ -148,18 +174,15 @@ public class WifiCallingSliceHelper {
// Activation needed for the next action of the user
// Give instructions to go to settings app
return getNonActionableWifiCallingSlice(
mContext.getString(R.string.wifi_calling_settings_title),
mContext.getString(
mContext.getText(R.string.wifi_calling_settings_title),
mContext.getText(
R.string.wifi_calling_settings_activation_instructions),
sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
}
return getWifiCallingSlice(sliceUri, mContext, isWifiCallingEnabled);
return getWifiCallingSlice(sliceUri, isWifiCallingEnabled);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
Log.e(TAG, "Unable to read the current WiFi calling status", e);
return getNonActionableWifiCallingSlice(
mContext.getString(R.string.wifi_calling_settings_title),
mContext.getString(R.string.wifi_calling_turn_on),
sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
return null;
}
}
@@ -174,25 +197,21 @@ public class WifiCallingSliceHelper {
final ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(isWifiOnTask);
Boolean isWifiEnabledByUser = false;
isWifiEnabledByUser = isWifiOnTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return isWifiEnabledByUser && imsManager.isNonTtyOrTtyOnVolteEnabled();
return isWifiOnTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
&& imsManager.isNonTtyOrTtyOnVolteEnabled();
}
/**
* Builds a toggle slice where the intent takes you to the wifi calling page and the toggle
* enables/disables wifi calling.
*/
private Slice getWifiCallingSlice(Uri sliceUri, Context mContext,
boolean isWifiCallingEnabled) {
private Slice getWifiCallingSlice(Uri sliceUri, boolean isWifiCallingEnabled) {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
final String title = mContext.getString(R.string.wifi_calling_settings_title);
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setColor(R.color.material_blue_500)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(b -> b
.setTitle(title)
.setTitle(mContext.getText(R.string.wifi_calling_settings_title))
.addEndItem(
new SliceAction(
getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED),
@@ -200,15 +219,160 @@ public class WifiCallingSliceHelper {
.setPrimaryAction(new SliceAction(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
title)))
mContext.getText(R.string.wifi_calling_settings_title))))
.build();
}
/**
* Returns Slice object for wifi calling preference.
*
* If wifi calling is not turned on, this method will return a slice to turn on wifi calling.
*
* If wifi calling preference is not user editable, this method will return a slice to display
* appropriate message.
*
* If wifi calling preference can be changed, this method will return a slice with 3 or 4 rows:
* Header Row: current preference settings
* Row 1: wifi only option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY, if wifi only option
* is editable
* Row 2: wifi preferred option with ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED
* Row 3: cellular preferred option with ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED
*/
public Slice createWifiCallingPreferenceSlice(Uri sliceUri) {
final int subId = getDefaultVoiceSubId();
if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(TAG, "Invalid Subscription Id");
return null;
}
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
final ImsManager imsManager = getImsManager(subId);
if (!imsManager.isWfcEnabledByPlatform()
|| !imsManager.isWfcProvisionedOnDevice()) {
Log.d(TAG, "Wifi calling is either not provisioned or not enabled by platform");
return null;
}
if (!isWifiCallingPrefEditable) {
Log.d(TAG, "Wifi calling preference is not editable");
return null;
}
boolean isWifiCallingEnabled = false;
int wfcMode = -1;
try {
isWifiCallingEnabled = isWifiCallingEnabled(imsManager);
wfcMode = getWfcMode(imsManager);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.e(TAG, "Unable to get wifi calling preferred mode", e);
return null;
}
if (!isWifiCallingEnabled) {
// wifi calling is not enabled. Ask user to enable wifi calling
return getNonActionableWifiCallingSlice(
mContext.getText(R.string.wifi_calling_mode_title),
mContext.getText(R.string.wifi_calling_turn_on),
sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
}
// Return the slice to change wifi calling preference
return getWifiCallingPreferenceSlice(
isWifiOnlySupported, wfcMode, sliceUri);
}
/**
* Returns actionable wifi calling preference slice.
*
* @param isWifiOnlySupported adds row for wifi only if this is true
* @param currentWfcPref current Preference {@link ImsConfig}
* @param sliceUri sliceUri
* @return Slice for actionable wifi calling preference settings
*/
private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported,
int currentWfcPref,
Uri sliceUri) {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
// Top row shows information on current preference state
ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
listBuilder.setHeader(new ListBuilder.HeaderBuilder(listBuilder)
.setTitle(mContext.getText(R.string.wifi_calling_mode_title))
.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
.setPrimaryAction(new SliceAction(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
mContext.getText(R.string.wifi_calling_mode_title))));
if (isWifiOnlySupported) {
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
com.android.internal.R.string.wfc_mode_wifi_only_summary,
ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY,
currentWfcPref == ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY));
}
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
com.android.internal.R.string.wfc_mode_wifi_preferred_summary,
ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED,
currentWfcPref == ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED));
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
com.android.internal.R.string.wfc_mode_cellular_preferred_summary,
ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED,
currentWfcPref == ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED));
return listBuilder.build();
}
/**
* Returns RowBuilder for a new row containing specific wifi calling preference.
*
* @param listBuilder ListBuilder that will be the parent for this RowBuilder
* @param preferenceTitleResId resource Id for the preference row title
* @param action action to be added for the row
* @return RowBuilder for the row
*/
private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder,
int preferenceTitleResId, String action, boolean checked) {
final IconCompat icon =
IconCompat.createWithResource(mContext, R.drawable.radio_button_check);
return new RowBuilder(listBuilder)
.setTitle(mContext.getText(preferenceTitleResId))
.setTitleItem(new SliceAction(getBroadcastIntent(action),
icon, mContext.getText(preferenceTitleResId), checked));
}
/**
* Returns the String describing wifi calling preference mentioned in wfcMode
*
* @param wfcMode ImsConfig constant for the preference {@link ImsConfig}
* @return summary/name of the wifi calling preference
*/
private CharSequence getWifiCallingPreferenceSummary(int wfcMode) {
switch (wfcMode) {
case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
return mContext.getText(
com.android.internal.R.string.wfc_mode_wifi_only_summary);
case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
return mContext.getText(
com.android.internal.R.string.wfc_mode_wifi_preferred_summary);
case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
return mContext.getText(
com.android.internal.R.string.wfc_mode_cellular_preferred_summary);
default:
return null;
}
}
protected ImsManager getImsManager(int subId) {
return ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId));
}
private Integer getWfcMode(ImsManager imsManager)
private int getWfcMode(ImsManager imsManager)
throws InterruptedException, ExecutionException, TimeoutException {
FutureTask<Integer> wfcModeTask = new FutureTask<>(new Callable<Integer>() {
@Override
@@ -233,7 +397,7 @@ public class WifiCallingSliceHelper {
if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final ImsManager imsManager = getImsManager(subId);
if (imsManager.isWfcEnabledByPlatform()
|| imsManager.isWfcProvisionedOnDevice()) {
&& imsManager.isWfcProvisionedOnDevice()) {
final boolean currentValue = imsManager.isWfcEnabledByUser()
&& imsManager.isNonTtyOrTtyOnVolteEnabled();
final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
@@ -255,6 +419,63 @@ public class WifiCallingSliceHelper {
mContext.getContentResolver().notifyChange(uri, null);
}
/**
* Handles wifi calling preference Setting change from wifi calling preference Slice and posts
* notification for the change. Should be called when intent action is one of the below
* ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY
* ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED
* ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED
*
* @param intent intent
*/
public void handleWifiCallingPreferenceChanged(Intent intent) {
final int subId = getDefaultVoiceSubId();
final int errorValue = -1;
if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
ImsManager imsManager = getImsManager(subId);
if (isWifiCallingPrefEditable
&& imsManager.isWfcEnabledByPlatform()
&& imsManager.isWfcProvisionedOnDevice()
&& imsManager.isWfcEnabledByUser()
&& imsManager.isNonTtyOrTtyOnVolteEnabled()) {
// Change the preference only when wifi calling is enabled
// And when wifi calling preference is editable for the current carrier
final int currentValue = imsManager.getWfcMode(false);
int newValue = errorValue;
switch (intent.getAction()) {
case ACTION_WIFI_CALLING_PREFERENCE_WIFI_ONLY:
if (isWifiOnlySupported) {
// change to wifi_only when wifi_only is enabled.
newValue = ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
}
break;
case ACTION_WIFI_CALLING_PREFERENCE_WIFI_PREFERRED:
newValue = ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED;
break;
case ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED:
newValue = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
break;
}
if (newValue != errorValue && newValue != currentValue) {
// Update the setting only when there is a valid update
imsManager.setWfcMode(newValue, false);
}
}
}
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message.
final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING_PREFERENCE,
false /*isPlatformSlice*/);
mContext.getContentResolver().notifyChange(uri, null);
}
/**
* Returns Slice with the title and subtitle provided as arguments with wifi signal Icon.
*
@@ -263,12 +484,11 @@ public class WifiCallingSliceHelper {
* @param sliceUri slice uri
* @return Slice with title and subtitle
*/
// TODO(b/79548264) asses different scenarios and return null instead of non-actionable slice
private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri,
PendingIntent primaryActionIntent) {
private Slice getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle,
Uri sliceUri, PendingIntent primaryActionIntent) {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setColor(R.color.material_blue_500)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(b -> b
.setTitle(title)
.setSubtitle(subtitle)
@@ -281,8 +501,8 @@ public class WifiCallingSliceHelper {
/**
* Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise.
*/
private boolean isCarrierConfigManagerKeyEnabled(Context mContext, String key,
int subId, boolean defaultValue) {
protected boolean isCarrierConfigManagerKeyEnabled(String key, int subId,
boolean defaultValue) {
final CarrierConfigManager configManager = getCarrierConfigManager(mContext);
boolean ret = false;
if (configManager != null) {
@@ -302,9 +522,6 @@ public class WifiCallingSliceHelper {
* Returns the current default voice subId obtained from SubscriptionManager
*/
protected int getDefaultVoiceSubId() {
if (mSubscriptionManager == null) {
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
}
return SubscriptionManager.getDefaultVoiceSubscriptionId();
}
@@ -350,6 +567,7 @@ public class WifiCallingSliceHelper {
private PendingIntent getBroadcastIntent(String action) {
final Intent intent = new Intent(action);
intent.setClass(mContext, SliceBroadcastReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
@@ -362,17 +580,4 @@ public class WifiCallingSliceHelper {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
}
/**
* Returns carrier id name of the current Subscription
*/
private String getSimCarrierName() {
final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
final CharSequence carrierName = telephonyManager.getSimCarrierIdName();
if (carrierName == null) {
return mContext.getString(R.string.carrier);
}
return carrierName.toString();
}
}