From fe9059b11dae4823e4b4e4733039f9686594dc97 Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Mon, 8 Oct 2018 15:56:51 -0700 Subject: [PATCH 01/14] Also all EXTRA_USER as input for ACTION_SHOW_ADMIN_SUPPORT_DETAILS Test: Built Bug: 116798569 Change-Id: Idbb1e7c6efbde57c00e96d7d9a2aefb233b94586 --- .../enterprise/ActionDisabledByAdminDialog.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java index 11427661cdb..717c5bcd757 100644 --- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java +++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java @@ -59,11 +59,15 @@ public class ActionDisabledByAdminDialog extends Activity } admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN); - int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); - if (userId == UserHandle.USER_NULL) { - admin.user = null; + if (intent.hasExtra(Intent.EXTRA_USER)) { + admin.user = intent.getParcelableExtra(Intent.EXTRA_USER); } else { - admin.user = UserHandle.of(userId); + int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + if (userId == UserHandle.USER_NULL) { + admin.user = null; + } else { + admin.user = UserHandle.of(userId); + } } return admin; } From 7ba739ba14700d5fc97f69f71bfcd128b1956e59 Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Thu, 20 Sep 2018 15:15:57 +0100 Subject: [PATCH 02/14] Private DNS: Extract host verification code Since Private DNS host may now be set by the admin via the DevicePolicyManager, extract the verification code to the ConnectivityManager so it can be used both from Settings and framework code. Bug: 112982691 Test: See cts tests. Change-Id: Ic091e4714f8d3f9f28042bc825cf57c991504f27 --- .../PrivateDnsModeDialogPreference.java | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java index 9e083453a9a..a4e7d2ad541 100644 --- a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java +++ b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java @@ -27,6 +27,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.net.NetworkUtils; import android.provider.Settings; import android.system.Os; import android.text.Editable; @@ -72,8 +73,6 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, R.id.private_dns_mode_provider); } - private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6}; - @VisibleForTesting static final String MODE_KEY = Settings.Global.PRIVATE_DNS_MODE; @VisibleForTesting @@ -203,23 +202,6 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat updateDialogInfo(); } - private boolean isWeaklyValidatedHostname(String hostname) { - // TODO(b/34953048): Use a validation method that permits more accurate, - // but still inexpensive, checking of likely valid DNS hostnames. - final String WEAK_HOSTNAME_REGEX = "^[a-zA-Z0-9_.-]+$"; - if (!hostname.matches(WEAK_HOSTNAME_REGEX)) { - return false; - } - - for (int address_family : ADDRESS_FAMILIES) { - if (Os.inet_pton(address_family, hostname) != null) { - return false; - } - } - - return true; - } - private Button getSaveButton() { final AlertDialog dialog = (AlertDialog) getDialog(); if (dialog == null) { @@ -236,7 +218,7 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat final Button saveButton = getSaveButton(); if (saveButton != null) { saveButton.setEnabled(modeProvider - ? isWeaklyValidatedHostname(mEditText.getText().toString()) + ? NetworkUtils.isWeaklyValidatedHostname(mEditText.getText().toString()) : true); } } From 717194c87c7f619152dddffa12e2ec2f6127fab7 Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Wed, 3 Oct 2018 17:05:48 +0100 Subject: [PATCH 03/14] Consider Private DNS user restriction As a new user restriction, to disallow changing Private DNS settings, was added, make the Private DNS mode dialog preference consider whether to let the user modify it or not based on the presence of this restriction. Bug: 112982691 Test: atest com.android.cts.devicepolicy.DeviceOwnerTest#testPrivateDnsPolicy Test: m -j RunSettingsRoboTests ROBOTEST_FILTER=PrivateDnsPreferenceControllerTest Test: Manual, using TestDPC Change-Id: If815860ace3aadf6f79fd23173f0a2c80a29f0e1 --- .../PrivateDnsPreferenceController.java | 17 +++++++++ .../PrivateDnsPreferenceControllerTest.java | 37 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java index 561801052a6..8b3bfa0bf72 100644 --- a/src/com/android/settings/network/PrivateDnsPreferenceController.java +++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java @@ -34,6 +34,8 @@ import android.net.Network; import android.net.Uri; import android.os.Handler; import android.os.Looper; +import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import androidx.preference.Preference; @@ -46,6 +48,8 @@ import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; +import com.android.settingslib.RestrictedLockUtilsInternal; +import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import java.net.InetAddress; import java.util.List; @@ -136,6 +140,19 @@ public class PrivateDnsPreferenceController extends BasePreferenceController return ""; } + @Override + public void updateState(Preference preference) { + super.updateState(preference); + //TODO(b/112982691): Add policy transparency explaining why this setting is disabled. + preference.setEnabled(!isManagedByAdmin()); + } + + private boolean isManagedByAdmin() { + EnforcedAdmin enforcedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + mContext, UserManager.DISALLOW_CONFIG_PRIVATE_DNS, UserHandle.myUserId()); + return enforcedAdmin != null; + } + private class PrivateDnsSettingsObserver extends ContentObserver { public PrivateDnsSettingsObserver(Handler h) { super(h); diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java index b475c7e9391..464b2906744 100644 --- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java @@ -43,6 +43,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager; @@ -50,6 +51,8 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.LinkProperties; import android.net.Network; import android.os.Handler; +import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import androidx.lifecycle.LifecycleOwner; @@ -58,6 +61,8 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowUserManager; +import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; @@ -79,6 +84,10 @@ import java.util.Collections; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = { + ShadowUserManager.class, + ShadowDevicePolicyManager.class +}) public class PrivateDnsPreferenceControllerTest { private final static String HOSTNAME = "dns.example.com"; @@ -108,6 +117,7 @@ public class PrivateDnsPreferenceControllerTest { private ShadowContentResolver mShadowContentResolver; private Lifecycle mLifecycle; private LifecycleOwner mLifecycleOwner; + private ShadowUserManager mShadowUserManager; @Before public void setUp() { @@ -127,6 +137,8 @@ public class PrivateDnsPreferenceControllerTest { mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); mLifecycle.addObserver(mController); + + mShadowUserManager = ShadowUserManager.getShadow(); } private void updateLinkProperties(LinkProperties lp) { @@ -264,6 +276,31 @@ public class PrivateDnsPreferenceControllerTest { verify(mPreference).setSummary(getResourceString(R.string.private_dns_mode_opportunistic)); } + @Test + public void isEnabled_canBeDisabledByAdmin() { + final int userId = UserHandle.myUserId(); + final List enforcingUsers = Collections.singletonList( + new UserManager.EnforcingUser(userId, + UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) + ); + mShadowUserManager.setUserRestrictionSources( + UserManager.DISALLOW_CONFIG_PRIVATE_DNS, + UserHandle.of(userId), + enforcingUsers); + + ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser( + new ComponentName("test", "test")); + + mController.updateState(mPreference); + verify(mPreference).setEnabled(false); + } + + @Test + public void isEnabled_isEnabledByDefault() { + mController.updateState(mPreference); + verify(mPreference).setEnabled(true); + } + private void setPrivateDnsMode(String mode) { Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, mode); } From f7bb72c60c4deff9ec4b844a0d51ad04454eae2b Mon Sep 17 00:00:00 2001 From: Raff Tsai Date: Tue, 16 Oct 2018 21:47:58 +0800 Subject: [PATCH 04/14] Use the same layout style for contextual cards Test: manual Change-Id: I41d86df5147290a17ef698f4f6a192081d1e0742 --- res/layout/homepage_condition_tile.xml | 5 +---- res/layout/homepage_slice_tile.xml | 7 +------ res/values/styles.xml | 9 +++++++++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/res/layout/homepage_condition_tile.xml b/res/layout/homepage_condition_tile.xml index 50ef3c250d2..9be5c1efdf4 100644 --- a/res/layout/homepage_condition_tile.xml +++ b/res/layout/homepage_condition_tile.xml @@ -17,12 +17,9 @@ + style="@style/ContextualCardStyle"> diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml index b947d656097..151ad24e4c9 100644 --- a/res/layout/homepage_slice_tile.xml +++ b/res/layout/homepage_slice_tile.xml @@ -20,12 +20,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/homepage_card_top_margin" - android:layout_marginBottom="@dimen/homepage_card_bottom_margin" - android:layout_marginStart="@dimen/homepage_card_side_margin" - android:layout_marginEnd="@dimen/homepage_card_side_margin" - app:cardCornerRadius="@dimen/homepage_card_corner_radius" - app:cardElevation="@dimen/homepage_card_elevation"> + style="@style/ContextualCardStyle"> 24dp + + From d5405cf49db7d683a5275becbfd418676782d2d4 Mon Sep 17 00:00:00 2001 From: tmfang Date: Fri, 5 Oct 2018 18:45:07 +0800 Subject: [PATCH 05/14] Fix InstantiationException on fragment Since we overrided the empty constructor, it can't find a empty constructor when Fragment tries to instantiate a fragment in framework. So, we can't override this constructor, and then just use newInstance() to initialize and setup a new Fragment. Test: robotest Change-Id: Ifcd1c1771bc69d947caeee5c5bc055c4f94365c2 Fixes: 115676209 --- src/com/android/settings/ProxySelector.java | 2 +- .../settings/SettingsPreferenceFragment.java | 26 ++++++++++++++----- .../settings/SettingsDialogFragmentTest.java | 8 +++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/ProxySelector.java b/src/com/android/settings/ProxySelector.java index 774e47c6e80..4bd458541c5 100644 --- a/src/com/android/settings/ProxySelector.java +++ b/src/com/android/settings/ProxySelector.java @@ -113,7 +113,7 @@ public class ProxySelector extends InstrumentedFragment implements DialogCreatab if (mDialogFragment != null) { Log.e(TAG, "Old dialog fragment not null!"); } - mDialogFragment = new SettingsDialogFragment(this, dialogId); + mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); mDialogFragment.show(getActivity().getSupportFragmentManager(), Integer.toString(dialogId)); } diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java index 87a35116ca0..5cfe2188d29 100644 --- a/src/com/android/settings/SettingsPreferenceFragment.java +++ b/src/com/android/settings/SettingsPreferenceFragment.java @@ -454,7 +454,7 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF if (mDialogFragment != null) { Log.e(TAG, "Old dialog fragment not null!"); } - mDialogFragment = new SettingsDialogFragment(this, dialogId); + mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId)); } @@ -541,22 +541,26 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF private DialogInterface.OnCancelListener mOnCancelListener; private DialogInterface.OnDismissListener mOnDismissListener; - public SettingsDialogFragment(DialogCreatable fragment, int dialogId) { - super(fragment, dialogId); + public static SettingsDialogFragment newInstance(DialogCreatable fragment, int dialogId) { if (!(fragment instanceof Fragment)) { throw new IllegalArgumentException("fragment argument must be an instance of " + Fragment.class.getName()); } - mParentFragment = (Fragment) fragment; - } + final SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment(); + settingsDialogFragment.setParentFragment(fragment); + settingsDialogFragment.setDialogId(dialogId); + + return settingsDialogFragment; + } @Override public int getMetricsCategory() { - if (mDialogCreatable == null) { + if (mParentFragment == null) { return Instrumentable.METRICS_CATEGORY_UNKNOWN; } - final int metricsCategory = mDialogCreatable.getDialogMetricsCategory(mDialogId); + final int metricsCategory = + ((DialogCreatable) mParentFragment).getDialogMetricsCategory(mDialogId); if (metricsCategory <= 0) { throw new IllegalStateException("Dialog must provide a metrics category"); } @@ -639,6 +643,14 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF } } } + + private void setParentFragment(DialogCreatable fragment) { + mParentFragment = (Fragment) fragment; + } + + private void setDialogId(int dialogId) { + mDialogId = dialogId; + } } protected boolean hasNextButton() { diff --git a/tests/robotests/src/com/android/settings/SettingsDialogFragmentTest.java b/tests/robotests/src/com/android/settings/SettingsDialogFragmentTest.java index c78a44a78f4..ed0e5a02235 100644 --- a/tests/robotests/src/com/android/settings/SettingsDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/SettingsDialogFragmentTest.java @@ -51,8 +51,8 @@ public class SettingsDialogFragmentTest { public void testGetMetrics_shouldGetMetricFromDialogCreatable() { when(mDialogCreatable.getDialogMetricsCategory(DIALOG_ID)).thenReturn(1); - mDialogFragment = - new SettingsPreferenceFragment.SettingsDialogFragment(mDialogCreatable, DIALOG_ID); + mDialogFragment = SettingsPreferenceFragment.SettingsDialogFragment.newInstance( + mDialogCreatable, DIALOG_ID); mDialogFragment.onAttach(RuntimeEnvironment.application); mDialogFragment.getMetricsCategory(); @@ -65,8 +65,8 @@ public class SettingsDialogFragmentTest { when(mDialogCreatable.getDialogMetricsCategory(DIALOG_ID)).thenReturn(-1); try { - mDialogFragment = - new SettingsPreferenceFragment.SettingsDialogFragment(mDialogCreatable, DIALOG_ID); + mDialogFragment = SettingsPreferenceFragment.SettingsDialogFragment.newInstance( + mDialogCreatable, DIALOG_ID); mDialogFragment.onAttach(RuntimeEnvironment.application); fail("Should fail with IllegalStateException"); } catch (IllegalStateException e) { From 6e16b69887bb8dece5725c1824b83c2bcdb2df96 Mon Sep 17 00:00:00 2001 From: tmfang Date: Thu, 11 Oct 2018 16:20:15 +0800 Subject: [PATCH 06/14] Sync style of filter component in data usage Settings have new filter component with settings style. This CL replaced Spinner to SettingsSpinner in data usage page. Change-Id: I212b6b6ed203f8bffd094c0180873060b93c39cb Fixes: 117568930 Test: robotests, visual --- res/drawable/ic_apps_filter_settings_24dp.xml | 28 +++++++++++++++++++ res/layout/apps_filter_spinner.xml | 2 +- res/layout/data_usage_cycle_item.xml | 27 ------------------ res/layout/data_usage_cycles.xml | 20 ++++++------- .../settings/datausage/AppDataUsage.java | 2 +- .../settings/datausage/AppDataUsageV2.java | 2 +- .../settings/datausage/CycleAdapter.java | 16 +++++------ .../settings/datausage/DataUsageList.java | 2 +- .../settings/datausage/DataUsageListV2.java | 2 +- .../settings/datausage/SpinnerPreference.java | 4 +-- 10 files changed, 51 insertions(+), 54 deletions(-) create mode 100644 res/drawable/ic_apps_filter_settings_24dp.xml delete mode 100644 res/layout/data_usage_cycle_item.xml diff --git a/res/drawable/ic_apps_filter_settings_24dp.xml b/res/drawable/ic_apps_filter_settings_24dp.xml new file mode 100644 index 00000000000..01a53a7e7e1 --- /dev/null +++ b/res/drawable/ic_apps_filter_settings_24dp.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/res/layout/apps_filter_spinner.xml b/res/layout/apps_filter_spinner.xml index ca69cc61f82..c9b1e074078 100644 --- a/res/layout/apps_filter_spinner.xml +++ b/res/layout/apps_filter_spinner.xml @@ -37,7 +37,7 @@ android:layout_toRightOf="@id/filter_spinner" android:contentDescription="@string/configure" android:scaleType="center" - android:src="@drawable/ic_settings_24dp" + android:src="@drawable/ic_apps_filter_settings_24dp" android:visibility="gone"/> diff --git a/res/layout/data_usage_cycle_item.xml b/res/layout/data_usage_cycle_item.xml deleted file mode 100644 index 015608d2b8e..00000000000 --- a/res/layout/data_usage_cycle_item.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - diff --git a/res/layout/data_usage_cycles.xml b/res/layout/data_usage_cycles.xml index 9c6cc31b199..05c38e0b68c 100644 --- a/res/layout/data_usage_cycles.xml +++ b/res/layout/data_usage_cycles.xml @@ -14,21 +14,17 @@ limitations under the License. --> - + android:minHeight="?android:attr/listPreferredItemHeight"> - + android:layout_width="wrap_content" + android:layout_centerInParent="true"/> + + - diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java index fcb6b72a9c7..4dddeab6b2e 100644 --- a/src/com/android/settings/datausage/AppDataUsage.java +++ b/src/com/android/settings/datausage/AppDataUsage.java @@ -144,7 +144,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); mCycle = (SpinnerPreference) findPreference(KEY_CYCLE); - mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener, false); + mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener); if (mAppItem.key > 0) { if (mPackages.size() != 0) { diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java index 4e8325b27c8..7515c51d5c5 100644 --- a/src/com/android/settings/datausage/AppDataUsageV2.java +++ b/src/com/android/settings/datausage/AppDataUsageV2.java @@ -131,7 +131,7 @@ public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenc mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); mCycle = (SpinnerPreference) findPreference(KEY_CYCLE); - mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener, false); + mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener); if (mAppItem.key > 0) { if (mPackages.size() != 0) { diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java index 9378dea9450..74d27be7e67 100644 --- a/src/com/android/settings/datausage/CycleAdapter.java +++ b/src/com/android/settings/datausage/CycleAdapter.java @@ -20,28 +20,25 @@ import android.net.NetworkStatsHistory; import android.text.format.DateUtils; import android.util.Pair; import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import com.android.settings.R; import com.android.settings.Utils; import com.android.settingslib.net.ChartData; import com.android.settingslib.net.NetworkCycleData; +import com.android.settingslib.widget.settingsspinner.SettingsSpinnerAdapter; import java.time.ZonedDateTime; import java.util.Iterator; import java.util.List; import java.util.Objects; -public class CycleAdapter extends ArrayAdapter { +public class CycleAdapter extends SettingsSpinnerAdapter { private final SpinnerInterface mSpinner; private final AdapterView.OnItemSelectedListener mListener; public CycleAdapter(Context context, SpinnerInterface spinner, - AdapterView.OnItemSelectedListener listener, boolean isHeader) { - super(context, isHeader ? R.layout.filter_spinner_item - : R.layout.data_usage_cycle_item); - setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + AdapterView.OnItemSelectedListener listener) { + super(context); mSpinner = spinner; mListener = listener; mSpinner.setAdapter(this); @@ -159,7 +156,7 @@ public class CycleAdapter extends ArrayAdapter { public boolean updateCycleList(List cycleData) { // stash away currently selected cycle to try restoring below final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem) - mSpinner.getSelectedItem(); + mSpinner.getSelectedItem(); clear(); final Context context = getContext(); @@ -223,8 +220,11 @@ public class CycleAdapter extends ArrayAdapter { public interface SpinnerInterface { void setAdapter(CycleAdapter cycleAdapter); + void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener); + Object getSelectedItem(); + void setSelection(int position); } } diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java index 0458207e8ad..8f0026f4e1e 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -182,7 +182,7 @@ public class DataUsageList extends DataUsageBaseFragment { public void setSelection(int position) { mCycleSpinner.setSelection(position); } - }, mCycleListener, true); + }, mCycleListener); mLoadingViewController = new LoadingViewController( getView().findViewById(R.id.loading_container), getListView()); diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java index aef9519b870..4432feec1be 100644 --- a/src/com/android/settings/datausage/DataUsageListV2.java +++ b/src/com/android/settings/datausage/DataUsageListV2.java @@ -175,7 +175,7 @@ public class DataUsageListV2 extends DataUsageBaseFragment { public void setSelection(int position) { mCycleSpinner.setSelection(position); } - }, mCycleListener, true); + }, mCycleListener); mLoadingViewController = new LoadingViewController( getView().findViewById(R.id.loading_container), getListView()); diff --git a/src/com/android/settings/datausage/SpinnerPreference.java b/src/com/android/settings/datausage/SpinnerPreference.java index 867930baa97..67298a14bb6 100644 --- a/src/com/android/settings/datausage/SpinnerPreference.java +++ b/src/com/android/settings/datausage/SpinnerPreference.java @@ -18,12 +18,12 @@ import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; -import android.widget.Spinner; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; +import com.android.settingslib.widget.settingsspinner.SettingsSpinner; public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface { @@ -63,7 +63,7 @@ public class SpinnerPreference extends Preference implements CycleAdapter.Spinne @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); - Spinner spinner = (Spinner) holder.findViewById(R.id.cycles_spinner); + SettingsSpinner spinner = (SettingsSpinner) holder.findViewById(R.id.cycles_spinner); spinner.setAdapter(mAdapter); spinner.setSelection(mPosition); spinner.setOnItemSelectedListener(mOnSelectedListener); From 37f2e60b8c73fa06bf8ce1ff08454682f426f65c Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Thu, 11 Oct 2018 15:01:23 -0700 Subject: [PATCH 07/14] Refactor CdmaSubscriptionListPreference Extract CdmaBasePreferenceController that can be shared by all CDMA PreferenceController. Also create new subscription controller to use it. Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I7cfc27ffd0704d09dc02e49fbf5641ff8b90642d --- res/xml/cdma_options.xml | 8 -- res/xml/network_setting_fragment.xml | 9 ++ .../network/telephony/CdmaOptions.java | 46 ------- .../CdmaSubscriptionListPreference.java | 115 ----------------- .../telephony/MobileNetworkFragment.java | 24 ++-- .../cdma/CdmaBasePreferenceController.java | 108 ++++++++++++++++ .../CdmaSubscriptionPreferenceController.java | 110 ++++++++++++++++ .../CdmaSystemSelectPreferenceController.java | 82 +----------- ...aSubscriptionPreferenceControllerTest.java | 121 ++++++++++++++++++ 9 files changed, 361 insertions(+), 262 deletions(-) delete mode 100644 src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java create mode 100644 src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java create mode 100644 src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml index 92265881500..b95e31b1e93 100644 --- a/res/xml/cdma_options.xml +++ b/res/xml/cdma_options.xml @@ -17,14 +17,6 @@ - - + + diff --git a/src/com/android/settings/network/telephony/CdmaOptions.java b/src/com/android/settings/network/telephony/CdmaOptions.java index b927e2584b9..0e6c6c2b238 100644 --- a/src/com/android/settings/network/telephony/CdmaOptions.java +++ b/src/com/android/settings/network/telephony/CdmaOptions.java @@ -43,7 +43,6 @@ public class CdmaOptions { private static final String LOG_TAG = "CdmaOptions"; private CarrierConfigManager mCarrierConfigManager; - private CdmaSubscriptionListPreference mButtonCdmaSubscription; private RestrictedPreference mButtonAPNExpand; private Preference mCategoryAPNExpand; private Preference mButtonCarrierSettings; @@ -65,8 +64,6 @@ public class CdmaOptions { mCarrierConfigManager = new CarrierConfigManager(prefFragment.getContext()); // Initialize preferences. - mButtonCdmaSubscription = (CdmaSubscriptionListPreference) mPrefScreen - .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY); mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY); mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY); mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY); @@ -82,8 +79,6 @@ public class CdmaOptions { PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); // Some CDMA carriers want the APN settings. boolean addAPNExpand = shouldAddApnExpandPreference(phoneType, carrierConfig); - boolean addCdmaSubscription = - deviceSupportsNvAndRuim(); // Read platform settings for carrier settings boolean addCarrierSettings = carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL); @@ -120,15 +115,6 @@ public class CdmaOptions { mPrefScreen.removePreference(mCategoryAPNExpand); } - if (addCdmaSubscription) { - log("Both NV and Ruim supported, ENABLE subscription type selection"); - mPrefScreen.addPreference(mButtonCdmaSubscription); - mButtonCdmaSubscription.setEnabled(true); - } else { - log("Both NV and Ruim NOT supported, REMOVE subscription type selection"); - mPrefScreen.removePreference(mButtonCdmaSubscription); - } - if (addCarrierSettings) { mPrefScreen.addPreference(mButtonCarrierSettings); } else { @@ -146,32 +132,6 @@ public class CdmaOptions { && config.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL); } - private boolean deviceSupportsNvAndRuim() { - // retrieve the list of subscription types supported by device. - String subscriptionsSupported = SystemProperties.get("ril.subscription.types"); - boolean nvSupported = false; - boolean ruimSupported = false; - - log("deviceSupportsnvAnRum: prop=" + subscriptionsSupported); - if (!TextUtils.isEmpty(subscriptionsSupported)) { - // Searches through the comma-separated list for a match for "NV" - // and "RUIM" to update nvSupported and ruimSupported. - for (String subscriptionType : subscriptionsSupported.split(",")) { - subscriptionType = subscriptionType.trim(); - if (subscriptionType.equalsIgnoreCase("NV")) { - nvSupported = true; - } - if (subscriptionType.equalsIgnoreCase("RUIM")) { - ruimSupported = true; - } - } - } - - log("deviceSupportsnvAnRum: nvSupported=" + nvSupported + - " ruimSupported=" + ruimSupported); - return (nvSupported && ruimSupported); - } - public boolean preferenceTreeClick(Preference preference) { if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) { log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true"); @@ -184,12 +144,6 @@ public class CdmaOptions { return false; } - public void showDialog(Preference preference) { - if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) { - mButtonCdmaSubscription.showDialog(null); - } - } - protected void log(String s) { android.util.Log.d(LOG_TAG, s); } diff --git a/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java b/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java deleted file mode 100644 index 559ba2d882a..00000000000 --- a/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.network.telephony; - -import android.content.Context; -import android.os.Bundle; -import androidx.preference.ListPreference; -import android.provider.Settings; -import android.telephony.TelephonyManager; -import android.util.AttributeSet; -import android.util.Log; - -import com.android.internal.telephony.Phone; -import com.android.settingslib.utils.ThreadUtils; - -public class CdmaSubscriptionListPreference extends ListPreference { - - private static final String LOG_TAG = "CdmaSubListPref"; - - // Used for CDMA subscription mode - private static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; - private static final int CDMA_SUBSCRIPTION_NV = 1; - - //preferredSubscriptionMode 0 - RUIM/SIM, preferred - // 1 - NV - static final int preferredSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION; - - private TelephonyManager mTelephonyManager; - - public CdmaSubscriptionListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - mTelephonyManager = TelephonyManager.from(context); - setCurrentCdmaSubscriptionModeValue(); - } - - private void setCurrentCdmaSubscriptionModeValue() { - int cdmaSubscriptionMode = Settings.Global.getInt(getContext().getContentResolver(), - Settings.Global.CDMA_SUBSCRIPTION_MODE, preferredSubscriptionMode); - setValue(Integer.toString(cdmaSubscriptionMode)); - } - - public CdmaSubscriptionListPreference(Context context) { - this(context, null); - } - - /** - * Sets the subscription id associated with this preference. - * - * @param subId the subscription id. - */ - public void setSubscriptionId(int subId) { - mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId); - } - - //TODO(b/114749736): move this logic to preference controller - protected void showDialog(Bundle state) { - setCurrentCdmaSubscriptionModeValue(); - } - - //TODO(b/114749736): move this logic to preference controller - protected void onDialogClosed(boolean positiveResult) { - if (!positiveResult) { - //The button was dismissed - no need to set new value - return; - } - - int buttonCdmaSubscriptionMode = Integer.parseInt(getValue()); - Log.d(LOG_TAG, "Setting new value " + buttonCdmaSubscriptionMode); - int statusCdmaSubscriptionMode; - switch(buttonCdmaSubscriptionMode) { - case CDMA_SUBSCRIPTION_NV: - statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_NV; - break; - case CDMA_SUBSCRIPTION_RUIM_SIM: - statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_RUIM_SIM; - break; - default: - statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION; - } - - // Set the CDMA subscription mode, when mode has been successfully changed, update the - // mode to the global setting. - ThreadUtils.postOnBackgroundThread(() -> { - // The subscription mode selected by user. - int cdmaSubscriptionMode = Integer.parseInt(getValue()); - - boolean isSuccessed = mTelephonyManager.setCdmaSubscriptionMode( - statusCdmaSubscriptionMode); - - // Update the global settings if successed. - if (isSuccessed) { - Settings.Global.putInt(getContext().getContentResolver(), - Settings.Global.CDMA_SUBSCRIPTION_MODE, - cdmaSubscriptionMode); - } else { - Log.e(LOG_TAG, "Setting Cdma subscription source failed"); - } - }); - } -} diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java index 3977cdd5f31..2fe79f82961 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java +++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java @@ -66,6 +66,7 @@ import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -162,6 +163,7 @@ public class MobileNetworkFragment extends DashboardFragment implements private DataUsagePreference mDataUsagePref; private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController; + private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController; private static final String iface = "rmnet0"; //TODO: this will go away private List mActiveSubInfos; @@ -400,6 +402,8 @@ public class MobileNetworkFragment extends DashboardFragment implements mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); + mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class); + mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId); } @Override @@ -724,15 +728,6 @@ public class MobileNetworkFragment extends DashboardFragment implements } } - /** - * Listen to extra preference changes that need as Metrics events logging. - */ - - if (prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) != null) { - prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) - .setOnPreferenceChangeListener(this); - } - // Get the networkMode from Settings.System and displays it mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode)); mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode)); @@ -1093,9 +1088,6 @@ public class MobileNetworkFragment extends DashboardFragment implements mVideoCallingPref.setEnabled(false); return false; } - } else if (preference == getPreferenceScreen() - .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) { - return true; } updateBody(); @@ -1431,11 +1423,13 @@ public class MobileNetworkFragment extends DashboardFragment implements EXTRA_EXIT_ECM_RESULT, false); if (isChoiceYes) { // If the phone exits from ECM mode, show the CDMA Options - if (TextUtils.equals(mClickedPreference.getKey(), + final String key = mClickedPreference.getKey(); + if (TextUtils.equals(key, mCdmaSystemSelectPreferenceController.getPreferenceKey())) { mCdmaSystemSelectPreferenceController.showDialog(); - } else { - mCdmaOptions.showDialog(mClickedPreference); + } else if (TextUtils.equals(key, + mCdmaSubscriptionPreferenceController.getPreferenceKey())) { + mCdmaSubscriptionPreferenceController.showDialog(); } } else { // do nothing diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java new file mode 100644 index 00000000000..49185a83949 --- /dev/null +++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java @@ -0,0 +1,108 @@ +/* + * 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.network.telephony.cdma; + +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.telephony.TelephonyManager; + +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.network.telephony.MobileNetworkUtils; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +/** + * Preference controller related to CDMA category + */ +public abstract class CdmaBasePreferenceController extends BasePreferenceController + implements LifecycleObserver, OnStart, OnStop { + + protected Preference mPreference; + protected TelephonyManager mTelephonyManager; + protected PreferenceManager mPreferenceManager; + protected int mSubId; + private DataContentObserver mDataContentObserver; + + public CdmaBasePreferenceController(Context context, String key) { + super(context, key); + mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); + } + + @Override + public void onStart() { + mDataContentObserver.register(mContext, mSubId); + } + + @Override + public void onStop() { + mDataContentObserver.unRegister(mContext); + } + + @Override + public int getAvailabilityStatus() { + return MobileNetworkUtils.isCdmaOptions(mContext, mSubId) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + public void init(PreferenceManager preferenceManager, int subId) { + mPreferenceManager = preferenceManager; + mSubId = subId; + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + /** + * Listener that listens to mobile data state change. + */ + public class DataContentObserver extends ContentObserver { + + public DataContentObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + updateState(mPreference); + } + + public void register(Context context, int subId) { + final Uri uri = Settings.Global.getUriFor( + Settings.Global.PREFERRED_NETWORK_MODE + subId); + context.getContentResolver().registerContentObserver(uri, false, this); + } + + public void unRegister(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + } +} diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java new file mode 100644 index 00000000000..eb14664f030 --- /dev/null +++ b/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java @@ -0,0 +1,110 @@ +/* + * 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.network.telephony.cdma; + +import android.content.Context; +import android.os.SystemProperties; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; + +import com.android.internal.telephony.Phone; +import com.android.settings.network.telephony.MobileNetworkUtils; + +/** + * Preference controller for "CDMA subscription" + */ +public class CdmaSubscriptionPreferenceController extends CdmaBasePreferenceController + implements ListPreference.OnPreferenceChangeListener { + private static final String TYPE_NV = "NV"; + private static final String TYPE_RUIM = "RUIM"; + + @VisibleForTesting + ListPreference mPreference; + + public CdmaSubscriptionPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return MobileNetworkUtils.isCdmaOptions(mContext, mSubId) && deviceSupportsNvAndRuim() + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final ListPreference listPreference = (ListPreference) preference; + listPreference.setVisible(getAvailabilityStatus() == AVAILABLE); + final int mode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION); + if (mode != Phone.CDMA_SUBSCRIPTION_UNKNOWN) { + listPreference.setValue(Integer.toString(mode)); + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object object) { + final int newMode = Integer.parseInt((String) object); + //TODO(b/117611981): only set it in one place + if (mTelephonyManager.setCdmaSubscriptionMode(newMode)) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, newMode); + return true; + } + + return false; + } + + public void showDialog() { + final int mode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION); + + mPreference.setValue(Integer.toString(mode)); + mPreferenceManager.showDialog(mPreference); + } + + @VisibleForTesting + boolean deviceSupportsNvAndRuim() { + // retrieve the list of subscription types supported by device. + final String subscriptionsSupported = SystemProperties.get("ril.subscription.types"); + boolean nvSupported = false; + boolean ruimSupported = false; + + if (!TextUtils.isEmpty(subscriptionsSupported)) { + // Searches through the comma-separated list for a match for "NV" + // and "RUIM" to update nvSupported and ruimSupported. + for (String subscriptionType : subscriptionsSupported.split(",")) { + subscriptionType = subscriptionType.trim(); + if (subscriptionType.equalsIgnoreCase(TYPE_NV)) { + nvSupported = true; + } else if (subscriptionType.equalsIgnoreCase(TYPE_RUIM)) { + ruimSupported = true; + } + } + } + + return (nvSupported && ruimSupported); + } +} diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java index 3d47feca83a..95e5dae4278 100644 --- a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java @@ -17,64 +17,20 @@ package com.android.settings.network.telephony.cdma; import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; import android.provider.Settings; import android.telephony.TelephonyManager; -import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; -import androidx.preference.PreferenceManager; -import androidx.preference.PreferenceScreen; - -import com.android.settings.core.BasePreferenceController; -import com.android.settings.network.telephony.MobileNetworkUtils; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "System Select" */ -public class CdmaSystemSelectPreferenceController extends BasePreferenceController - implements LifecycleObserver, OnStart, OnStop, ListPreference.OnPreferenceChangeListener { - - @VisibleForTesting - ListPreference mPreference; - private TelephonyManager mTelephonyManager; - private PreferenceManager mPreferenceManager; - private DataContentObserver mDataContentObserver; - private int mSubId; +public class CdmaSystemSelectPreferenceController extends CdmaBasePreferenceController + implements ListPreference.OnPreferenceChangeListener { public CdmaSystemSelectPreferenceController(Context context, String key) { super(context, key); - mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); - } - - @Override - public void onStart() { - mDataContentObserver.register(mContext, mSubId); - } - - @Override - public void onStop() { - mDataContentObserver.unRegister(mContext); - } - - @Override - public int getAvailabilityStatus() { - return MobileNetworkUtils.isCdmaOptions(mContext, mSubId) - ? AVAILABLE - : CONDITIONALLY_UNAVAILABLE; - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - mPreference = (ListPreference) screen.findPreference(getPreferenceKey()); } @Override @@ -106,12 +62,6 @@ public class CdmaSystemSelectPreferenceController extends BasePreferenceControll return false; } - public void init(PreferenceManager preferenceManager, int subId) { - mPreferenceManager = preferenceManager; - mSubId = subId; - mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); - } - public void showDialog() { if (!mTelephonyManager.getEmergencyCallbackMode()) { mPreferenceManager.showDialog(mPreference); @@ -119,37 +69,13 @@ public class CdmaSystemSelectPreferenceController extends BasePreferenceControll } private void resetCdmaRoamingModeToDefault() { + final ListPreference listPreference = (ListPreference) mPreference; //set the mButtonCdmaRoam - mPreference.setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY)); + listPreference.setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY)); //set the Settings.System Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.CDMA_ROAMING_MODE, TelephonyManager.CDMA_ROAMING_MODE_ANY); //Set the Status mTelephonyManager.setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_ANY); } - - /** - * Listener that listens mobile data state change. - */ - public class DataContentObserver extends ContentObserver { - - public DataContentObserver(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - updateState(mPreference); - } - - public void register(Context context, int subId) { - Uri uri = Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + subId); - context.getContentResolver().registerContentObserver(uri, false, this); - } - - public void unRegister(Context context) { - context.getContentResolver().unregisterContentObserver(this); - } - } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java new file mode 100644 index 00000000000..c938948a403 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java @@ -0,0 +1,121 @@ +/* + * 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.network.telephony.cdma; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.os.SystemProperties; +import android.provider.Settings; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceManager; + +import com.android.internal.telephony.Phone; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class CdmaSubscriptionPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private PreferenceManager mPreferenceManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mInvalidTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + + private CdmaSubscriptionPreferenceController mController; + private ListPreference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + mPreference = new ListPreference(mContext); + mController = new CdmaSubscriptionPreferenceController(mContext, "mobile_data"); + mController.init(mPreferenceManager, SUB_ID); + mController.mPreference = mPreference; + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void onPreferenceChange_selectNV_returnNVMode() { + doReturn(true).when(mTelephonyManager).setCdmaSubscriptionMode(anyInt()); + + mController.onPreferenceChange(mPreference, Integer.toString(Phone.CDMA_SUBSCRIPTION_NV)); + + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, + Phone.CDMA_SUBSCRIPTION_RUIM_SIM)).isEqualTo(Phone.CDMA_SUBSCRIPTION_NV); + } + + @Test + public void updateState_stateRUIM_displayRUIM() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.CDMA_SUBSCRIPTION_NV); + + mController.updateState(mPreference); + + assertThat(mPreference.getValue()).isEqualTo(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV)); + } + + @Test + public void updateState_stateUnknown_doNothing() { + mPreference.setValue(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV)); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.CDMA_SUBSCRIPTION_UNKNOWN); + + mController.updateState(mPreference); + + // Still NV mode + assertThat(mPreference.getValue()).isEqualTo(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV)); + } + + @Test + public void deviceSupportsNvAndRuim() { + SystemProperties.set("ril.subscription.types", "NV,RUIM"); + assertThat(mController.deviceSupportsNvAndRuim()).isTrue(); + + SystemProperties.set("ril.subscription.types", ""); + + assertThat(mController.deviceSupportsNvAndRuim()).isFalse(); + } +} From 2de3d28138c3c396380c320c974aec21ef877e70 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Thu, 11 Oct 2018 16:54:14 -0700 Subject: [PATCH 08/14] Refactor CdmaApnPreference Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I3d0203b7b5fb732e2814fb741761af4371924e9a --- res/xml/cdma_options.xml | 11 -- res/xml/network_setting_fragment.xml | 10 ++ .../network/telephony/CdmaOptions.java | 61 +-------- .../telephony/MobileNetworkFragment.java | 2 + .../cdma/CdmaApnPreferenceController.java | 87 +++++++++++++ .../cdma/CdmaBasePreferenceController.java | 4 + .../cdma/CdmaApnPreferenceControllerTest.java | 116 ++++++++++++++++++ 7 files changed, 221 insertions(+), 70 deletions(-) create mode 100644 src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml index b95e31b1e93..facc1d3294a 100644 --- a/res/xml/cdma_options.xml +++ b/res/xml/cdma_options.xml @@ -17,17 +17,6 @@ - - - - - - - diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 40d28dffcca..1a011b07fef 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -109,4 +109,14 @@ android:dialogTitle="@string/cdma_subscription_dialogtitle" settings:controller="com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController"/> + + + + + diff --git a/src/com/android/settings/network/telephony/CdmaOptions.java b/src/com/android/settings/network/telephony/CdmaOptions.java index 0e6c6c2b238..501746696c8 100644 --- a/src/com/android/settings/network/telephony/CdmaOptions.java +++ b/src/com/android/settings/network/telephony/CdmaOptions.java @@ -16,25 +16,15 @@ package com.android.settings.network.telephony; -import android.content.Intent; import android.os.PersistableBundle; -import android.os.SystemProperties; -import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; -import android.text.TextUtils; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.telephony.PhoneConstants; import com.android.settings.R; -import com.android.settingslib.RestrictedLockUtilsInternal; -import com.android.settingslib.RestrictedPreference; /** * List of Phone-specific settings screens. @@ -43,21 +33,18 @@ public class CdmaOptions { private static final String LOG_TAG = "CdmaOptions"; private CarrierConfigManager mCarrierConfigManager; - private RestrictedPreference mButtonAPNExpand; - private Preference mCategoryAPNExpand; private Preference mButtonCarrierSettings; private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key"; private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key"; private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key"; - private static final String BUTTON_APN_EXPAND_KEY = "button_cdma_apn_key"; - private static final String CATEGORY_APN_EXPAND_KEY = "category_cdma_apn_key"; private PreferenceFragmentCompat mPrefFragment; private PreferenceScreen mPrefScreen; private int mSubId; - public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen, int subId) { + public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen, + int subId) { mPrefFragment = prefFragment; mPrefScreen = prefScreen; mPrefFragment.addPreferencesFromResource(R.xml.cdma_options); @@ -65,20 +52,14 @@ public class CdmaOptions { // Initialize preferences. mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY); - mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY); - mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY); updateSubscriptionId(subId); } protected void updateSubscriptionId(int subId) { mSubId = subId; - int phoneType = TelephonyManager.from(mPrefFragment.getContext()) - .createForSubscriptionId(mSubId).getPhoneType(); PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); - // Some CDMA carriers want the APN settings. - boolean addAPNExpand = shouldAddApnExpandPreference(phoneType, carrierConfig); // Read platform settings for carrier settings boolean addCarrierSettings = carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL); @@ -86,34 +67,6 @@ public class CdmaOptions { // Making no assumptions of whether they are added or removed at this point. // Calling add or remove explicitly to make sure they are updated. - if (addAPNExpand) { - log("update: addAPNExpand"); - mButtonAPNExpand.setDisabledByAdmin( - MobileNetworkUtils.isDpcApnEnforced(mButtonAPNExpand.getContext()) - ? RestrictedLockUtilsInternal.getDeviceOwner( - mButtonAPNExpand.getContext()) - : null); - mButtonAPNExpand.setOnPreferenceClickListener( - new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - MetricsLogger.action(mButtonAPNExpand.getContext(), - MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS); - // We need to build the Intent by hand as the Preference Framework - // does not allow to add an Intent with some extras into a Preference - // XML file - final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS); - // This will setup the Home and Search affordance - intent.putExtra(":settings:show_fragment_as_subsetting", true); - intent.putExtra("sub_id", mSubId); - mPrefFragment.startActivity(intent); - return true; - } - }); - mPrefScreen.addPreference(mCategoryAPNExpand); - } else { - mPrefScreen.removePreference(mCategoryAPNExpand); - } if (addCarrierSettings) { mPrefScreen.addPreference(mButtonCarrierSettings); @@ -122,16 +75,6 @@ public class CdmaOptions { } } - /** - * Return whether we should add the APN expandable preference based on the phone type and - * carrier config - */ - @VisibleForTesting - public static boolean shouldAddApnExpandPreference(int phoneType, PersistableBundle config) { - return phoneType == PhoneConstants.PHONE_TYPE_CDMA - && config.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL); - } - public boolean preferenceTreeClick(Preference preference) { if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) { log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true"); diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java index 2fe79f82961..91b351eb2c5 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java +++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java @@ -66,6 +66,7 @@ import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.network.telephony.cdma.CdmaApnPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; @@ -399,6 +400,7 @@ public class MobileNetworkFragment extends DashboardFragment implements SubscriptionManager.INVALID_SUBSCRIPTION_ID); use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); + use(CdmaApnPreferenceController.class).init(mSubId); mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); diff --git a/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java new file mode 100644 index 00000000000..eaacdb2f0ec --- /dev/null +++ b/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java @@ -0,0 +1,87 @@ +/* + * 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.network.telephony.cdma; + +import android.content.Context; +import android.content.Intent; +import android.os.PersistableBundle; +import android.provider.Settings; +import android.telephony.CarrierConfigManager; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.SettingsActivity; +import com.android.settings.network.ApnSettings; +import com.android.settings.network.telephony.MobileNetworkUtils; +import com.android.settingslib.RestrictedLockUtilsInternal; +import com.android.settingslib.RestrictedPreference; + +/** + * Preference controller for "CDMA Apn" + */ +public class CdmaApnPreferenceController extends CdmaBasePreferenceController { + + private static final String CATEGORY_KEY = "category_cdma_apn_key"; + @VisibleForTesting + CarrierConfigManager mCarrierConfigManager; + + public CdmaApnPreferenceController(Context context, String key) { + super(context, key); + mCarrierConfigManager = new CarrierConfigManager(context); + } + + @Override + public int getAvailabilityStatus() { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); + + return carrierConfig != null + && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL) + && MobileNetworkUtils.isCdmaOptions(mContext, mSubId) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + if (isAvailable()) { + ((RestrictedPreference) mPreference).setDisabledByAdmin( + MobileNetworkUtils.isDpcApnEnforced(mContext) + ? RestrictedLockUtilsInternal.getDeviceOwner(mContext) + : null); + } else { + screen.findPreference(CATEGORY_KEY).setVisible(false); + } + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (getPreferenceKey().equals(preference.getKey())) { + // This activity runs in phone process, we must use intent to start + final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS); + // This will setup the Home and Search affordance + intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true); + intent.putExtra(ApnSettings.SUB_ID, mSubId); + mContext.startActivity(intent); + return true; + } + + return false; + } +} diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java index 49185a83949..3e9ebc66fc8 100644 --- a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java @@ -74,6 +74,10 @@ public abstract class CdmaBasePreferenceController extends BasePreferenceControl mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); } + public void init(int subId) { + init(null, subId); + } + @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); diff --git a/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java new file mode 100644 index 00000000000..2aceda7286b --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java @@ -0,0 +1,116 @@ +/* + * 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.network.telephony.cdma; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.content.Intent; +import android.os.PersistableBundle; +import android.provider.Settings; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.internal.telephony.PhoneConstants; +import com.android.settings.network.ApnSettings; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.RestrictedPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class CdmaApnPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mInvalidTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private CdmaApnPreferenceController mController; + private RestrictedPreference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + mPreference = new RestrictedPreference(mContext); + mController = new CdmaApnPreferenceController(mContext, "mobile_data"); + mController.init(SUB_ID); + mController.mPreference = mPreference; + mController.mCarrierConfigManager = mCarrierConfigManager; + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_apnSettingsNotSupported_returnUnavailable() { + doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType(); + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL, false); + doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_apnSettingsSupportedWithCDMA_returnAvailable() { + doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType(); + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL, true); + doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void handPreferenceTreeClick_fireIntent() { + ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); + + mController.handlePreferenceTreeClick(mPreference); + + verify(mContext).startActivity(captor.capture()); + final Intent intent = captor.getValue(); + assertThat(intent.getAction()).isEqualTo(Settings.ACTION_APN_SETTINGS); + assertThat(intent.getIntExtra(ApnSettings.SUB_ID, 0)).isEqualTo(SUB_ID); + } +} From 1d133e3f04b61afaced2d7a0a01b4a518819c2ea Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 12 Oct 2018 13:50:28 -0700 Subject: [PATCH 09/14] Refactor carrier settings Only show it when: 1. It is in CDMA or GSM mode 2. CarrierConfig tell settings to show it Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I45ecbc86c793ebec602142be208058e2043a2ba7 --- res/xml/cdma_options.xml | 26 ----- res/xml/gsm_umts_options.xml | 2 +- res/xml/network_setting_fragment.xml | 6 + .../CarrierPreferenceController.java | 68 +++++++++++ .../network/telephony/CdmaOptions.java | 38 +----- .../telephony/MobileNetworkFragment.java | 3 +- .../network/telephony/MobileNetworkUtils.java | 14 +++ .../CarrierPreferenceControllerTest.java | 108 ++++++++++++++++++ 8 files changed, 199 insertions(+), 66 deletions(-) delete mode 100644 res/xml/cdma_options.xml create mode 100644 src/com/android/settings/network/telephony/CarrierPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml deleted file mode 100644 index facc1d3294a..00000000000 --- a/res/xml/cdma_options.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml index f5439a4407e..1d1d4f3aa6f 100644 --- a/res/xml/gsm_umts_options.xml +++ b/res/xml/gsm_umts_options.xml @@ -27,7 +27,7 @@ android:title="@string/select_automatically" android:persistent="false"/> - diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 1a011b07fef..1de3ef7f33d 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -119,4 +119,10 @@ settings:controller="com.android.settings.network.telephony.cdma.CdmaApnPreferenceController"/> + + + diff --git a/src/com/android/settings/network/telephony/CarrierPreferenceController.java b/src/com/android/settings/network/telephony/CarrierPreferenceController.java new file mode 100644 index 00000000000..957eaaaa01a --- /dev/null +++ b/src/com/android/settings/network/telephony/CarrierPreferenceController.java @@ -0,0 +1,68 @@ +/* + * 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.network.telephony; + +import android.content.Context; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +/** + * Preference controller for "Carrier Settings" + */ +public class CarrierPreferenceController extends BasePreferenceController { + + @VisibleForTesting + CarrierConfigManager mCarrierConfigManager; + private int mSubId; + + public CarrierPreferenceController(Context context, String key) { + super(context, key); + mCarrierConfigManager = new CarrierConfigManager(context); + } + + public void init(int subId) { + mSubId = subId; + } + + @Override + public int getAvailabilityStatus() { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); + + // Return available if it is in CDMA or GSM mode, and the flag is on + return carrierConfig != null + && carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL) + && (MobileNetworkUtils.isCdmaOptions(mContext, mSubId) + || MobileNetworkUtils.isGsmOptions(mContext, mSubId)) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (getPreferenceKey().equals(preference.getKey())) { + //TODO(b/117651939): start carrier settings activity + return true; + } + + return false; + } +} diff --git a/src/com/android/settings/network/telephony/CdmaOptions.java b/src/com/android/settings/network/telephony/CdmaOptions.java index 501746696c8..c573128c40e 100644 --- a/src/com/android/settings/network/telephony/CdmaOptions.java +++ b/src/com/android/settings/network/telephony/CdmaOptions.java @@ -16,10 +16,6 @@ package com.android.settings.network.telephony; -import android.os.PersistableBundle; -import android.telephony.CarrierConfigManager; -import android.telephony.TelephonyManager; - import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; @@ -32,50 +28,18 @@ import com.android.settings.R; public class CdmaOptions { private static final String LOG_TAG = "CdmaOptions"; - private CarrierConfigManager mCarrierConfigManager; - private Preference mButtonCarrierSettings; - private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key"; private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key"; - private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key"; private PreferenceFragmentCompat mPrefFragment; - private PreferenceScreen mPrefScreen; - private int mSubId; public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen, int subId) { mPrefFragment = prefFragment; - mPrefScreen = prefScreen; - mPrefFragment.addPreferencesFromResource(R.xml.cdma_options); - mCarrierConfigManager = new CarrierConfigManager(prefFragment.getContext()); - - // Initialize preferences. - mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY); - - updateSubscriptionId(subId); - } - - protected void updateSubscriptionId(int subId) { - mSubId = subId; - - PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); - // Read platform settings for carrier settings - boolean addCarrierSettings = - carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL); - - // Making no assumptions of whether they are added or removed at this point. - // Calling add or remove explicitly to make sure they are updated. - - - if (addCarrierSettings) { - mPrefScreen.addPreference(mButtonCarrierSettings); - } else { - mPrefScreen.removePreference(mButtonCarrierSettings); - } } public boolean preferenceTreeClick(Preference preference) { + //TODO(b/114749736): handle it in preferenceController and remove this file if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) { log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true"); return true; diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java index 91b351eb2c5..518e59ba1e4 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java +++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java @@ -401,6 +401,7 @@ public class MobileNetworkFragment extends DashboardFragment implements use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); use(CdmaApnPreferenceController.class).init(mSubId); + use(CarrierPreferenceController.class).init(mSubId); mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); @@ -1798,8 +1799,6 @@ public class MobileNetworkFragment extends DashboardFragment implements // the open dialog gets dismissed or detached after pause / resume. if (mCdmaOptions == null) { mCdmaOptions = new CdmaOptions(prefFragment, prefScreen, subId); - } else { - mCdmaOptions.updateSubscriptionId(subId); } } diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index 666db1b5d99..8950178dd40 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -275,6 +275,20 @@ public class MobileNetworkUtils { return false; } + public static boolean isGsmOptions(Context context, int subId) { + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return false; + } + final TelephonyManager telephonyManager = TelephonyManager.from(context) + .createForSubscriptionId(subId); + + if (telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) { + return true; + } + + return false; + } + /** * Return {@code true} if it is world mode, and we may show advanced options in telephony * settings diff --git a/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java new file mode 100644 index 00000000000..e119e8990e0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java @@ -0,0 +1,108 @@ +/* + * 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.network.telephony; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.internal.telephony.PhoneConstants; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.RestrictedPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class CarrierPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mInvalidTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private CarrierPreferenceController mController; + private RestrictedPreference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + mPreference = new RestrictedPreference(mContext); + mController = new CarrierPreferenceController(mContext, "mobile_data"); + mController.init(SUB_ID); + mController.mCarrierConfigManager = mCarrierConfigManager; + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_cdmaWithFlagOff_returnUnavailable() { + doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType(); + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, false); + doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_cdmaWithFlagOnreturnAvailable() { + doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType(); + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, true); + doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_gsmWithFlagOnreturnAvailable() { + doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType(); + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, true); + doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } +} From 5680477b8b05baf821272799cfd8c57650fec9c8 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Mon, 15 Oct 2018 13:35:24 -0700 Subject: [PATCH 10/14] Refactor DataUsagePreference Move the logic to PreferenceController Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I7a0845c0cbc3f33e23257831d0d4ed97e7a5cc04 --- res/values/strings.xml | 3 + res/xml/network_setting_fragment.xml | 5 +- .../telephony/DataUsagePreference.java | 79 -------------- .../DataUsagePreferenceController.java | 100 +++++++++++++++++ .../telephony/MobileNetworkFragment.java | 14 +-- .../DataUsagePreferenceControllerTest.java | 102 ++++++++++++++++++ 6 files changed, 211 insertions(+), 92 deletions(-) delete mode 100644 src/com/android/settings/network/telephony/DataUsagePreference.java create mode 100644 src/com/android/settings/network/telephony/DataUsagePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 9ed8417f56f..ac8f305dbf1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10259,6 +10259,9 @@ Check with your network provider for pricing. + + App data usage + Unavailable when connected to %1$s diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 1de3ef7f33d..ce1644ff182 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -38,9 +38,10 @@ android:summaryOn="@string/roaming_enable" android:summaryOff="@string/roaming_disable"/> - + android:title="@string/mobile_data_usage_title" + settings:controller="com.android.settings.network.telephony.DataUsagePreferenceController"/> captor = ArgumentCaptor.forClass(Intent.class); + mController.handlePreferenceTreeClick(mPreference); + + verify(mContext).startActivity(captor.capture()); + final Intent intent = captor.getValue(); + + assertThat(intent.getAction()).isEqualTo(Settings.ACTION_MOBILE_DATA_USAGE); + assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID, 0)).isEqualTo(SUB_ID); + } + + @Test + public void updateState_invalidSubId_disabled() { + mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } +} From f896493c700075fefb90fe4f3a8330c1224c6629 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 16 Oct 2018 21:28:11 -0700 Subject: [PATCH 11/14] Import translations. DO NOT MERGE Auto-generated-cl: translation import Bug: 117801752 Change-Id: I43766c0d85af44370fa136fb4b54869ccfb9bdb4 --- res/values-ca/strings.xml | 2 +- res/values-fr-rCA/strings.xml | 2 +- res/values-mr/arrays.xml | 2 +- res/values-mr/strings.xml | 6 +++--- res/values-pa/strings.xml | 2 +- res/values-vi/strings.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 1ff64d7df10..dd23b453816 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -3965,7 +3965,7 @@ "Per veure l\'hora, les icones de notificació i altres dades, agafa el telèfon" "Per veure l\'hora, les icones de notificació i altres dades, agafa la tauleta" "Per veure l\'hora, les icones de notificació i altres dades, agafa el dispositiu." - "Fes lliscar el sensor d\'empremtes per veure notificacions" + "Llisca al sensor d\'empremtes per consultar les notificacions" "Fes lliscar l\'empremta digital" "Per consultar les notificacions, llisca cap avall al sensor d\'empremtes digitals de la part posterior del telèfon." "Per consultar les notificacions, llisca cap avall al sensor d\'empremtes digitals situat a la part posterior de la tauleta." diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 61002f3c984..cdac7361b82 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -1450,7 +1450,7 @@ "Rétablir les valeurs par défaut" "La réinitialisation des paramètres APN par défaut est terminée." "Options de réinitialisation" - "Impossible de réinitialiser le réseau, les applications ou l\'appareil" + "Vous pouvez réinitialiser le réseau, les applications ou l\'appareil" "Réinitialiser les paramètres Wi-Fi, cellulaires et Bluetooth" "Cette opération entraîne la réinitialisation de tous les paramètres réseau, y compris :\n\n"
  • "Le Wi‑Fi"
  • \n
  • "Les données cellulaires"
  • \n
  • "Le Bluetooth"
  • "Réinitialiser aussi la carte eSIM" diff --git a/res/values-mr/arrays.xml b/res/values-mr/arrays.xml index 9dec5a58926..ca7df6efe05 100644 --- a/res/values-mr/arrays.xml +++ b/res/values-mr/arrays.xml @@ -210,7 +210,7 @@ "IPv4/IPv6" - "निर्दिष्ट केले नाही" + "नमूद केले नाही" "LTE" "HSPAP" "HSPA" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 8d24e5dfa25..307581cf1b0 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -868,9 +868,9 @@ "सिस्टम प्रमाणपत्रे वापरा" "प्रदान करू नका" "प्रमाणित करू नका" - "कोणतेही प्रमाणपत्र निर्दिष्ट केले नाही. तुमचे कनेक्शन खाजगी होणार नाही." + "कोणतेही प्रमाणपत्र नमूद केले नाही. तुमचे कनेक्शन खाजगी होणार नाही." "नेटवर्कचे नाव फार लांबलचक आहे." - "एक डोमेन निर्दिष्ट करणे आवश्यक आहे." + "एक डोमेन नमूद करणे आवश्यक आहे." "WPS उपलब्ध" " (WPS उपलब्ध)" "तुमचा नेटवर्क पासवर्ड एंटर करा" @@ -2683,7 +2683,7 @@ "(सर्व्हरवरुन प्राप्त झालेले)" "हा VPN प्रकार सर्व वेळी कनेक्ट केलेला राहू शकत नाही" "नेहमी-चालू VPN केवळ अंकीय सर्व्हर पत्त्यांना समर्थित करतात" - "नेहमी-चालू VPN साठी DNS सर्व्हर निर्दिष्ट करणे आवश्यक आहे" + "नेहमी-चालू VPN साठी DNS सर्व्हर नमूद करणे आवश्यक आहे" "नेहमी-चालू VPN साठी DNS सर्व्हर पत्ते अंकीय असणे आवश्यक आहे" "एंटर केलेली माहिती नेहमी-चालू VPN ला समर्थित करत नाही" "रद्द करा" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 90b9fda0dad..4b78f024a95 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -393,7 +393,7 @@ "ਪਰਦੇਦਾਰੀ" "ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ" "ਸੁਰੱਖਿਆ ਸਥਿਤੀ" - "ਸਕ੍ਰੀਨ ਲਾਕ , ਫਿੰਗਰਪ੍ਰਿੰਟ" + "ਸਕ੍ਰੀਨ ਲਾਕ, ਫਿੰਗਰਪ੍ਰਿੰਟ" "ਸਕ੍ਰੀਨ ਲਾਕ" "ਫਿੰਗਰਪ੍ਰਿੰਟ" "ਫਿੰਗਰਪ੍ਰਿੰਟਸ ਵਿਵਸਥਿਤ ਕਰੋ" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 302a6cd26b8..74b0ae4ba2c 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -3526,7 +3526,7 @@ "(Mặc định của hệ thống)" "Bộ nhớ ứng dụng" "Truy cập dữ liệu sử dụng" - "Cho phép quyền truy cập sử dụng" + "Cho phép truy cập dữ liệu sử dụng" "Tùy chọn sử dụng ứng dụng" "Thời gian dùng ứng dụng" "Quyền truy cập vào dữ liệu sử dụng cho phép một ứng dụng theo dõi các ứng dụng khác mà bạn đang sử dụng và tần suất sử dụng cũng như thông tin nhà mạng, thông tin cài đặt ngôn ngữ và các chi tiết khác." From 60d0b3ce3bcd113fcc3c6d6aba64c9dd7ec96736 Mon Sep 17 00:00:00 2001 From: tmfang Date: Wed, 17 Oct 2018 00:59:06 +0800 Subject: [PATCH 12/14] Fix visible problem on status bar Battery Icon is not displayed on "Vision settings" screen Test: visual Change-Id: I272302af5b6e7309318c04b891d20526f68c5b0d Fixes: 117751096 --- res/values/themes_suw.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml index d66f917173b..e0d25c9cd4b 100644 --- a/res/values/themes_suw.xml +++ b/res/values/themes_suw.xml @@ -183,7 +183,6 @@