diff --git a/res/drawable/ic_radio_button_checked_black_24dp.xml b/res/drawable/ic_radio_button_checked_black_24dp.xml new file mode 100644 index 00000000000..3be6f9962e3 --- /dev/null +++ b/res/drawable/ic_radio_button_checked_black_24dp.xml @@ -0,0 +1,24 @@ + + + + diff --git a/res/drawable/ic_radio_button_unchecked_black_24dp.xml b/res/drawable/ic_radio_button_unchecked_black_24dp.xml new file mode 100644 index 00000000000..a864f7b07b4 --- /dev/null +++ b/res/drawable/ic_radio_button_unchecked_black_24dp.xml @@ -0,0 +1,24 @@ + + + + diff --git a/res/drawable/radio_button_check.xml b/res/drawable/radio_button_check.xml new file mode 100644 index 00000000000..e7884d71731 --- /dev/null +++ b/res/drawable/radio_button_check.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index 0fd5c42f4df..db09a378e1b 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -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); diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java index 231298c9ddd..9f1ef769d7d 100644 --- a/src/com/android/settings/slices/SliceBroadcastReceiver.java +++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java @@ -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)) { diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java index e8e33ef0531..ab8db2b7728 100644 --- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java +++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java @@ -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 wfcModeTask = new FutureTask<>(new Callable() { @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(); - } - } diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java index 21f6daa3428..6388297eaeb 100644 --- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java +++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java @@ -20,9 +20,12 @@ import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; import static android.app.slice.Slice.HINT_TITLE; import static android.app.slice.SliceItem.FORMAT_TEXT; +import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -41,8 +44,11 @@ import androidx.slice.SliceMetadata; import androidx.slice.SliceProvider; import androidx.slice.core.SliceAction; import androidx.slice.core.SliceQuery; +import androidx.slice.widget.ListContent; +import androidx.slice.widget.RowContent; import androidx.slice.widget.SliceLiveData; +import com.android.ims.ImsConfig; import com.android.ims.ImsManager; import com.android.settings.R; import com.android.settings.slices.SettingsSliceProvider; @@ -61,6 +67,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @@ -73,8 +81,6 @@ public class WifiCallingSliceHelperTest { @Mock private ImsManager mMockImsManager; - private final Uri mWfcURI = Uri.parse("content://com.android.settings.slices/wifi_calling"); - private FakeWifiCallingSliceHelper mWfcSliceHelper; private SettingsSliceProvider mProvider; private SliceBroadcastReceiver mReceiver; @@ -111,21 +117,21 @@ public class WifiCallingSliceHelperTest { public void test_CreateWifiCallingSlice_invalidSubId() { mWfcSliceHelper.setDefaultVoiceSubId(-1); - final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + final Slice slice = mWfcSliceHelper.createWifiCallingSlice( + WifiCallingSliceHelper.WIFI_CALLING_URI); - testWifiCallingSettingsUnavailableSlice(slice, null, - WifiCallingSliceHelper.getSettingsIntent(mContext)); + assertThat(slice).isNull(); } @Test public void test_CreateWifiCallingSlice_wfcNotSupported() { - doReturn(false).when(mMockImsManager).isWfcEnabledByPlatform(); + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(false); - final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + final Slice slice = mWfcSliceHelper.createWifiCallingSlice( + WifiCallingSliceHelper.WIFI_CALLING_URI); assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); - testWifiCallingSettingsUnavailableSlice(slice, null, - WifiCallingSliceHelper.getSettingsIntent(mContext)); + assertThat(slice).isNull(); } @Test @@ -135,29 +141,32 @@ public class WifiCallingSliceHelperTest { turned off) we need to guide the user to wifi calling settings activity so the user can perform the activation there.(PrimaryAction) */ - doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); - doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); - doReturn(false).when(mMockImsManager).isWfcEnabledByUser(); - doReturn(false).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); - doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(false); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(false); + when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent - final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + final Slice slice = mWfcSliceHelper.createWifiCallingSlice( + WifiCallingSliceHelper.WIFI_CALLING_URI); assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); testWifiCallingSettingsUnavailableSlice(slice, null, - getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), + mContext.getString(R.string.wifi_calling_settings_title)); } @Test public void test_CreateWifiCallingSlice_success() { - doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); - doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); - doReturn(true).when(mMockImsManager).isWfcEnabledByUser(); - doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); - doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); - final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + final Slice slice = mWfcSliceHelper.createWifiCallingSlice( + WifiCallingSliceHelper.WIFI_CALLING_URI); assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); testWifiCallingSettingsToggleSlice(slice, null); @@ -165,28 +174,28 @@ public class WifiCallingSliceHelperTest { @Test public void test_SettingSliceProvider_getsRightSliceWifiCalling() { - doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); - doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); - doReturn(true).when(mMockImsManager).isWfcEnabledByUser(); - doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); - doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); - doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider) - .getNewWifiCallingSliceHelper(mContext); + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); + when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) + .thenReturn(mWfcSliceHelper); - final Slice slice = mProvider.onBindSlice(mWfcURI); + final Slice slice = mProvider.onBindSlice(WifiCallingSliceHelper.WIFI_CALLING_URI); assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); testWifiCallingSettingsToggleSlice(slice, null); } @Test - public void test_SliceBroadcastReceiver_toggleOffWifiCalling() { - doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); - doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); - doReturn(false).when(mMockImsManager).isWfcEnabledByUser(); - doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); - doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider) - .getNewWifiCallingSliceHelper(mContext); + public void test_SliceBroadcastReceiver_toggleOnWifiCalling() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(false); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) + .thenReturn(mWfcSliceHelper); mWfcSliceHelper.setActivationAppIntent(null); ArgumentCaptor mWfcSettingCaptor = ArgumentCaptor.forClass(Boolean.class); @@ -204,8 +213,104 @@ public class WifiCallingSliceHelperTest { assertThat(mWfcSettingCaptor.getValue()).isTrue(); } + @Test + public void test_CreateWifiCallingPreferenceSlice_prefNotEditable() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mWfcSliceHelper.setIsWifiCallingPrefEditable(false); + + final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice( + WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + assertThat(slice).isNull(); + } + + @Test + public void test_CreateWifiCallingPreferenceSlice_wfcOff() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(false); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mWfcSliceHelper.setIsWifiCallingPrefEditable(true); + + final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice( + WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingSettingsUnavailableSlice(slice, null, + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), + mContext.getString(R.string.wifi_calling_mode_title)); + } + + @Test + public void test_CreateWifiCallingPreferenceSlice_success() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mMockImsManager.getWfcMode(false)).thenReturn( + ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED); + mWfcSliceHelper.setIsWifiCallingPrefEditable(true); + + final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice( + WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingPreferenceSlice(slice, null, + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + } + + @Test + public void test_SettingsSliceProvider_getWfcPreferenceSlice() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mMockImsManager.getWfcMode(false)).thenReturn( + ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED); + when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) + .thenReturn(mWfcSliceHelper); + mWfcSliceHelper.setIsWifiCallingPrefEditable(true); + + final Slice slice = mProvider.onBindSlice( + WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingPreferenceSlice(slice, null, + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + } + @Test + public void test_SliceBroadcastReceiver_setWfcPrefCellularPref() { + when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true); + when(mMockImsManager.isWfcProvisionedOnDevice()).thenReturn(true); + when(mMockImsManager.isWfcEnabledByUser()).thenReturn(true); + when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + when(mMockImsManager.getWfcMode(false)).thenReturn( + ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED); + when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) + .thenReturn(mWfcSliceHelper); + mWfcSliceHelper.setIsWifiCallingPrefEditable(true); + + ArgumentCaptor mWfcPreferenceCaptor = ArgumentCaptor.forClass(Integer.class); + + // Change preference to Cellular pref + Intent intent = new Intent( + WifiCallingSliceHelper.ACTION_WIFI_CALLING_PREFERENCE_CELLULAR_PREFERRED); + + mReceiver.onReceive(mContext, intent); + + verify((mMockImsManager)).setWfcMode(mWfcPreferenceCaptor.capture(), eq(false)); + + // assert the change + assertThat(mWfcPreferenceCaptor.getValue()).isEqualTo( + ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED); + } + private void testWifiCallingSettingsUnavailableSlice(Slice slice, - SliceData sliceData, PendingIntent expectedPrimaryAction) { + SliceData sliceData, PendingIntent expectedPrimaryAction, String title) { final SliceMetadata metadata = SliceMetadata.from(mContext, slice); //Check there is no toggle action @@ -219,7 +324,7 @@ public class WifiCallingSliceHelperTest { // Check the title final List sliceItems = slice.getItems(); - assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title)); + assertTitle(sliceItems, title); } private void testWifiCallingSettingsToggleSlice(Slice slice, @@ -248,6 +353,51 @@ public class WifiCallingSliceHelperTest { assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title)); } + private void testWifiCallingPreferenceSlice(Slice slice, SliceData sliceData, + PendingIntent expectedPrimaryAction) { + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + + //Check there is no toggle action + final List toggles = metadata.getToggles(); + assertThat(toggles).isEmpty(); + + // Check whether the primary action is to open wifi calling settings activity + final PendingIntent primaryPendingIntent = + metadata.getPrimaryAction().getAction(); + assertThat(primaryPendingIntent).isEqualTo(expectedPrimaryAction); + + // Get all the rows + final ListContent listContent = new ListContent(mContext, slice); + final ArrayList rowItems = listContent.getRowItems(); + + assertThat(rowItems.size()).isEqualTo(4 /* 4 items including header */); + + // First row is HEADER + SliceItem rowSliceItem = rowItems.get(0); + RowContent rowContent = new RowContent(mContext, rowSliceItem, true); + assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText( + R.string.wifi_calling_mode_title)); + + // next is WIFI_ONLY + rowSliceItem = rowItems.get(1); + rowContent = new RowContent(mContext, rowSliceItem, false); + assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText( + com.android.internal.R.string.wfc_mode_wifi_only_summary)); + + // next is WIFI_PREFERRED + rowSliceItem = rowItems.get(2); + rowContent = new RowContent(mContext, rowSliceItem, false); + assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText( + com.android.internal.R.string.wfc_mode_wifi_preferred_summary)); + + // next is CELLULAR_PREFERRED + rowSliceItem = rowItems.get(3); + rowContent = new RowContent(mContext, rowSliceItem, false); + assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText( + com.android.internal.R.string.wfc_mode_cellular_preferred_summary)); + + } + private PendingIntent getBroadcastIntent(String action) { final Intent intent = new Intent(action); intent.setClass(mContext, SliceBroadcastReceiver.class); @@ -279,6 +429,8 @@ public class WifiCallingSliceHelperTest { } private class FakeWifiCallingSliceHelper extends WifiCallingSliceHelper { int mSubId = 1; + boolean isWifiCallingPrefEditable = true; + boolean isWifiOnlySupported = true; private Intent mActivationAppIntent; FakeWifiCallingSliceHelper(Context context) { @@ -308,9 +460,23 @@ public class WifiCallingSliceHelperTest { protected Intent getWifiCallingCarrierActivityIntent(int subId) { return mActivationAppIntent; } + @Override + protected boolean isCarrierConfigManagerKeyEnabled(String key, int subId, + boolean defaultValue) { + if(key.equals(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) { + return isWifiCallingPrefEditable; + } else if(key.equals(CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL)) { + return isWifiOnlySupported; + } + return defaultValue; + } public void setActivationAppIntent(Intent intent) { mActivationAppIntent = intent; } + + public void setIsWifiCallingPrefEditable(boolean isWifiCallingPrefEditable) { + this.isWifiCallingPrefEditable = isWifiCallingPrefEditable; + } } }