From 8fdf33d50a970107cc696ae6f8f9b0c1ecd40ee8 Mon Sep 17 00:00:00 2001 From: Niklas Lindgren Date: Fri, 21 Sep 2018 14:23:07 +0200 Subject: [PATCH 01/14] Start using CarrierConfig for 4G/LTE icon Icon will be updated on sim swap or in case the default data SIM changes. Test: Add configs in vendor xml and swap between sim cards. Tested on both single sim and dual sim. Bug: 113309356 Change-Id: I1847bcb4e6c1b6dcef7b14bce14f91bd3e4734a5 --- .../simstatus/SimStatusDialogController.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java index 9cea62d1e31..f273689abda 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java @@ -338,14 +338,10 @@ public class SimStatusDialogController implements LifecycleObserver, OnResume, O } boolean show4GForLTE = false; - try { - final Context con = mContext.createPackageContext( - "com.android.systemui", 0 /* flags */); - final int id = con.getResources().getIdentifier("config_show4GForLTE", - "bool" /* default type */, "com.android.systemui" /* default package */); - show4GForLTE = con.getResources().getBoolean(id); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "NameNotFoundException for show4GForLTE"); + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + if (carrierConfig != null) { + show4GForLTE = carrierConfig.getBoolean( + CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); } if (show4GForLTE) { From a6c927b51aae07e9b9523ca9c70487b2d0450d8f Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Sun, 30 Sep 2018 22:47:22 -0700 Subject: [PATCH 02/14] Fix Connect State message in Device details for Hearing Aids In the Device details of Settings App and when using two Hearing Aids devices (left and right sides), this will fix the connect state messages for these two devices. Also added Robo tests for the changes. Test: Manual tests and also ran RunSettingsLibRoboTests and RunSettingsRoboTests. Bug: 117074814 Bug: 116725094 Change-Id: I169cda4a1658b0a67cc7c7367b38d57a021e6953 Merged-In: I0b1a170967ddcce7f388603fd521f6ed1eeba30b Merged-In: I169cda4a1658b0a67cc7c7367b38d57a021e6953 --- .../BluetoothDetailsHeaderController.java | 14 ++++++++++---- .../BluetoothDetailsHeaderControllerTest.java | 11 ++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java index f9ecd8e3ee1..c445edf8b81 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java @@ -18,6 +18,7 @@ package com.android.settings.bluetooth; import android.content.Context; import android.graphics.drawable.Drawable; +import android.util.Log; import android.util.Pair; import androidx.preference.PreferenceFragment; @@ -36,6 +37,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle; */ public class BluetoothDetailsHeaderController extends BluetoothDetailsController { private static final String KEY_DEVICE_HEADER = "bluetooth_device_header"; + private static final String TAG = "BluetoothDetailsHeaderController"; private EntityHeaderController mHeaderController; private LocalBluetoothManager mLocalManager; @@ -63,12 +65,16 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController .getBtClassDrawableWithDescription(mContext, mCachedDevice, mContext.getResources().getFraction(R.fraction.bt_battery_scale_fraction, 1, 1)); String summaryText = mCachedDevice.getConnectionSummary(); - // If both the hearing aids are connected, two battery status should be shown. - final String pairDeviceSummary = mDeviceManager - .getHearingAidPairDeviceSummary(mCachedDevice); - if (pairDeviceSummary != null) { + + if (mCachedDevice.isHearingAidDevice()) { + // For Hearing Aid device, display the other battery status. + final String pairDeviceSummary = mDeviceManager + .getHearingAidPairDeviceSummary(mCachedDevice); + Log.d(TAG, "setHeaderProperties: HearingAid: summaryText=" + summaryText + + ", pairDeviceSummary=" + pairDeviceSummary); mHeaderController.setSecondSummary(pairDeviceSummary); } + mHeaderController.setLabel(mCachedDevice.getName()); mHeaderController.setIcon(pair.first); mHeaderController.setIconContentDescription(pair.second); diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java index 4d295e57ea1..7833effc838 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -96,7 +97,7 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro verify(mHeaderController).setIcon(any(Drawable.class)); verify(mHeaderController).setIconContentDescription(any(String.class)); verify(mHeaderController).setSummary(any(String.class)); - verify(mHeaderController).setSecondSummary(any(String.class)); + verify(mHeaderController, never()).setSecondSummary(any(String.class)); verify(mHeaderController).done(mActivity, true); } @@ -119,4 +120,12 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro inOrder.verify(mHeaderController) .setSummary(mContext.getString(R.string.bluetooth_connecting)); } + + @Test + public void testSecondSummary_isHearingAidDevice_showSecondSummary() { + when(mCachedDevice.isHearingAidDevice()).thenReturn(true); + showScreen(mController); + + verify(mHeaderController).setSecondSummary(any(String.class)); + } } From 8d9b26562046827a1a626fd1696efebae582cf34 Mon Sep 17 00:00:00 2001 From: Emily Chuang Date: Wed, 17 Oct 2018 20:50:20 +0800 Subject: [PATCH 03/14] Give SliceView a height to support four rows and show more button. The default height of sliceView with MODE_LARGE is 240dp which supports three rows(including the header) above "show more" button. Since WIFI and Connected devices use cases require four rows + show more button, we need to expand the height to fulfill it. Bug: 117868297 Test: visual Change-Id: I13b29c3f859d1c117c680432f9a6ad8e71c6acf5 --- res/layout/homepage_slice_tile.xml | 2 +- res/values/dimens.xml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml index b947d656097..4244460a961 100644 --- a/res/layout/homepage_slice_tile.xml +++ b/res/layout/homepage_slice_tile.xml @@ -30,7 +30,7 @@ 6dp 6dp + + 288dp + 24dp From 615f18e987eb83c9dc30417392faf343f90566fe Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 17 Oct 2018 16:27:41 -0700 Subject: [PATCH 04/14] Fix nav-up button in main settings activity. It should be a non-clickable search icon, not back button. Apparently the init code must be executed after setActionBar. Change-Id: Ibbc8aefeebc44562c6105cb51e6f6447a9705ff9 Fixes: 117797520 Test: manual --- src/com/android/settings/SettingsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 9106fe4e5fa..4bf7fac926b 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -296,9 +296,9 @@ public class SettingsActivity extends SettingsBaseActivity deviceProvisioned ? View.VISIBLE : View.INVISIBLE); findViewById(R.id.action_bar).setVisibility(View.GONE); final Toolbar toolbar = findViewById(R.id.search_action_bar); + setActionBar(toolbar); FeatureFactory.getFactory(this).getSearchFeatureProvider() .initSearchToolbar(this, toolbar); - setActionBar(toolbar); } ActionBar actionBar = getActionBar(); From 77b2a30e9df88a8c74123e2d74eeff2e8381f9ad Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Wed, 17 Oct 2018 22:46:54 +0800 Subject: [PATCH 05/14] Updated misc in Contextual Settings Homepage - Set static cards with full width and removed packageName from setName method. - Removed Storage card from createStaticCards method because it does not belong to default category. - Changed the parameter type of setSliceUri from String to Uri in ContextualCard. - Added StorageSlice and DeviceInfoSlice to the contextual card provider. - Fixed test cases related to these changes. bug: 117874766 Test: robotest Change-Id: Ic2dca353f85d0b6191ab19882dd8c5cb9c6cc658 --- .../settings/homepage/CardContentLoader.java | 22 +++++-------------- .../settings/homepage/ContextualCard.java | 4 ++-- .../SettingsContextualCardProvider.java | 16 +++++++++++++- .../homepage/deviceinfo/DataUsageSlice.java | 12 +++++----- .../homepage/deviceinfo/DeviceInfoSlice.java | 11 ++++------ .../homepage/deviceinfo/StorageSlice.java | 8 +++---- .../homepage/CardContentLoaderTest.java | 7 +++--- .../SettingsContextualCardProviderTest.java | 2 +- .../SliceContextualCardRendererTest.java | 3 ++- .../homepage/CardContentLoaderTest.java | 3 ++- 10 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/com/android/settings/homepage/CardContentLoader.java b/src/com/android/settings/homepage/CardContentLoader.java index 0b0d6c52e65..401e53cbbbb 100644 --- a/src/com/android/settings/homepage/CardContentLoader.java +++ b/src/com/android/settings/homepage/CardContentLoader.java @@ -34,7 +34,6 @@ import androidx.slice.Slice; import com.android.settings.homepage.deviceinfo.DataUsageSlice; import com.android.settings.homepage.deviceinfo.DeviceInfoSlice; -import com.android.settings.homepage.deviceinfo.StorageSlice; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.ArrayList; @@ -94,13 +93,13 @@ public class CardContentLoader extends AsyncLoaderCompat> { final double rankingScore = 0.0; final List result = new ArrayList() {{ add(new ContextualCard.Builder() - .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI.toString()) - .setName(packageName + "/" + DataUsageSlice.PATH_DATA_USAGE_CARD) + .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI) + .setName(DataUsageSlice.PATH_DATA_USAGE) .setPackageName(packageName) .setRankingScore(rankingScore) .setAppVersion(appVersionCode) .setCardType(ContextualCard.CardType.SLICE) - .setIsHalfWidth(true) + .setIsHalfWidth(false) .build()); //TODO(b/115971399): Will change following values of SliceUri and Name // after landing these slice cards. @@ -114,22 +113,13 @@ public class CardContentLoader extends AsyncLoaderCompat> { // .setIsHalfWidth(true) // .build()); add(new ContextualCard.Builder() - .setSliceUri(DeviceInfoSlice.DEVICE_INFO_CARD_URI.toString()) - .setName(packageName + "/" + DeviceInfoSlice.PATH_DEVICE_INFO_CARD) + .setSliceUri(DeviceInfoSlice.DEVICE_INFO_CARD_URI) + .setName(DeviceInfoSlice.PATH_DEVICE_INFO) .setPackageName(packageName) .setRankingScore(rankingScore) .setAppVersion(appVersionCode) .setCardType(ContextualCard.CardType.SLICE) - .setIsHalfWidth(true) - .build()); - add(new ContextualCard.Builder() - .setSliceUri(StorageSlice.STORAGE_CARD_URI.toString()) - .setName(StorageSlice.PATH_STORAGE_CARD) - .setPackageName(packageName) - .setRankingScore(rankingScore) - .setAppVersion(appVersionCode) - .setCardType(ContextualCard.CardType.SLICE) - .setIsHalfWidth(true) + .setIsHalfWidth(false) .build()); }}; return result; diff --git a/src/com/android/settings/homepage/ContextualCard.java b/src/com/android/settings/homepage/ContextualCard.java index 130b878f00e..bb83836fc1d 100644 --- a/src/com/android/settings/homepage/ContextualCard.java +++ b/src/com/android/settings/homepage/ContextualCard.java @@ -244,8 +244,8 @@ public class ContextualCard { return this; } - public Builder setSliceUri(String sliceUri) { - mSliceUri = sliceUri; + public Builder setSliceUri(Uri sliceUri) { + mSliceUri = sliceUri.toString(); return this; } diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java index 2dede95e758..d1c633f423c 100644 --- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java +++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java @@ -21,6 +21,8 @@ import static android.provider.SettingsSlicesContract.KEY_WIFI; import android.annotation.Nullable; import com.android.settings.homepage.deviceinfo.DataUsageSlice; +import com.android.settings.homepage.deviceinfo.DeviceInfoSlice; +import com.android.settings.homepage.deviceinfo.StorageSlice; import com.android.settings.intelligence.ContextualCardProto.ContextualCard; import com.android.settings.intelligence.ContextualCardProto.ContextualCardList; import com.android.settings.wifi.WifiSlice; @@ -43,11 +45,23 @@ public class SettingsContextualCardProvider extends ContextualCardProvider { final ContextualCard dataUsageCard = ContextualCard.newBuilder() .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI.toString()) - .setCardName(DataUsageSlice.PATH_DATA_USAGE_CARD) + .setCardName(DataUsageSlice.PATH_DATA_USAGE) + .build(); + final ContextualCard deviceInfoCard = + ContextualCard.newBuilder() + .setSliceUri(DeviceInfoSlice.DEVICE_INFO_CARD_URI.toString()) + .setCardName(DeviceInfoSlice.PATH_DEVICE_INFO) + .build(); + final ContextualCard storageInfoCard = + ContextualCard.newBuilder() + .setSliceUri(StorageSlice.STORAGE_CARD_URI.toString()) + .setCardName(StorageSlice.PATH_STORAGE_INFO) .build(); final ContextualCardList cards = ContextualCardList.newBuilder() .addCard(wifiCard) .addCard(dataUsageCard) + .addCard(deviceInfoCard) + .addCard(storageInfoCard) .build(); return cards; diff --git a/src/com/android/settings/homepage/deviceinfo/DataUsageSlice.java b/src/com/android/settings/homepage/deviceinfo/DataUsageSlice.java index d78b93de688..aebeaaeceb1 100644 --- a/src/com/android/settings/homepage/deviceinfo/DataUsageSlice.java +++ b/src/com/android/settings/homepage/deviceinfo/DataUsageSlice.java @@ -53,7 +53,7 @@ public class DataUsageSlice implements CustomSliceable { /** * The path denotes the unique name of data usage slice. */ - public static final String PATH_DATA_USAGE_CARD = "data_usage_card"; + public static final String PATH_DATA_USAGE = "data_usage_card"; /** * Backing Uri for the Data usage Slice. @@ -61,7 +61,7 @@ public class DataUsageSlice implements CustomSliceable { public static final Uri DATA_USAGE_CARD_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) - .appendPath(PATH_DATA_USAGE_CARD) + .appendPath(PATH_DATA_USAGE) .build(); private final Context mContext; @@ -88,8 +88,8 @@ public class DataUsageSlice implements CustomSliceable { final DataUsageController.DataUsageInfo info = dataUsageController.getDataUsageInfo(); final ListBuilder listBuilder = new ListBuilder(mContext, DATA_USAGE_CARD_URI, ListBuilder.INFINITY) - .setAccentColor(Utils.getColorAccentDefaultColor(mContext)) - .setHeader(new ListBuilder.HeaderBuilder().setTitle(title)); + .setAccentColor(Utils.getColorAccentDefaultColor(mContext)) + .setHeader(new ListBuilder.HeaderBuilder().setTitle(title)); if (DataUsageUtils.hasSim(mContext)) { listBuilder.addRow(new ListBuilder.RowBuilder() .setTitle(getDataUsageText(info)) @@ -106,9 +106,9 @@ public class DataUsageSlice implements CustomSliceable { @Override public Intent getIntent() { final String screenTitle = mContext.getText(R.string.data_usage_wifi_title).toString(); - final Uri contentUri = new Uri.Builder().appendPath(PATH_DATA_USAGE_CARD).build(); + final Uri contentUri = new Uri.Builder().appendPath(PATH_DATA_USAGE).build(); return SliceBuilderUtils.buildSearchResultPageIntent(mContext, - DataUsageSummary.class.getName(), PATH_DATA_USAGE_CARD, screenTitle, + DataUsageSummary.class.getName(), PATH_DATA_USAGE, screenTitle, MetricsProto.MetricsEvent.SLICE) .setClassName(mContext.getPackageName(), SubSettings.class.getName()) .setData(contentUri); diff --git a/src/com/android/settings/homepage/deviceinfo/DeviceInfoSlice.java b/src/com/android/settings/homepage/deviceinfo/DeviceInfoSlice.java index dc315c53515..ded48984fba 100644 --- a/src/com/android/settings/homepage/deviceinfo/DeviceInfoSlice.java +++ b/src/com/android/settings/homepage/deviceinfo/DeviceInfoSlice.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.net.Uri; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.text.TextUtils; @@ -53,7 +52,7 @@ public class DeviceInfoSlice implements CustomSliceable { /** * The path denotes the unique name of device info slice */ - public static final String PATH_DEVICE_INFO_CARD = "device_info_card"; + public static final String PATH_DEVICE_INFO = "device_info_card"; /** * Backing Uri for the Device info Slice. @@ -61,16 +60,14 @@ public class DeviceInfoSlice implements CustomSliceable { public static final Uri DEVICE_INFO_CARD_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) - .appendPath(PATH_DEVICE_INFO_CARD) + .appendPath(PATH_DEVICE_INFO) .build(); private final Context mContext; - private final TelephonyManager mTelephonyManager; private final SubscriptionManager mSubscriptionManager; public DeviceInfoSlice(Context context) { mContext = context; - mTelephonyManager = mContext.getSystemService(TelephonyManager.class); mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); } @@ -101,9 +98,9 @@ public class DeviceInfoSlice implements CustomSliceable { @Override public Intent getIntent() { final String screenTitle = mContext.getText(R.string.device_info_label).toString(); - final Uri contentUri = new Uri.Builder().appendPath(PATH_DEVICE_INFO_CARD).build(); + final Uri contentUri = new Uri.Builder().appendPath(PATH_DEVICE_INFO).build(); return SliceBuilderUtils.buildSearchResultPageIntent(mContext, - MyDeviceInfoFragment.class.getName(), PATH_DEVICE_INFO_CARD, screenTitle, + MyDeviceInfoFragment.class.getName(), PATH_DEVICE_INFO, screenTitle, MetricsProto.MetricsEvent.SLICE) .setClassName(mContext.getPackageName(), SubSettings.class.getName()) .setData(contentUri); diff --git a/src/com/android/settings/homepage/deviceinfo/StorageSlice.java b/src/com/android/settings/homepage/deviceinfo/StorageSlice.java index c9464e40061..0f95c57fa03 100644 --- a/src/com/android/settings/homepage/deviceinfo/StorageSlice.java +++ b/src/com/android/settings/homepage/deviceinfo/StorageSlice.java @@ -48,7 +48,7 @@ public class StorageSlice implements CustomSliceable { /** * The path denotes the unique name of storage slicel */ - public static final String PATH_STORAGE_CARD = "storage_card"; + public static final String PATH_STORAGE_INFO = "storage_card"; /** * Backing Uri for the storage slice. @@ -56,7 +56,7 @@ public class StorageSlice implements CustomSliceable { public static final Uri STORAGE_CARD_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) - .appendPath(PATH_STORAGE_CARD) + .appendPath(PATH_STORAGE_INFO) .build(); private final Context mContext; @@ -93,9 +93,9 @@ public class StorageSlice implements CustomSliceable { @Override public Intent getIntent() { final String screenTitle = mContext.getText(R.string.storage_label).toString(); - final Uri contentUri = new Uri.Builder().appendPath(PATH_STORAGE_CARD).build(); + final Uri contentUri = new Uri.Builder().appendPath(PATH_STORAGE_INFO).build(); return SliceBuilderUtils.buildSearchResultPageIntent(mContext, - StorageDashboardFragment.class.getName(), PATH_STORAGE_CARD, screenTitle, + StorageDashboardFragment.class.getName(), PATH_STORAGE_INFO, screenTitle, MetricsProto.MetricsEvent.SLICE) .setClassName(mContext.getPackageName(), SubSettings.class.getName()) .setData(contentUri); diff --git a/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java index defe0d9f759..a7527f37b1f 100644 --- a/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java @@ -57,15 +57,14 @@ public class CardContentLoaderTest { public void createStaticCards_shouldReturnTwoCards() { final List defaultData = mCardContentLoader.createStaticCards(); - assertThat(defaultData).hasSize(3); + assertThat(defaultData).hasSize(2); } @Test public void createStaticCards_shouldContainDataUsageAndDeviceInfo() { final Uri dataUsage = DataUsageSlice.DATA_USAGE_CARD_URI; final Uri deviceInfo = DeviceInfoSlice.DEVICE_INFO_CARD_URI; - final Uri storageInfo = StorageSlice.STORAGE_CARD_URI; - final List expectedUris = Arrays.asList(dataUsage, deviceInfo, storageInfo); + final List expectedUris = Arrays.asList(dataUsage, deviceInfo); final List actualCardUris = mCardContentLoader.createStaticCards().stream().map( ContextualCard::getSliceUri).collect(Collectors.toList()); @@ -105,7 +104,7 @@ public class CardContentLoaderTest { return new ContextualCard.Builder() .setName("test_card") .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(sliceUri) + .setSliceUri(Uri.parse(sliceUri)) .build(); } } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java index a80b963c594..fbc91114883 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java @@ -58,6 +58,6 @@ public class SettingsContextualCardProviderTest { final ContextualCardList cards = ContextualCardList.parseFrom( returnValue.getByteArray(ContextualCardProvider.BUNDLE_CARD_LIST)); - assertThat(cards.getCardCount()).isEqualTo(2); + assertThat(cards.getCardCount()).isEqualTo(4); } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java index c597a6e4fb0..c5ca8d79487 100644 --- a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java +++ b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import android.content.Context; +import android.net.Uri; import android.view.LayoutInflater; import android.view.View; @@ -108,7 +109,7 @@ public class SliceContextualCardRendererTest { private ContextualCard buildContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName("test_name") - .setSliceUri(sliceUri) + .setSliceUri(Uri.parse(sliceUri)) .build(); } } diff --git a/tests/unit/src/com/android/settings/homepage/CardContentLoaderTest.java b/tests/unit/src/com/android/settings/homepage/CardContentLoaderTest.java index 1f762bbf0ec..38a1f5a65b0 100644 --- a/tests/unit/src/com/android/settings/homepage/CardContentLoaderTest.java +++ b/tests/unit/src/com/android/settings/homepage/CardContentLoaderTest.java @@ -19,6 +19,7 @@ package com.android.settings.homepage; import static com.google.common.truth.Truth.assertThat; import android.content.Context; +import android.net.Uri; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; @@ -61,7 +62,7 @@ public class CardContentLoaderTest { return new ContextualCard.Builder() .setName("test_card") .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(sliceUri) + .setSliceUri(Uri.parse(sliceUri)) .build(); } } From e8a56c183a9f703a55eb4237886e0bcb0d70dd18 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 16 Oct 2018 14:20:46 -0700 Subject: [PATCH 06/14] Refactor PreferredNetworkModePreference Create preference controller for it. Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I456b0b954f47a6fb4c03926049b0579fd6488969 --- res/xml/network_setting_fragment.xml | 3 +- .../telephony/MobileNetworkFragment.java | 297 +----------------- ...ferredNetworkModePreferenceController.java | 183 +++++++++++ ...edNetworkModePreferenceControllerTest.java | 144 +++++++++ 4 files changed, 335 insertions(+), 292 deletions(-) create mode 100644 src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 74e03ed9f15..6cfa0a3aefa 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -57,7 +57,8 @@ android:summary="@string/preferred_network_mode_summary" android:entries="@array/preferred_network_mode_choices" android:entryValues="@array/preferred_network_mode_values" - android:dialogTitle="@string/preferred_network_mode_dialogtitle" /> + android:dialogTitle="@string/preferred_network_mode_dialogtitle" + settings:controller="com.android.settings.network.telephony.PreferredNetworkModePreferenceController"/> newSil) { - TabState state = TabState.DO_NOTHING; - if (newSil == null) { - if (mActiveSubInfos.size() >= TAB_THRESHOLD) { - if (DBG) log("isUpdateTabsNeeded: NO_TABS, size unknown and was tabbed"); - state = TabState.NO_TABS; - } - } else if (newSil.size() < TAB_THRESHOLD && mActiveSubInfos.size() >= TAB_THRESHOLD) { - if (DBG) log("isUpdateTabsNeeded: NO_TABS, size went to small"); - state = TabState.NO_TABS; - } else if (newSil.size() >= TAB_THRESHOLD && mActiveSubInfos.size() < TAB_THRESHOLD) { - if (DBG) log("isUpdateTabsNeeded: UPDATE, size changed"); - state = TabState.UPDATE; - } else if (newSil.size() >= TAB_THRESHOLD) { - Iterator siIterator = mActiveSubInfos.iterator(); - for(SubscriptionInfo newSi : newSil) { - SubscriptionInfo curSi = siIterator.next(); - if (!newSi.getDisplayName().equals(curSi.getDisplayName())) { - if (DBG) log("isUpdateTabsNeeded: UPDATE, new name=" - + newSi.getDisplayName()); - state = TabState.UPDATE; - break; - } - } - } - if (DBG) { - Log.i(LOG_TAG, "isUpdateTabsNeeded:- " + state - + " newSil.size()=" + ((newSil != null) ? newSil.size() : 0) - + " mActiveSubInfos.size()=" + mActiveSubInfos.size()); - } - return state; - } - private void updatePhone() { if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { mImsMgr = ImsManager.getInstance(getContext(), @@ -389,6 +305,7 @@ public class MobileNetworkFragment extends DashboardFragment implements use(CdmaApnPreferenceController.class).init(mSubId); use(CarrierPreferenceController.class).init(mSubId); use(DataUsagePreferenceController.class).init(mSubId); + use(PreferredNetworkModePreferenceController.class).init(mSubId); mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); @@ -433,9 +350,6 @@ public class MobileNetworkFragment extends DashboardFragment implements //get UI object references PreferenceScreen prefSet = getPreferenceScreen(); - - mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference( - BUTTON_PREFERED_NETWORK_MODE); mButtonEnabledNetworks = (ListPreference) prefSet.findPreference( BUTTON_ENABLED_NETWORKS_KEY); @@ -597,8 +511,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (DBG) { log("updateBody: isLteOnCdma=" + isLteOnCdma + " phoneSubId=" + phoneSubId); } - - prefSet.addPreference(mButtonPreferredNetworkMode); prefSet.addPreference(mButtonEnabledNetworks); prefSet.addPreference(mButton4glte); @@ -622,7 +534,6 @@ public class MobileNetworkFragment extends DashboardFragment implements && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); if (carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) { - prefSet.removePreference(mButtonPreferredNetworkMode); prefSet.removePreference(mButtonEnabledNetworks); prefSet.removePreference(mLteDataServicePref); } else if (carrierConfig.getBoolean(CarrierConfigManager @@ -630,7 +541,6 @@ public class MobileNetworkFragment extends DashboardFragment implements && !mTelephonyManager.getServiceState().getRoaming() && mTelephonyManager.getServiceState().getDataRegState() == ServiceState.STATE_IN_SERVICE) { - prefSet.removePreference(mButtonPreferredNetworkMode); prefSet.removePreference(mButtonEnabledNetworks); final int phoneType = mTelephonyManager.getPhoneType(); @@ -650,12 +560,10 @@ public class MobileNetworkFragment extends DashboardFragment implements prefSet.removePreference(mButtonEnabledNetworks); // set the listener for the mButtonPreferredNetworkMode list preference so we can issue // change Preferred Network Mode. - mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this); updateCdmaOptions(this, prefSet, mSubId); updateGsmUmtsOptions(this, prefSet, phoneSubId); } else { - prefSet.removePreference(mButtonPreferredNetworkMode); updateEnabledNetworksEntries(); mButtonEnabledNetworks.setOnPreferenceChangeListener(this); if (DBG) log("settingsNetworkMode: " + settingsNetworkMode); @@ -688,8 +596,6 @@ public class MobileNetworkFragment extends DashboardFragment implements // Get the networkMode from Settings.System and displays it mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode)); - mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode)); - UpdatePreferredNetworkModeSummary(settingsNetworkMode); UpdateEnabledNetworksValueAndSummary(settingsNetworkMode); // Display preferred network type based on what modem returns b/18676277 new SetPreferredNetworkAsyncTask( @@ -886,64 +792,7 @@ public class MobileNetworkFragment extends DashboardFragment implements sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue); final int phoneSubId = mSubId; - if (preference == mButtonPreferredNetworkMode) { - //NOTE onPreferenceChange seems to be called even if there is no change - //Check if the button value is changed from the System.Setting - mButtonPreferredNetworkMode.setValue((String) objValue); - int buttonNetworkMode; - buttonNetworkMode = Integer.parseInt((String) objValue); - int settingsNetworkMode = android.provider.Settings.Global.getInt( - getContext().getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId, - preferredNetworkMode); - if (buttonNetworkMode != settingsNetworkMode) { - int modemNetworkMode; - // if new mode is invalid ignore it - switch (buttonNetworkMode) { - case TelephonyManager.NETWORK_MODE_WCDMA_PREF: - case TelephonyManager.NETWORK_MODE_GSM_ONLY: - case TelephonyManager.NETWORK_MODE_WCDMA_ONLY: - case TelephonyManager.NETWORK_MODE_GSM_UMTS: - case TelephonyManager.NETWORK_MODE_CDMA_EVDO: - case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO: - case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA: - case TelephonyManager.NETWORK_MODE_GLOBAL: - case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO: - case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_ONLY: - case TelephonyManager.NETWORK_MODE_LTE_WCDMA: - case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY: - case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA: - case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM: - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM: - case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA: - case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: - // This is one of the modes we recognize - modemNetworkMode = buttonNetworkMode; - break; - default: - loge("Invalid Network Mode (" +buttonNetworkMode+ ") chosen. Ignore."); - return true; - } - - android.provider.Settings.Global.putInt( - getContext().getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId, - buttonNetworkMode ); - //Set the modem network mode - new SetPreferredNetworkAsyncTask( - mTelephonyManager, - mSubId, - modemNetworkMode, - mHandler.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE)) - .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - } else if (preference == mButtonEnabledNetworks) { + if (preference == mButtonEnabledNetworks) { mButtonEnabledNetworks.setValue((String) objValue); int buttonNetworkMode; buttonNetworkMode = Integer.parseInt((String) objValue); @@ -1051,15 +900,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (success) { int networkMode; - if (getPreferenceScreen().findPreference( - BUTTON_PREFERED_NETWORK_MODE) != null) { - networkMode = Integer.parseInt(mButtonPreferredNetworkMode.getValue()); - android.provider.Settings.Global.putInt( - getContext().getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE - + mSubId, - networkMode ); - } if (getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null) { networkMode = Integer.parseInt(mButtonEnabledNetworks.getValue()); android.provider.Settings.Global.putInt( @@ -1087,126 +927,7 @@ public class MobileNetworkFragment extends DashboardFragment implements settingsNetworkMode); } - UpdatePreferredNetworkModeSummary(settingsNetworkMode); UpdateEnabledNetworksValueAndSummary(settingsNetworkMode); - // changes the mButtonPreferredNetworkMode accordingly to settingsNetworkMode - mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode)); - } - - private void UpdatePreferredNetworkModeSummary(int NetworkMode) { - switch(NetworkMode) { - case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_tdscdma_gsm_summary); - break; - case TelephonyManager.NETWORK_MODE_WCDMA_PREF: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_wcdma_perf_summary); - break; - case TelephonyManager.NETWORK_MODE_GSM_ONLY: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_gsm_only_summary); - break; - case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_tdscdma_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_WCDMA_ONLY: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_wcdma_only_summary); - break; - case TelephonyManager.NETWORK_MODE_GSM_UMTS: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_CDMA_EVDO: - switch (mTelephonyManager.getLteOnCdmaMode()) { - case PhoneConstants.LTE_ON_CDMA_TRUE: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_cdma_summary); - break; - case PhoneConstants.LTE_ON_CDMA_FALSE: - default: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_cdma_evdo_summary); - break; - } - break; - case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_cdma_only_summary); - break; - case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_evdo_only_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_tdscdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_ONLY: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_tdscdma_gsm_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_tdscdma_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_cdma_evdo_summary); - break; - case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_tdscdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA: - if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA - || mIsGlobalCdma - || isWorldMode()) { - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_global_summary); - } else { - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_summary); - } - break; - case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_GLOBAL: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_cdma_evdo_gsm_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_tdscdma_wcdma_summary); - break; - case TelephonyManager.NETWORK_MODE_LTE_WCDMA: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_lte_wcdma_summary); - break; - default: - mButtonPreferredNetworkMode.setSummary( - R.string.preferred_network_mode_global_summary); - } } private void UpdateEnabledNetworksValueAndSummary(int NetworkMode) { @@ -1477,9 +1198,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (mButtonEnabledNetworks != null) { mButtonEnabledNetworks.setEnabled(enabled); } - if (mButtonPreferredNetworkMode != null) { - mButtonPreferredNetworkMode.setEnabled(enabled); - } } private void updateCallingCategory() { @@ -1622,7 +1340,7 @@ public class MobileNetworkFragment extends DashboardFragment implements // new value in onPreferenceChange. if (preference == mLteDataServicePref || preference == mEuiccSettingsPref - || preference == mWiFiCallingPref || preference == mButtonPreferredNetworkMode + || preference == mWiFiCallingPref || preference == mButtonEnabledNetworks || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) @@ -1643,8 +1361,7 @@ public class MobileNetworkFragment extends DashboardFragment implements // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences. if (preference == mButton4glte || preference == mVideoCallingPref) { MetricsLogger.action(getContext(), category, (Boolean) newValue); - } else if (preference == mButtonPreferredNetworkMode - || preference == mButtonEnabledNetworks + } else if (preference == mButtonEnabledNetworks || preference == preferenceScreen .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) || preference == preferenceScreen @@ -1663,8 +1380,6 @@ public class MobileNetworkFragment extends DashboardFragment implements return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SET_UP_DATA_SERVICE; } else if (preference == mButton4glte) { return MetricsProto.MetricsEvent.ACTION_MOBILE_ENHANCED_4G_LTE_MODE_TOGGLE; - } else if (preference == mButtonPreferredNetworkMode) { - return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_PREFERRED_NETWORK; } else if (preference == mButtonEnabledNetworks) { return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_ENABLED_NETWORK; } else if (preference == mEuiccSettingsPref) { diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java new file mode 100644 index 00000000000..f60f927a32e --- /dev/null +++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java @@ -0,0 +1,183 @@ +/* + * 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.provider.Settings; +import android.telephony.CarrierConfigManager; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; + +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.PhoneConstants; +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +/** + * Preference controller for "Preferred network mode" + */ +public class PreferredNetworkModePreferenceController extends BasePreferenceController implements + ListPreference.OnPreferenceChangeListener { + + private CarrierConfigManager mCarrierConfigManager; + private TelephonyManager mTelephonyManager; + private PersistableBundle mPersistableBundle; + private int mSubId; + private boolean mIsGlobalCdma; + + public PreferredNetworkModePreferenceController(Context context, String key) { + super(context, key); + mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + boolean visible; + if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + visible = false; + } else if (mPersistableBundle == null) { + visible = false; + } else if (mPersistableBundle.getBoolean( + CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) { + visible = false; + } else if (mPersistableBundle.getBoolean( + CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL) + && !mTelephonyManager.getServiceState().getRoaming() + && mTelephonyManager.getServiceState().getDataRegState() + == ServiceState.STATE_IN_SERVICE) { + visible = false; + } else if (mPersistableBundle.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { + visible = true; + } else { + visible = false; + } + + return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final ListPreference listPreference = (ListPreference) preference; + final int networkMode = getPreferredNetworkMode(); + listPreference.setValue(Integer.toString(networkMode)); + listPreference.setSummary(getPreferredNetworkModeSummaryResId(networkMode)); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object object) { + final int settingsMode = Integer.parseInt((String) object); + + if (mTelephonyManager.setPreferredNetworkType(mSubId, settingsMode)) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + mSubId, + settingsMode); + return true; + } + + return false; + } + + public void init(int subId) { + mSubId = subId; + mPersistableBundle = mCarrierConfigManager.getConfigForSubId(mSubId); + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + + final boolean isLteOnCdma = + mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE; + mIsGlobalCdma = isLteOnCdma + && mPersistableBundle.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); + } + + private int getPreferredNetworkMode() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + mSubId, + Phone.PREFERRED_NT_MODE); + } + + private int getPreferredNetworkModeSummaryResId(int NetworkMode) { + //TODO(b/114749736): refactor it to "Preferred network mode: ", instead of building + // string for each type... + switch (NetworkMode) { + case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA: + return R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM: + return R.string.preferred_network_mode_tdscdma_gsm_summary; + case TelephonyManager.NETWORK_MODE_WCDMA_PREF: + return R.string.preferred_network_mode_wcdma_perf_summary; + case TelephonyManager.NETWORK_MODE_GSM_ONLY: + return R.string.preferred_network_mode_gsm_only_summary; + case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA: + return R.string.preferred_network_mode_tdscdma_wcdma_summary; + case TelephonyManager.NETWORK_MODE_WCDMA_ONLY: + return R.string.preferred_network_mode_wcdma_only_summary; + case TelephonyManager.NETWORK_MODE_GSM_UMTS: + return R.string.preferred_network_mode_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_CDMA_EVDO: + switch (mTelephonyManager.getLteOnCdmaMode()) { + case PhoneConstants.LTE_ON_CDMA_TRUE: + return R.string.preferred_network_mode_cdma_summary; + default: + return R.string.preferred_network_mode_cdma_evdo_summary; + } + case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO: + return R.string.preferred_network_mode_cdma_only_summary; + case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA: + return R.string.preferred_network_mode_evdo_only_summary; + case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA: + return R.string.preferred_network_mode_lte_tdscdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_ONLY: + return R.string.preferred_network_mode_lte_summary; + case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM: + return R.string.preferred_network_mode_lte_tdscdma_gsm_summary; + case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA: + return R.string.preferred_network_mode_lte_tdscdma_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA: + return R.string.preferred_network_mode_lte_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO: + return R.string.preferred_network_mode_lte_cdma_evdo_summary; + case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY: + return R.string.preferred_network_mode_tdscdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: + return R.string.preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA: + if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA + || mIsGlobalCdma + || MobileNetworkUtils.isWorldMode(mContext, mSubId)) { + return R.string.preferred_network_mode_global_summary; + } else { + return R.string.preferred_network_mode_lte_summary; + } + case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: + return R.string.preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_GLOBAL: + return R.string.preferred_network_mode_cdma_evdo_gsm_wcdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA: + return R.string.preferred_network_mode_lte_tdscdma_wcdma_summary; + case TelephonyManager.NETWORK_MODE_LTE_WCDMA: + return R.string.preferred_network_mode_lte_wcdma_summary; + default: + return R.string.preferred_network_mode_global_summary; + } + } +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java new file mode 100644 index 00000000000..d11e11c185b --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java @@ -0,0 +1,144 @@ +/* + * 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.provider.Settings; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.fragment.app.FragmentManager; +import androidx.preference.ListPreference; + +import com.android.settings.R; +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 PreferredNetworkModePreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private FragmentManager mFragmentManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mInvalidTelephonyManager; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private PersistableBundle mPersistableBundle; + private PreferredNetworkModePreferenceController 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(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class); + doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + mPersistableBundle = new PersistableBundle(); + doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + mPreference = new ListPreference(mContext); + mPreference.setEntries(R.array.preferred_network_mode_choices); + mPreference.setEntryValues(R.array.preferred_network_mode_values); + mController = new PreferredNetworkModePreferenceController(mContext, "mobile_data"); + mController.init(SUB_ID); + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() { + mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, + true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_worldPhone_returnAvailable() { + mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, + false); + mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void updateState_updateByNetworkMode() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, + TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA); + + mController.updateState(mPreference); + + assertThat(mPreference.getValue()).isEqualTo( + String.valueOf(TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA)); + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getString(R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary)); + } + + @Test + public void onPreferenceChange_updateSuccess() { + doReturn(true).when(mTelephonyManager).setPreferredNetworkType(SUB_ID, + TelephonyManager.NETWORK_MODE_LTE_TDSCDMA); + + mController.onPreferenceChange(mPreference, + String.valueOf(TelephonyManager.NETWORK_MODE_LTE_TDSCDMA)); + + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isEqualTo( + TelephonyManager.NETWORK_MODE_LTE_TDSCDMA); + } + + @Test + public void onPreferenceChange_updateFail() { + doReturn(false).when(mTelephonyManager).setPreferredNetworkType(SUB_ID, + TelephonyManager.NETWORK_MODE_LTE_TDSCDMA); + + mController.onPreferenceChange(mPreference, + String.valueOf(TelephonyManager.NETWORK_MODE_LTE_TDSCDMA)); + + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isNotEqualTo( + TelephonyManager.NETWORK_MODE_LTE_TDSCDMA); + } + +} From 0057c4127cd7ce9435ca65be9cef6919695dc1b4 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Mon, 15 Oct 2018 19:41:10 +0800 Subject: [PATCH 07/14] Added the EmergencyInfoSlice for ContextualHomepage - Generated a simple EmergencyInfo slice with fixed string in title and summary. - Moved hardcode string into strings.xml - Modified the contentProviderCall_returnCorrectSize test case for general version Bug: 114793520 Test: compile and manual test Change-Id: Ia3444c61b0f7e4c04794fe3590dc0731885cf062 --- res/values/strings.xml | 3 + .../SettingsContextualCardProvider.java | 7 ++ .../deviceinfo/EmergencyInfoSlice.java | 77 +++++++++++++++++++ .../slices/SettingsSliceProvider.java | 5 ++ .../SettingsContextualCardProviderTest.java | 11 ++- 5 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/com/android/settings/homepage/deviceinfo/EmergencyInfoSlice.java diff --git a/res/values/strings.xml b/res/values/strings.xml index ac8f305dbf1..183eca4295d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10264,4 +10264,7 @@ Unavailable when connected to %1$s + + + Medical info, emergency contacts diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java index d1c633f423c..26f86b9da5e 100644 --- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java +++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import com.android.settings.homepage.deviceinfo.DataUsageSlice; import com.android.settings.homepage.deviceinfo.DeviceInfoSlice; import com.android.settings.homepage.deviceinfo.StorageSlice; +import com.android.settings.homepage.deviceinfo.EmergencyInfoSlice; import com.android.settings.intelligence.ContextualCardProto.ContextualCard; import com.android.settings.intelligence.ContextualCardProto.ContextualCardList; import com.android.settings.wifi.WifiSlice; @@ -57,11 +58,17 @@ public class SettingsContextualCardProvider extends ContextualCardProvider { .setSliceUri(StorageSlice.STORAGE_CARD_URI.toString()) .setCardName(StorageSlice.PATH_STORAGE_INFO) .build(); + final ContextualCard emergencyInfoCard = + ContextualCard.newBuilder() + .setSliceUri(EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.toString()) + .setCardName(EmergencyInfoSlice.PATH_EMERGENCY_INFO_CARD) + .build(); final ContextualCardList cards = ContextualCardList.newBuilder() .addCard(wifiCard) .addCard(dataUsageCard) .addCard(deviceInfoCard) .addCard(storageInfoCard) + .addCard(emergencyInfoCard) .build(); return cards; diff --git a/src/com/android/settings/homepage/deviceinfo/EmergencyInfoSlice.java b/src/com/android/settings/homepage/deviceinfo/EmergencyInfoSlice.java new file mode 100644 index 00000000000..62678b37516 --- /dev/null +++ b/src/com/android/settings/homepage/deviceinfo/EmergencyInfoSlice.java @@ -0,0 +1,77 @@ +/* + * 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.homepage.deviceinfo; + +import android.app.PendingIntent; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; + +import androidx.core.graphics.drawable.IconCompat; +import androidx.slice.Slice; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.SliceAction; + +import com.android.settings.R; +import com.android.settings.slices.SettingsSliceProvider; + +// This is a slice helper class for EmergencyInfo +public class EmergencyInfoSlice { + /** + * The path denotes the unique name of emergency info slice. + */ + public static final String PATH_EMERGENCY_INFO_CARD = "emergency_info_card"; + + /** + * Backing Uri for the Emergency Info Slice. + */ + public static final Uri EMERGENCY_INFO_CARD_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(PATH_EMERGENCY_INFO_CARD) + .build(); + + private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO"; + + public static Slice getSlice(Context context) { + final ListBuilder listBuilder = new ListBuilder(context, EMERGENCY_INFO_CARD_URI, + ListBuilder.INFINITY); + listBuilder.addRow( + new ListBuilder.RowBuilder() + .setTitle(context.getText(R.string.emergency_info_title)) + .setSubtitle( + context.getText(R.string.emergency_info_contextual_card_summary)) + .setPrimaryAction(generatePrimaryAction(context))); + return listBuilder.build(); + } + + private static SliceAction generatePrimaryAction(Context context) { + PendingIntent pendingIntent = + PendingIntent.getActivity( + context, + 0 /* requestCode */, + new Intent(ACTION_EDIT_EMERGENCY_INFO), + PendingIntent.FLAG_UPDATE_CURRENT); + + return SliceAction.create( + pendingIntent, + IconCompat.createWithResource(context, R.drawable.empty_icon), + ListBuilder.SMALL_IMAGE, + context.getText(R.string.emergency_info_title)); + } +} diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index 8b975b4c518..41c207bba34 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -41,6 +41,7 @@ import com.android.settings.R; import com.android.settings.bluetooth.BluetoothSliceBuilder; import com.android.settings.core.BasePreferenceController; import com.android.settings.flashlight.FlashlightSliceBuilder; +import com.android.settings.homepage.deviceinfo.EmergencyInfoSlice; import com.android.settings.location.LocationSliceBuilder; import com.android.settings.network.telephony.Enhanced4gLteSliceHelper; import com.android.settings.notification.ZenModeSliceBuilder; @@ -178,6 +179,8 @@ public class SettingsSliceProvider extends SliceProvider { registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri); mRegisteredUris.add(sliceUri); return; + } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) { + return; } // Start warming the slice, we expect someone will want it soon. @@ -241,6 +244,8 @@ public class SettingsSliceProvider extends SliceProvider { .createWifiCallingPreferenceSlice(sliceUri); } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) { return FlashlightSliceBuilder.getSlice(getContext()); + } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) { + return EmergencyInfoSlice.getSlice(getContext()); } SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri); diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java index fbc91114883..2c42379f86e 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java @@ -32,6 +32,7 @@ import com.google.android.settings.intelligence.libs.contextualcards.ContextualC import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; @RunWith(SettingsRobolectricTestRunner.class) @@ -40,6 +41,7 @@ public class SettingsContextualCardProviderTest { private Context mContext; private ContentResolver mResolver; private Uri mUri; + private SettingsContextualCardProvider mProvider; @Before public void setUp() { @@ -49,15 +51,18 @@ public class SettingsContextualCardProviderTest { .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsContextualCardProvider.CARD_AUTHORITY) .build(); + mProvider = Robolectric.setupContentProvider(SettingsContextualCardProvider.class); } @Test public void contentProviderCall_returnCorrectSize() throws Exception { + final int actualNo = mProvider.getContextualCards().getCardCount(); + final Bundle returnValue = mResolver.call(mUri, ContextualCardProvider.METHOD_GET_CARD_LIST, "", null); final ContextualCardList cards = - ContextualCardList.parseFrom( - returnValue.getByteArray(ContextualCardProvider.BUNDLE_CARD_LIST)); - assertThat(cards.getCardCount()).isEqualTo(4); + ContextualCardList.parseFrom( + returnValue.getByteArray(ContextualCardProvider.BUNDLE_CARD_LIST)); + assertThat(cards.getCardCount()).isEqualTo(actualNo); } } \ No newline at end of file From f17233ba7d4ae9d80995e526a530ae10771a98f2 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Mon, 8 Oct 2018 12:06:26 +0800 Subject: [PATCH 08/14] Slice background worker with Wi-Fi Slice Test: manual Change-Id: Ic4fdc5713f511ff80f03728c99c68fda3d0cab02 --- .../settings/slices/CustomSliceable.java | 10 ++ .../slices/SettingsSliceProvider.java | 30 ++++ .../slices/SliceBackgroundWorker.java | 85 ++++++++++ .../settings/wifi/WifiDialogActivity.java | 11 +- src/com/android/settings/wifi/WifiSlice.java | 147 +++++++++++++++++- .../slices/SettingsSliceProviderTest.java | 40 ++++- 6 files changed, 313 insertions(+), 10 deletions(-) create mode 100644 src/com/android/settings/slices/SliceBackgroundWorker.java diff --git a/src/com/android/settings/slices/CustomSliceable.java b/src/com/android/settings/slices/CustomSliceable.java index 48b5d161db0..e09cc7386f7 100644 --- a/src/com/android/settings/slices/CustomSliceable.java +++ b/src/com/android/settings/slices/CustomSliceable.java @@ -89,6 +89,16 @@ public interface CustomSliceable { return null; } + /** + * Settings Slices which can represent component lists that are updatable by the + * {@link SliceBackgroundWorker} returned here. + * + * @return a {@link SliceBackgroundWorker} for fetching the list of results in the background. + */ + default SliceBackgroundWorker getBackgroundWorker() { + return null; + } + /** * Standardize the intents returned to indicate actions by the Slice. *

diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index 8b975b4c518..395b8787792 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -28,6 +28,7 @@ import android.os.StrictMode; import android.provider.Settings; import android.provider.SettingsSlicesContract; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.KeyValueListParser; import android.util.Log; @@ -131,6 +132,8 @@ public class SettingsSliceProvider extends SliceProvider { final Set mRegisteredUris = new ArraySet<>(); + final Map mWorkerMap = new ArrayMap<>(); + public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); } @@ -165,6 +168,7 @@ public class SettingsSliceProvider extends SliceProvider { if (filter != null) { registerIntentToUri(filter, sliceUri); } + startBackgroundWorker(sliceable); return; } @@ -191,6 +195,7 @@ public class SettingsSliceProvider extends SliceProvider { SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri); mRegisteredUris.remove(sliceUri); } + stopBackgroundWorker(sliceUri); mSliceDataCache.remove(sliceUri); } @@ -348,6 +353,31 @@ public class SettingsSliceProvider extends SliceProvider { } } + private void startBackgroundWorker(CustomSliceable sliceable) { + final SliceBackgroundWorker worker = sliceable.getBackgroundWorker(); + if (worker == null) { + return; + } + + final Uri uri = sliceable.getUri(); + Log.d(TAG, "Starting background worker for: " + uri); + if (mWorkerMap.containsKey(uri)) { + return; + } + + mWorkerMap.put(uri, worker); + worker.onSlicePinned(); + } + + private void stopBackgroundWorker(Uri uri) { + final SliceBackgroundWorker worker = mWorkerMap.get(uri); + if (worker != null) { + Log.d(TAG, "Stopping background worker for: " + uri); + worker.onSliceUnpinned(); + mWorkerMap.remove(uri); + } + } + private List buildUrisFromKeys(List keys, String authority) { final List descendants = new ArrayList<>(); diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java new file mode 100644 index 00000000000..7178eadbdc5 --- /dev/null +++ b/src/com/android/settings/slices/SliceBackgroundWorker.java @@ -0,0 +1,85 @@ +/* + * 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.slices; + +import android.content.ContentResolver; +import android.net.Uri; + +import java.util.ArrayList; +import java.util.List; + +/** + * The Slice background worker is used to make Settings Slices be able to work with data that is + * changing continuously, e.g. available Wi-Fi networks. + * + * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be + * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}. + * + * {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data + * changed, and then notifies the Slice {@link Uri} to update. + */ +public abstract class SliceBackgroundWorker { + + private final ContentResolver mContentResolver; + private final Uri mUri; + + private List mCachedResults; + + protected SliceBackgroundWorker(ContentResolver cr, Uri uri) { + mContentResolver = cr; + mUri = uri; + } + + /** + * Called when the Slice is pinned. This is the place to register callbacks or initialize scan + * tasks. + */ + protected abstract void onSlicePinned(); + + /** + * Called when the Slice is unpinned. This is the place to unregister callbacks or perform any + * final cleanup. + */ + protected abstract void onSliceUnpinned(); + + /** + * @return a {@link List} of cached results + */ + public final List getResults() { + return mCachedResults == null ? null : new ArrayList<>(mCachedResults); + } + + /** + * Update the results when data changes + */ + protected final void updateResults(List results) { + boolean needNotify = false; + + if (results == null) { + if (mCachedResults != null) { + needNotify = true; + } + } else { + needNotify = !results.equals(mCachedResults); + } + + if (needNotify) { + mCachedResults = results; + mContentResolver.notifyChange(mUri, null); + } + } +} diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java index 63785e6902f..e3a03ad55c9 100644 --- a/src/com/android/settings/wifi/WifiDialogActivity.java +++ b/src/com/android/settings/wifi/WifiDialogActivity.java @@ -37,12 +37,6 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo private static final String TAG = "WifiDialogActivity"; - private static final int RESULT_CONNECTED = RESULT_FIRST_USER; - private static final int RESULT_FORGET = RESULT_FIRST_USER + 1; - - private static final String KEY_ACCESS_POINT_STATE = "access_point_state"; - private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; - /** * Boolean extra indicating whether this activity should connect to an access point on the * caller's behalf. If this is set to false, the caller should check @@ -51,6 +45,11 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo */ @VisibleForTesting static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller"; + static final String KEY_ACCESS_POINT_STATE = "access_point_state"; + private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; + + private static final int RESULT_CONNECTED = RESULT_FIRST_USER; + private static final int RESULT_FORGET = RESULT_FIRST_USER + 1; private WifiDialog mDialog; diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java index d0b14e383c7..536be6f3862 100644 --- a/src/com/android/settings/wifi/WifiSlice.java +++ b/src/com/android/settings/wifi/WifiSlice.java @@ -29,6 +29,9 @@ import android.net.Uri; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.provider.SettingsSlicesContract; import android.text.TextUtils; @@ -42,8 +45,16 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.Utils; +import com.android.settings.core.SubSettingLauncher; import com.android.settings.slices.CustomSliceable; +import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.slices.SliceBuilderUtils; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; +import com.android.settingslib.wifi.AccessPoint; +import com.android.settingslib.wifi.WifiTracker; + +import java.util.ArrayList; +import java.util.List; /** * Utility class to build a Wifi Slice, and handle all associated actions. @@ -96,14 +107,73 @@ public class WifiSlice implements CustomSliceable { final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */, isWifiEnabled); - return new ListBuilder(mContext, WIFI_URI, ListBuilder.INFINITY) + final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_URI, ListBuilder.INFINITY) .setAccentColor(color) .addRow(new RowBuilder() .setTitle(title) .setSubtitle(summary) .addEndItem(toggleSliceAction) - .setPrimaryAction(primarySliceAction)) - .build(); + .setPrimaryAction(primarySliceAction)); + + if (isWifiEnabled) { + final List result = getBackgroundWorker().getResults(); + if (result != null && !result.isEmpty()) { + for (AccessPoint ap : result) { + listBuilder.addRow(getAccessPointRow(ap)); + } + listBuilder.setSeeMoreAction(primaryAction); + } + } + return listBuilder.build(); + } + + private RowBuilder getAccessPointRow(AccessPoint accessPoint) { + final String title = accessPoint.getConfigName(); + final IconCompat levelIcon = IconCompat.createWithResource(mContext, + com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel())); + final RowBuilder rowBuilder = new RowBuilder() + .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE) + .setTitle(title) + .setSubtitle(accessPoint.getSettingsSummary()) + .setPrimaryAction(new SliceAction( + getAccessPointAction(accessPoint), levelIcon, title)); + + final IconCompat endIcon = getEndIcon(accessPoint); + if (endIcon != null) { + rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE); + } + return rowBuilder; + } + + private IconCompat getEndIcon(AccessPoint accessPoint) { + if (accessPoint.isActive()) { + return IconCompat.createWithResource(mContext, R.drawable.ic_settings); + } else if (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { + return IconCompat.createWithResource(mContext, R.drawable.ic_friction_lock_closed); + } else if (accessPoint.isMetered()) { + return IconCompat.createWithResource(mContext, R.drawable.ic_friction_money); + } + return null; + } + + private PendingIntent getAccessPointAction(AccessPoint accessPoint) { + final Bundle extras = new Bundle(); + accessPoint.saveWifiState(extras); + + Intent intent; + if (accessPoint.isActive()) { + intent = new SubSettingLauncher(mContext) + .setTitleRes(R.string.pref_title_network_details) + .setDestination(WifiNetworkDetailsFragment.class.getName()) + .setArguments(extras) + .setSourceMetricsCategory(MetricsEvent.WIFI) + .toIntent(); + } else { + intent = new Intent(mContext, WifiDialogActivity.class); + intent.putExtra(WifiDialogActivity.KEY_ACCESS_POINT_STATE, extras); + } + return PendingIntent.getActivity(mContext, accessPoint.hashCode() /* requestCode */, + intent, 0 /* flags */); } /** @@ -176,4 +246,75 @@ public class WifiSlice implements CustomSliceable { return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */); } + + @Override + public SliceBackgroundWorker getBackgroundWorker() { + return WifiScanWorker.getInstance(mContext, WIFI_URI); + } + + private static class WifiScanWorker extends SliceBackgroundWorker + implements WifiTracker.WifiListener { + + private static WifiScanWorker mWifiScanWorker; + + private final Context mContext; + + private WifiTracker mWifiTracker; + private WifiManager mWifiManager; + + private WifiScanWorker(Context context, Uri uri) { + super(context.getContentResolver(), uri); + mContext = context; + } + + public static WifiScanWorker getInstance(Context context, Uri uri) { + if (mWifiScanWorker == null) { + mWifiScanWorker = new WifiScanWorker(context, uri); + } + return mWifiScanWorker; + } + + @Override + protected void onSlicePinned() { + new Handler(Looper.getMainLooper()).post(() -> { + mWifiTracker = new WifiTracker(mContext, this, true, true); + mWifiManager = mWifiTracker.getManager(); + mWifiTracker.onStart(); + onAccessPointsChanged(); + }); + } + + @Override + protected void onSliceUnpinned() { + mWifiTracker.onStop(); + mWifiTracker.onDestroy(); + mWifiScanWorker = null; + } + + @Override + public void onWifiStateChanged(int state) { + } + + @Override + public void onConnectedChanged() { + } + + @Override + public void onAccessPointsChanged() { + // in case state has changed + if (!mWifiManager.isWifiEnabled()) { + updateResults(null); + return; + } + // AccessPoints are sorted by the WifiTracker + final List accessPoints = mWifiTracker.getAccessPoints(); + final List resultList = new ArrayList<>(); + for (AccessPoint ap : accessPoints) { + if (ap.isReachable()) { + resultList.add(ap); + } + } + updateResults(resultList); + } + } } diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index f7c6bba76e2..19f3d329b1d 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -118,7 +118,7 @@ public class SettingsSliceProviderTest { mProvider.mSliceWeakDataCache = new HashMap<>(); mProvider.mSliceDataCache = new HashMap<>(); mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext); - mProvider.mCustomSliceManager = new CustomSliceManager(mContext); + mProvider.mCustomSliceManager = spy(new CustomSliceManager(mContext)); when(mProvider.getContext()).thenReturn(mContext); mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase(); @@ -481,6 +481,44 @@ public class SettingsSliceProviderTest { mProvider.onSlicePinned(uri); } + private SliceBackgroundWorker initBackgroundWorker(Uri uri) { + final SliceBackgroundWorker worker = spy(new SliceBackgroundWorker( + mContext.getContentResolver(), uri) { + @Override + public void onSlicePinned() { + } + + @Override + public void onSliceUnpinned() { + } + }); + final WifiSlice wifiSlice = spy(new WifiSlice(mContext)); + when(wifiSlice.getBackgroundWorker()).thenReturn(worker); + when(mProvider.mCustomSliceManager.getSliceableFromUri(uri)).thenReturn(wifiSlice); + return worker; + } + + @Test + public void onSlicePinned_backgroundWorker_started() { + final Uri uri = WifiSlice.WIFI_URI; + final SliceBackgroundWorker worker = initBackgroundWorker(uri); + + mProvider.onSlicePinned(uri); + + verify(worker).onSlicePinned(); + } + + @Test + public void onSlicePinned_backgroundWorker_stopped() { + final Uri uri = WifiSlice.WIFI_URI; + final SliceBackgroundWorker worker = initBackgroundWorker(uri); + + mProvider.onSlicePinned(uri); + mProvider.onSliceUnpinned(uri); + + verify(worker).onSliceUnpinned(); + } + @Test public void grantWhitelistedPackagePermissions_noWhitelist_shouldNotGrant() { final List uris = new ArrayList<>(); From 1fccc048f554c1a4eec269203f8048f21e13e84e Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Thu, 18 Oct 2018 13:54:01 -0700 Subject: [PATCH 09/14] Update id for Toolbar If you use action_bar, it will show blank action bar. Bug: 114749736 Test: Manual Change-Id: I459eb00262e667446c88d7ff638b9a425a6eada2 --- res/layout/mobile_settings_container.xml | 2 +- .../settings/network/telephony/MobileSettingsActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/layout/mobile_settings_container.xml b/res/layout/mobile_settings_container.xml index c52b362123d..c88b512f443 100644 --- a/res/layout/mobile_settings_container.xml +++ b/res/layout/mobile_settings_container.xml @@ -23,7 +23,7 @@ android:orientation="vertical"> Date: Wed, 17 Oct 2018 12:54:05 -0700 Subject: [PATCH 10/14] Refactor another network mode preference This preference show up if phone is not in world mode and offer some simplified choices. Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I9204466be630f122fb02773d18a947706999ab79 --- res/values/config.xml | 3 +- res/values/strings.xml | 2 + res/xml/network_setting_fragment.xml | 3 +- ...nabledNetworkModePreferenceController.java | 334 +++++++++++++++ .../telephony/MobileNetworkFragment.java | 390 +----------------- .../network/telephony/MobileNetworkUtils.java | 21 + ...edNetworkModePreferenceControllerTest.java | 145 +++++++ 7 files changed, 508 insertions(+), 390 deletions(-) create mode 100644 src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java diff --git a/res/values/config.xml b/res/values/config.xml index 8e60505ccc0..b496080ea68 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -143,6 +143,5 @@ false - + diff --git a/res/values/strings.xml b/res/values/strings.xml index ac8f305dbf1..45fd3b27fa9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10261,6 +10261,8 @@ App data usage + + Invalid Network Mode %1$d. Ignore. Unavailable when connected to %1$s diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 6cfa0a3aefa..044651cbd2d 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -66,7 +66,8 @@ android:summary="@string/preferred_network_mode_summary" android:entries="@array/enabled_networks_choices" android:entryValues="@array/enabled_networks_values" - android:dialogTitle="@string/preferred_network_mode_dialogtitle" /> + android:dialogTitle="@string/preferred_network_mode_dialogtitle" + settings:controller="com.android.settings.network.telephony.EnabledNetworkModePreferenceController"/> Date: Thu, 18 Oct 2018 16:23:47 -0700 Subject: [PATCH 11/14] Use public API to launch search UI. Test: manual Change-Id: I5527dd6de5990aed365b6e78a9492ced00b99565 --- src/com/android/settings/search/SearchFeatureProvider.java | 3 ++- .../android/settings/search/SearchFeatureProviderImplTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java index 27e8349c162..b2eb8bbb3fc 100644 --- a/src/com/android/settings/search/SearchFeatureProvider.java +++ b/src/com/android/settings/search/SearchFeatureProvider.java @@ -23,6 +23,7 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.provider.Settings; import android.view.View; import android.widget.Toolbar; @@ -35,7 +36,7 @@ import com.android.settingslib.search.SearchIndexableResources; */ public interface SearchFeatureProvider { - Intent SEARCH_UI_INTENT = new Intent("com.android.settings.action.SETTINGS_SEARCH"); + Intent SEARCH_UI_INTENT = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS); int REQUEST_CODE = 0; /** diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java index adb5e43b17f..ba29ea1a9e3 100644 --- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.spy; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; +import android.provider.Settings; import android.widget.Toolbar; import com.android.settings.testutils.FakeFeatureFactory; @@ -63,7 +64,7 @@ public class SearchFeatureProviderImplTest { final Intent launchIntent = Shadows.shadowOf(mActivity).getNextStartedActivity(); assertThat(launchIntent.getAction()) - .isEqualTo("com.android.settings.action.SETTINGS_SEARCH"); + .isEqualTo(Settings.ACTION_APP_SEARCH_SETTINGS); } @Test(expected = IllegalArgumentException.class) From 502f3c6c9151685f24d4527e020086b6d209c274 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Wed, 17 Oct 2018 21:24:22 -0700 Subject: [PATCH 12/14] Refactor 4gForLTE preference Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I6a9d7044e16de2e70fadd97379b2a6de6d18525f --- res/xml/network_setting_fragment.xml | 3 +- .../Enhanced4gLtePreferenceController.java | 148 ++++++++++++++++++ .../telephony/MobileNetworkFragment.java | 59 +------ ...Enhanced4gLtePreferenceControllerTest.java | 138 ++++++++++++++++ 4 files changed, 291 insertions(+), 57 deletions(-) create mode 100644 src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceControllerTest.java diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 044651cbd2d..7d46120a544 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -49,7 +49,8 @@ android:key="enhanced_4g_lte" android:title="@string/enhanced_4g_lte_mode_title" android:persistent="false" - android:summary="@string/enhanced_4g_lte_mode_summary"/> + android:summary="@string/enhanced_4g_lte_mode_summary" + settings:controller="com.android.settings.network.telephony.Enhanced4gLtePreferenceController"/> Date: Thu, 18 Oct 2018 14:48:48 -0700 Subject: [PATCH 13/14] Refactor DataServicePreference Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I773aeabdc1964436cc1e67bbbe9ad7fa6494e504 --- res/xml/network_setting_fragment.xml | 7 +- .../DataServiceSetupPreferenceController.java | 91 ++++++++++++ .../telephony/MobileNetworkFragment.java | 36 +---- ...aServiceSetupPreferenceControllerTest.java | 137 ++++++++++++++++++ 4 files changed, 235 insertions(+), 36 deletions(-) create mode 100644 src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/network/telephony/DataServiceSetupPreferenceControllerTest.java diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index 7d46120a544..e54a90d7730 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -20,10 +20,11 @@ android:title="@string/network_settings_title" settings:initialExpandedChildrenCount="4"> - - + android:title="@string/cdma_lte_data_service" + settings:controller="com.android.settings.network.telephony.DataServiceSetupPreferenceController"> + captor = ArgumentCaptor.forClass(Intent.class); + + mController.handlePreferenceTreeClick(mPreference); + + verify(mContext).startActivity(captor.capture()); + + final Intent intent = captor.getValue(); + assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW); + assertThat(intent.getData()).isEqualTo( + Uri.parse(TextUtils.expandTemplate(SETUP_URL, "").toString())); + } +} From 948b4938fee7cc78e0e3260be200182c1467941b Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 19 Oct 2018 15:19:11 -0700 Subject: [PATCH 14/14] Fix sound settings affinity Change-Id: Id92d7473f1d77ee5640a9da8f320777df496f635 Fixes: 117586503 Test: manual --- AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 109f2b9e8f7..af690d920b1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2534,7 +2534,6 @@ android:label="@string/sound_settings" android:icon="@drawable/ic_homepage_sound" android:exported="true" - android:taskAffinity="com.android.settings" android:parentActivityName="Settings">