diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 03e40aa13fc..3e6758e6318 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1357,4 +1357,17 @@ "9" + + + @string/wifi_calling_mode_wifi_preferred_summary + @string/wifi_calling_mode_cellular_preferred_summary + @string/wifi_calling_mode_wifi_only_summary + + + + + @string/wifi_calling_mode_wifi_preferred_summary + @string/wifi_calling_mode_cellular_preferred_summary + + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index c7bf1c7576c..e099cf04ea5 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -132,6 +132,11 @@ + + + + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 4ac0db88d86..335c0f47294 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -279,6 +279,15 @@ 14sp + + 20sp + + + 20dp + 12dp + 8dp + 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 0789a95c873..ef02b359c62 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2472,7 +2472,7 @@ Calling preference - Wi-Fi calling mode + Calling preference Roaming preference @@ -2480,9 +2480,9 @@ Roaming preference - Wi-Fi preferred - Mobile preferred - Wi-Fi only + @*android:string/wfc_mode_wifi_preferred_summary + @*android:string/wfc_mode_cellular_preferred_summary + @*android:string/wfc_mode_wifi_only_summary Wi-Fi @@ -2495,8 +2495,8 @@ "0" - Wi-Fi preferred - Mobile preferred + @*android:string/wfc_mode_wifi_preferred_summary + @*android:string/wfc_mode_cellular_preferred_summary Wi-Fi @@ -2506,6 +2506,14 @@ "2" "1" + + + If Wi\u2011Fi is unavailable, use mobile network + + If mobile network is unavailable, use Wi\u2011Fi + + Call over Wi\u2011Fi. If Wi\u2011Fi is lost, call will end. + When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.%1$s diff --git a/res/xml/single_choice_list_item_2.xml b/res/xml/single_choice_list_item_2.xml new file mode 100644 index 00000000000..ca80f444602 --- /dev/null +++ b/res/xml/single_choice_list_item_2.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml index 0adb1e8d357..0276bdb6b10 100644 --- a/res/xml/wifi_calling_settings.xml +++ b/res/xml/wifi_calling_settings.xml @@ -15,24 +15,27 @@ --> - + android:dialogTitle="@string/wifi_calling_mode_dialog_title" + settings:entrySummaries="@array/wifi_calling_mode_summaries" /> - + android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title" + settings:entrySummaries="@array/wifi_calling_mode_summaries" /> { + private final Context mContext; + private ListWithEntrySummaryPreference mSelector; + + /** + * SelectorAdapter constructor. + * + * @param context The current context. + * @param rowResourceId The resource id of the XML tag that is inflating the linear layout. + * @param listPreference The instance of ListWithEntrySummaryPreference. + */ + public SelectorAdapter(Context context, int rowResourceId, + ListWithEntrySummaryPreference listPreference) { + super(context, rowResourceId, listPreference.getEntryValues()); + mContext = context; + mSelector = listPreference; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(mContext); + View row = inflater.inflate(R.xml.single_choice_list_item_2, parent, false); + + TextView title = (TextView) row.findViewById(R.id.title); + title.setText(mSelector.getEntries()[position]); + + TextView summary = (TextView) row.findViewById(R.id.summary); + summary.setText(mSelector.getEntrySummary(position)); + + RadioButton rb = (RadioButton) row.findViewById(R.id.radio); + if (position == mSelector.findIndexOfValue(mSelector.getValue())) { + rb.setChecked(true); + } + + return row; + } + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + + final SavedState myState = new SavedState(superState); + myState.mEntries = getEntries(); + myState.mEntryValues = getEntryValues(); + myState.mSummaries = mSummaries; + return myState; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(SavedState.class)) { + // Didn't save state for us in onSaveInstanceState + super.onRestoreInstanceState(state); + return; + } + + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + setEntries(myState.mEntries); + setEntryValues(myState.mEntryValues); + mSummaries = myState.mSummaries; + } + + /** + * We save entries, entryValues and summaries into bundle. + * At onCreate of fragment, dialog will be restored if it was open. In this case, + * we need to restore entries, entryValues and summaries. Without those information, + * crash when entering multi window during wfc modes dialog shown. + */ + private static class SavedState extends BaseSavedState { + private CharSequence[] mEntries; + private CharSequence[] mEntryValues; + private CharSequence[] mSummaries; + + public SavedState(Parcel source) { + super(source); + mEntries = source.readCharSequenceArray(); + mEntryValues = source.readCharSequenceArray(); + mSummaries = source.readCharSequenceArray(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeCharSequenceArray(mEntries); + dest.writeCharSequenceArray(mEntryValues); + dest.writeCharSequenceArray(mSummaries); + } + + public SavedState(Parcelable superState) { + super(superState); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java index 79112c74be3..7253f014572 100644 --- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java +++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java @@ -82,8 +82,8 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment //UI objects private SwitchBar mSwitchBar; private Switch mSwitch; - private ListPreference mButtonWfcMode; - private ListPreference mButtonWfcRoamingMode; + private ListWithEntrySummaryPreference mButtonWfcMode; + private ListWithEntrySummaryPreference mButtonWfcRoamingMode; private Preference mUpdateAddress; private TextView mEmptyView; @@ -264,10 +264,11 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment mTelephonyManager = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)) .createForSubscriptionId(mSubId); - mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE); + mButtonWfcMode = (ListWithEntrySummaryPreference) findPreference(BUTTON_WFC_MODE); mButtonWfcMode.setOnPreferenceChangeListener(this); - mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE); + mButtonWfcRoamingMode = (ListWithEntrySummaryPreference) findPreference( + BUTTON_WFC_ROAMING_MODE); mButtonWfcRoamingMode.setOnPreferenceChangeListener(this); mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS); @@ -325,10 +326,14 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment if (!isWifiOnlySupported) { mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only); mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only); + mButtonWfcMode.setEntrySummaries(R.array.wifi_calling_mode_summaries_without_wifi_only); + mButtonWfcRoamingMode.setEntries( R.array.wifi_calling_mode_choices_v2_without_wifi_only); mButtonWfcRoamingMode.setEntryValues( R.array.wifi_calling_mode_values_without_wifi_only); + mButtonWfcRoamingMode.setEntrySummaries( + R.array.wifi_calling_mode_summaries_without_wifi_only); } diff --git a/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java new file mode 100644 index 00000000000..cc2622f4b35 --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi.calling; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.os.Parcelable; +import android.widget.ListAdapter; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.io.IOException; + +@RunWith(RobolectricTestRunner.class) +public class ListWithEntrySummaryPreferenceTest { + + private Context mContext; + private ListWithEntrySummaryPreference mPreference; + + private CharSequence[] mDefaultEntries = + {"default_entry1", "default_entry2", "default_entry3"}; + private CharSequence[] mDefaultEntryValues = {"0", "1", "2"}; + private CharSequence[] mDefaultEntrySummaries = + {"default_summary1", "default_summary2", "default_summary3"}; + + private CharSequence[] mCustomEntries = {"custom_entry1", "custom_entry2"}; + private CharSequence[] mCustomEntryValues = {"0", "1"}; + private CharSequence[] mCustomEntrySummaries = {"custom_summary1", "custom_summary2"}; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mPreference = new ListWithEntrySummaryPreference(mContext, null); + mPreference.setEntries(mDefaultEntries); + mPreference.setEntryValues(mDefaultEntryValues); + mPreference.setEntrySummaries(mDefaultEntrySummaries); + } + + @Test + public void initialize_defaultEntries_shouldDisplayDefalutEntries() { + AlertDialog dialog = showDialog(mPreference); + ListAdapter adapter = dialog.getListView().getAdapter(); + + int len = mDefaultEntries.length; + assertThat(adapter.getCount()).isEqualTo(len); + for (int i = 0; i < len; i++) { + TextView title = adapter.getView(i, null, null).findViewById(R.id.title); + TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary); + assertThat(title.getText()).isEqualTo(mDefaultEntries[i]); + assertThat(summary.getText()).isEqualTo(mDefaultEntrySummaries[i]); + } + } + + @Test + public void setEntries_customEntries_shouldUpdateEntries() { + mPreference.setEntries(mCustomEntries); + mPreference.setEntryValues(mCustomEntryValues); + mPreference.setEntrySummaries(mCustomEntrySummaries); + + AlertDialog dialog = showDialog(mPreference); + ListAdapter adapter = dialog.getListView().getAdapter(); + + int len = mCustomEntries.length; + assertThat(adapter.getCount()).isEqualTo(len); + for (int i = 0; i < len; i++) { + TextView title = adapter.getView(i, null, null).findViewById(R.id.title); + TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary); + assertThat(title.getText()).isEqualTo(mCustomEntries[i]); + assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]); + } + } + + @Test + public void onSaveAndRestoreInstanceState_resumePreference_shouldNotChangeEntries() { + setEntries_customEntries_shouldUpdateEntries(); + + final Parcelable parcelable = mPreference.onSaveInstanceState(); + ListWithEntrySummaryPreference preference + = new ListWithEntrySummaryPreference(mContext, null); + preference.setEntries(mDefaultEntries); + preference.setEntryValues(mDefaultEntryValues); + preference.setEntrySummaries(mDefaultEntrySummaries); + preference.onRestoreInstanceState(parcelable); + + AlertDialog dialog = showDialog(preference); + ListAdapter adapter = dialog.getListView().getAdapter(); + + int len = mCustomEntries.length; + assertThat(adapter.getCount()).isEqualTo(len); + for (int i = 0; i < len; i++) { + TextView title = adapter.getView(i, null, null).findViewById(R.id.title); + TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary); + assertThat(title.getText()).isEqualTo(mCustomEntries[i]); + assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]); + } + } + + private AlertDialog showDialog(ListWithEntrySummaryPreference preference) { + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + preference.onPrepareDialogBuilder(builder, null); + return builder.show(); + } +}