From 9f7c4cedea2ff8de107917a71943641155fd0775 Mon Sep 17 00:00:00 2001 From: Joshua Mccloskey Date: Thu, 16 Sep 2021 19:05:57 -0700 Subject: [PATCH 1/7] Updated settings preference title for work profile Test: Verified string apperas in regular work settings. Fixes: 193258818 Change-Id: I89671820a0bf900014567087e1e553e3ad7fe472 --- res/values/strings.xml | 3 +++ res/xml/security_dashboard_settings.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 74b8d7fd701..22631417a4b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -883,6 +883,9 @@ Fingerprint + + + Fingerprint for work Manage fingerprints diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 23d2b6bf0dd..5b687afc488 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -155,7 +155,7 @@ Date: Wed, 14 Jul 2021 16:05:57 -0700 Subject: [PATCH 2/7] Fix QR code scanner layout in "Pair devices over Wi-Fi" page. The toolbar needs to be disabled to remove the empty space at the top of the page. Also added the landscape layout xml. Bug: 193602141 Test: atest SettingsUnitTests and manual Change-Id: I30368835979b360a8f09e16f70adf57064784517 (cherry picked from commit fd009229e507cc40c47f6da8aeac730e8979456a) --- AndroidManifest.xml | 2 + .../adb_qrcode_scanner_fragment.xml | 97 +++++++++++++++++++ res/layout/adb_qrcode_scanner_fragment.xml | 64 +++++------- .../development/AdbQrCodeActivity.java | 75 ++++++++++++++ .../AdbQrCodePreferenceController.java | 12 +-- .../development/AdbQrcodeScannerFragment.java | 18 +++- .../wifi/dpp/WifiDppBaseActivity.java | 2 +- 7 files changed, 216 insertions(+), 54 deletions(-) create mode 100644 res/layout-land/adb_qrcode_scanner_fragment.xml create mode 100644 src/com/android/settings/development/AdbQrCodeActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 97de9a52741..cd6db0f1aa1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2188,6 +2188,8 @@ + + diff --git a/res/layout-land/adb_qrcode_scanner_fragment.xml b/res/layout-land/adb_qrcode_scanner_fragment.xml new file mode 100644 index 00000000000..64515510c44 --- /dev/null +++ b/res/layout-land/adb_qrcode_scanner_fragment.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/adb_qrcode_scanner_fragment.xml b/res/layout/adb_qrcode_scanner_fragment.xml index 5b83cb2f33a..78231554319 100644 --- a/res/layout/adb_qrcode_scanner_fragment.xml +++ b/res/layout/adb_qrcode_scanner_fragment.xml @@ -17,10 +17,11 @@ + android:icon="@drawable/ic_scan_32dp" + app:sudDescriptionText="@string/adb_wireless_qrcode_pairing_description"> - + + + + + - - - - - - - - - - - + android:visibility="invisible"/> @@ -109,4 +92,5 @@ + diff --git a/src/com/android/settings/development/AdbQrCodeActivity.java b/src/com/android/settings/development/AdbQrCodeActivity.java new file mode 100644 index 00000000000..bab20f9754a --- /dev/null +++ b/src/com/android/settings/development/AdbQrCodeActivity.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 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.development; + +import android.app.settings.SettingsEnums; +import android.content.Intent; +import android.os.Bundle; + +import androidx.fragment.app.FragmentTransaction; + +import com.android.settings.R; +import com.android.settings.wifi.dpp.WifiDppBaseActivity; + +/** + * To scan an ADB QR code to pair a device. + * + * To use intent action {@code ACTION_ADB_QR_CODE_SCANNER}. + */ +public class AdbQrCodeActivity extends WifiDppBaseActivity { + private static final String TAG = "AdbQrCodeActivity"; + + static final String TAG_FRAGMENT_ADB_QR_CODE_SCANNER = "adb_qr_code_scanner_fragment"; + + public static final String ACTION_ADB_QR_CODE_SCANNER = + "android.settings.ADB_QR_CODE_SCANNER"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.SETTINGS_ADB_WIRELESS; + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + AdbQrcodeScannerFragment fragment = + (AdbQrcodeScannerFragment) mFragmentManager.findFragmentByTag( + TAG_FRAGMENT_ADB_QR_CODE_SCANNER); + + if (fragment == null) { + fragment = new AdbQrcodeScannerFragment(); + } else { + if (fragment.isVisible()) { + return; + } + + // When the fragment in back stack but not on top of the stack, we can simply pop + // stack because current fragment transactions are arranged in an order + mFragmentManager.popBackStackImmediate(); + return; + } + final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); + + fragmentTransaction.replace(R.id.fragment_container, fragment, + TAG_FRAGMENT_ADB_QR_CODE_SCANNER); + fragmentTransaction.commit(); + } + + @Override + protected void handleIntent(Intent intent) { + } +} diff --git a/src/com/android/settings/development/AdbQrCodePreferenceController.java b/src/com/android/settings/development/AdbQrCodePreferenceController.java index 7c1ae12538d..9085d1ba848 100644 --- a/src/com/android/settings/development/AdbQrCodePreferenceController.java +++ b/src/com/android/settings/development/AdbQrCodePreferenceController.java @@ -16,8 +16,8 @@ package com.android.settings.development; -import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.Intent; import android.debug.IAdbManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -28,7 +28,6 @@ import androidx.fragment.app.Fragment; import androidx.preference.Preference; import com.android.settings.core.BasePreferenceController; -import com.android.settings.core.SubSettingLauncher; /** * Controller for the "Pair device with QR code" preference in the Wireless debugging @@ -68,12 +67,9 @@ public class AdbQrCodePreferenceController extends BasePreferenceController { return false; } - new SubSettingLauncher(preference.getContext()) - .setDestination(AdbQrcodeScannerFragment.class.getName()) - .setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS) - .setResultListener(mParentFragment, - WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST) - .launch(); + final Intent intent = new Intent(mContext, AdbQrCodeActivity.class); + mParentFragment.startActivityForResult(intent, + WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST); return true; } } diff --git a/src/com/android/settings/development/AdbQrcodeScannerFragment.java b/src/com/android/settings/development/AdbQrcodeScannerFragment.java index 7a30443bca4..1035fbeab33 100644 --- a/src/com/android/settings/development/AdbQrcodeScannerFragment.java +++ b/src/com/android/settings/development/AdbQrcodeScannerFragment.java @@ -44,12 +44,15 @@ import android.widget.TextView; import androidx.annotation.StringRes; import com.android.settings.R; +import com.android.settings.SetupWizardUtils; import com.android.settings.wifi.dpp.AdbQrCode; import com.android.settings.wifi.dpp.WifiDppQrCodeBaseFragment; import com.android.settings.wifi.dpp.WifiNetworkConfig; import com.android.settings.wifi.qrcode.QrCamera; import com.android.settings.wifi.qrcode.QrDecorateView; +import com.google.android.setupdesign.util.ThemeHelper; + /** * Fragment shown when clicking on the "Pair by QR code" preference in * the Wireless Debugging fragment. @@ -144,6 +147,9 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen @Override public void onCreate(Bundle savedInstanceState) { + Context context = getContext(); + context.setTheme(SetupWizardUtils.getTheme(context, getActivity().getIntent())); + ThemeHelper.trySetDynamicColor(getContext()); super.onCreate(savedInstanceState); mIntentFilter = new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); @@ -158,6 +164,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mSummary = view.findViewById(R.id.sud_layout_subtitle); mTextureView = (TextureView) view.findViewById(R.id.preview_view); mTextureView.setSurfaceTextureListener(this); @@ -165,8 +172,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen mDecorateView = view.findViewById(R.id.decorate_view); setProgressBarShown(false); - setHeaderIconImageResource(R.drawable.ic_scan_24dp); - mQrCameraView = view.findViewById(R.id.camera_layout); mVerifyingView = view.findViewById(R.id.verifying_layout); mVerifyingTextView = view.findViewById(R.id.verifying_textview); @@ -181,12 +186,18 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen public void onResume() { super.onResume(); + restartCamera(); + mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService(Context.ADB_SERVICE)); getActivity().registerReceiver(mReceiver, mIntentFilter); } @Override public void onPause() { + if (mCamera != null) { + mCamera.stop(); + } + super.onPause(); getActivity().unregisterReceiver(mReceiver); @@ -195,8 +206,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen } catch (RemoteException e) { Log.e(TAG, "Unable to cancel pairing"); } - getActivity().setResult(Activity.RESULT_CANCELED); - getActivity().finish(); } @Override @@ -213,7 +222,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - getActivity().getActionBar().hide(); // setTitle for TalkBack getActivity().setTitle(R.string.wifi_dpp_scan_qr_code); } diff --git a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java index 499f66cb3c8..f55960be5e0 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java @@ -26,7 +26,7 @@ import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.core.InstrumentedActivity; -abstract class WifiDppBaseActivity extends InstrumentedActivity { +public abstract class WifiDppBaseActivity extends InstrumentedActivity { protected FragmentManager mFragmentManager; protected abstract void handleIntent(Intent intent); From caa29d401b1b93d825a683952006f2685ed44769 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Mon, 20 Sep 2021 22:38:29 +0800 Subject: [PATCH 3/7] Minor change to Wi-Fi WPA3 password length restriction - Change the maximum length limit to 128 Bug: 200305860 Test: manual test make RunSettingsRoboTests ROBOTEST_FILTER=WifiConfigController2Test Change-Id: Ia739dab35da75c73e28077ccc81979253def6128 --- src/com/android/settings/wifi/WifiConfigController2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index e8f2384d5cd..011c9709c00 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -484,7 +484,7 @@ public class WifiConfigController2 implements TextWatcher, } boolean isValidSaePassword(String password) { - if (password.length() >= 1 && password.length() <= 63) { + if (password.length() >= 1 && password.length() <= 128) { return true; } return false; From 95db7ae728d3664ec09ed0176c1cd4a792b2c5f9 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Wed, 15 Sep 2021 17:16:19 +0800 Subject: [PATCH 4/7] [Provider Model] The SIMs page should list all p-SIMs - We do not support multiple pSIMs until now, so we need to get all p-SIMs from SubscriptionManager - Apply same checking for downloaded sim Bug: 199032142 Test: vendor test Test: atest NetworkProviderSimsCategoryControllerTest and atest NetworkProviderSimListControllerTest Change-Id: I77d7c52e73ac4e5d09fa3f3926490d7f8f8b0913 --- .../network/MobileNetworkListFragment.java | 8 +- ...viderDownloadedSimsCategoryController.java | 28 ++++--- .../NetworkProviderSimListController.java | 1 - ...NetworkProviderSimsCategoryController.java | 43 ++++++---- ...rDownloadedSimsCategoryControllerTest.java | 83 +++++++++++++++---- .../NetworkProviderSimListControllerTest.java | 19 ++++- ...orkProviderSimsCategoryControllerTest.java | 79 +++++++++++++----- 7 files changed, 189 insertions(+), 72 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkListFragment.java b/src/com/android/settings/network/MobileNetworkListFragment.java index 1767c1c8039..03e5a010631 100644 --- a/src/com/android/settings/network/MobileNetworkListFragment.java +++ b/src/com/android/settings/network/MobileNetworkListFragment.java @@ -65,14 +65,12 @@ public class MobileNetworkListFragment extends DashboardFragment { if (Utils.isProviderModelEnabled(getContext())) { NetworkProviderSimsCategoryController simCategoryPrefCtrl = - new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM); - simCategoryPrefCtrl.init(getSettingsLifecycle()); + new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM, + getSettingsLifecycle()); controllers.add(simCategoryPrefCtrl); - NetworkProviderDownloadedSimsCategoryController downloadedSimsCategoryCtrl = new NetworkProviderDownloadedSimsCategoryController(context, - KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); - downloadedSimsCategoryCtrl.init(getSettingsLifecycle()); + KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, getSettingsLifecycle()); controllers.add(downloadedSimsCategoryCtrl); } else { controllers.add(new MobileNetworkListController(getContext(), getLifecycle())); diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java index f7c70f25a90..f5176b030d4 100644 --- a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java +++ b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java @@ -1,8 +1,8 @@ package com.android.settings.network; import android.content.Context; +import android.util.Log; -import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; @@ -15,23 +15,17 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; public class NetworkProviderDownloadedSimsCategoryController extends PreferenceCategoryController implements LifecycleObserver { + private static final String LOG_TAG = "NetworkProviderDownloadedSimsCategoryController"; private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM = "provider_model_downloaded_sim_category"; private PreferenceCategory mPreferenceCategory; private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController; - public NetworkProviderDownloadedSimsCategoryController(Context context, String key) { - super(context, key); - } - - public void init(Lifecycle lifecycle) { - mNetworkProviderDownloadedSimListController = createDownloadedSimListController(lifecycle); - } - - @VisibleForTesting - protected NetworkProviderDownloadedSimListController createDownloadedSimListController( + public NetworkProviderDownloadedSimsCategoryController(Context context, String key, Lifecycle lifecycle) { - return new NetworkProviderDownloadedSimListController(mContext, lifecycle); + super(context, key); + mNetworkProviderDownloadedSimListController = + new NetworkProviderDownloadedSimListController(mContext, lifecycle); } @Override @@ -47,15 +41,23 @@ public class NetworkProviderDownloadedSimsCategoryController extends @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); + mNetworkProviderDownloadedSimListController.displayPreference(screen); mPreferenceCategory = screen.findPreference( KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "displayPreference(), Can not find the category."); + return; + } mPreferenceCategory.setVisible(isAvailable()); - mNetworkProviderDownloadedSimListController.displayPreference(screen); } @Override public void updateState(Preference preference) { super.updateState(preference); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "updateState(), Can not find the category."); + return; + } int count = mPreferenceCategory.getPreferenceCount(); String title = mContext.getString(count > 1 ? R.string.downloaded_sims_category_title diff --git a/src/com/android/settings/network/NetworkProviderSimListController.java b/src/com/android/settings/network/NetworkProviderSimListController.java index 814a461e988..8fb6cb65d36 100644 --- a/src/com/android/settings/network/NetworkProviderSimListController.java +++ b/src/com/android/settings/network/NetworkProviderSimListController.java @@ -172,7 +172,6 @@ public class NetworkProviderSimListController extends AbstractPreferenceControll for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) { if (!info.isEmbedded()) { subList.add(info); - break; } } return subList; diff --git a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java index e27575a3b63..06035a91e44 100644 --- a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java +++ b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java @@ -17,33 +17,28 @@ package com.android.settings.network; import android.content.Context; +import android.util.Log; -import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; public class NetworkProviderSimsCategoryController extends PreferenceCategoryController implements LifecycleObserver { - + private static final String LOG_TAG = "NetworkProviderSimsCategoryController"; private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category"; private NetworkProviderSimListController mNetworkProviderSimListController; + private PreferenceCategory mPreferenceCategory; - public NetworkProviderSimsCategoryController(Context context, String key) { + public NetworkProviderSimsCategoryController(Context context, String key, Lifecycle lifecycle) { super(context, key); - } - - public void init(Lifecycle lifecycle) { - mNetworkProviderSimListController = createSimListController(lifecycle); - } - - @VisibleForTesting - protected NetworkProviderSimListController createSimListController( - Lifecycle lifecycle) { - return new NetworkProviderSimListController(mContext, lifecycle); + mNetworkProviderSimListController = + new NetworkProviderSimListController(mContext, lifecycle); } @Override @@ -59,8 +54,26 @@ public class NetworkProviderSimsCategoryController extends PreferenceCategoryCon @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - PreferenceCategory preferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM); - preferenceCategory.setVisible(isAvailable()); mNetworkProviderSimListController.displayPreference(screen); + mPreferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "displayPreference(), Can not find the category."); + return; + } + mPreferenceCategory.setVisible(isAvailable()); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "updateState(), Can not find the category."); + return; + } + int count = mPreferenceCategory.getPreferenceCount(); + String title = mContext.getString(count > 1 + ? R.string.provider_network_settings_title + : R.string.sim_category_title); + mPreferenceCategory.setTitle(title); } } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java index e34b489844e..90455022eda 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java @@ -26,9 +26,12 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; +import android.telephony.SubscriptionInfo; +import com.android.settings.testutils.ResourcesUtils; import com.android.settingslib.core.lifecycle.Lifecycle; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -41,38 +44,39 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) public class NetworkProviderDownloadedSimsCategoryControllerTest { private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM = "provider_model_downloaded_sim_category"; + private static final String KEY_ADD_MORE = "add_more"; + private static final String SUB_1 = "SUB_1"; + private static final String SUB_2 = "SUB_2"; + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; - @Mock - private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController; - @Mock - private PreferenceCategory mPreferenceCategory; @Mock private Lifecycle mLifecycle; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; private Context mContext; private NetworkProviderDownloadedSimsCategoryController mCategoryController; - + private PreferenceCategory mPreferenceCategory; private PreferenceManager mPreferenceManager; private PreferenceScreen mPreferenceScreen; + private Preference mAddMorePreference; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - mCategoryController = new NetworkProviderDownloadedSimsCategoryController( - mContext, KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM) { - @Override - protected NetworkProviderDownloadedSimListController createDownloadedSimListController( - Lifecycle lifecycle) { - return mNetworkProviderDownloadedSimListController; - } - }; if (Looper.myLooper() == null) { Looper.prepare(); @@ -80,14 +84,21 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest { mPreferenceManager = new PreferenceManager(mContext); mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext); - when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); - when(mPreferenceCategory.getPreferenceCount()).thenReturn(1); + mPreferenceCategory = new PreferenceCategory(mContext); + mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); + mAddMorePreference = new Preference(mContext); + mAddMorePreference.setKey(KEY_ADD_MORE); + mAddMorePreference.setVisible(true); mPreferenceScreen.addPreference(mPreferenceCategory); + mPreferenceScreen.addPreference(mAddMorePreference); + + mCategoryController = new NetworkProviderDownloadedSimsCategoryController(mContext, + KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, mLifecycle); } @Test public void getAvailabilityStatus_returnUnavailable() { - mNetworkProviderDownloadedSimListController = null; + SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>()); assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo( CONDITIONALLY_UNAVAILABLE); @@ -95,10 +106,46 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest { @Test public void displayPreference_isVisible() { - when(mNetworkProviderDownloadedSimListController.isAvailable()).thenReturn(true); - mCategoryController.init(mLifecycle); + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); mCategoryController.displayPreference(mPreferenceScreen); assertEquals(mPreferenceCategory.isVisible(), true); } + + + @Test + public void updateState_setTitle_withTwoDownloadedSims_returnDownloadedSims() { + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + setUpSubscriptionInfoForDownloadedSim(SUB_ID_2, SUB_2, mSubscriptionInfo2); + SubscriptionUtil.setAvailableSubscriptionsForTesting( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "downloaded_sims_category_title")); + } + + @Test + public void updateState_setTitle_withOneDownloadedSim_returnDownloadedSim() { + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "downloaded_sim_category_title")); + } + + private void setUpSubscriptionInfoForDownloadedSim(int subId, String displayName, + SubscriptionInfo subscriptionInfo) { + when(subscriptionInfo.isEmbedded()).thenReturn(true); + when(subscriptionInfo.getSubscriptionId()).thenReturn(subId); + when(subscriptionInfo.getDisplayName()).thenReturn(displayName); + } } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java index 3b0a40ab702..066cf6b5f69 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java @@ -16,10 +16,14 @@ package com.android.settings.network; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.google.common.truth.Truth.assertThat; + import static androidx.lifecycle.Lifecycle.Event; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -170,7 +174,6 @@ public class NetworkProviderSimListControllerTest { assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary)); } - @Test @UiThreadTest public void getSummary_inactivePSim() { @@ -227,4 +230,18 @@ public class NetworkProviderSimListControllerTest { assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary)); } + @Test + @UiThreadTest + public void getAvailablePhysicalSubscription_withTwoPhysicalSims_returnTwo() { + final SubscriptionInfo info1 = mock(SubscriptionInfo.class); + when(info1.isEmbedded()).thenReturn(false); + final SubscriptionInfo info2 = mock(SubscriptionInfo.class); + when(info2.isEmbedded()).thenReturn(false); + when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( + Arrays.asList(info1, info2)); + displayPreferenceWithLifecycle(); + + assertThat(mController.getAvailablePhysicalSubscription().size()).isEqualTo(2); + } + } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java index cfa376bd183..c8d750ce437 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java @@ -17,6 +17,7 @@ package com.android.settings.network; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -25,7 +26,10 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import com.android.settings.testutils.ResourcesUtils; import com.android.settingslib.core.lifecycle.Lifecycle; import androidx.preference.PreferenceCategory; @@ -40,37 +44,35 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) public class NetworkProviderSimsCategoryControllerTest { private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category"; + private static final String SUB_1 = "SUB_1"; + private static final String SUB_2 = "SUB_2"; + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; - @Mock - private NetworkProviderSimListController mNetworkProviderSimListController; - @Mock - private PreferenceCategory mPreferenceCategory; @Mock private Lifecycle mLifecycle; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; private Context mContext; private NetworkProviderSimsCategoryController mCategoryController; - private PreferenceManager mPreferenceManager; private PreferenceScreen mPreferenceScreen; + private PreferenceCategory mPreferenceCategory; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mContext = spy(ApplicationProvider.getApplicationContext()); - mCategoryController = new NetworkProviderSimsCategoryController( - mContext, KEY_PREFERENCE_CATEGORY_SIM) { - @Override - protected NetworkProviderSimListController createSimListController( - Lifecycle lifecycle) { - return mNetworkProviderSimListController; - } - }; if (Looper.myLooper() == null) { Looper.prepare(); @@ -78,14 +80,17 @@ public class NetworkProviderSimsCategoryControllerTest { mPreferenceManager = new PreferenceManager(mContext); mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext); - when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_SIM); - when(mPreferenceCategory.getPreferenceCount()).thenReturn(1); + mPreferenceCategory = new PreferenceCategory(mContext); + mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_SIM); mPreferenceScreen.addPreference(mPreferenceCategory); + + mCategoryController = new NetworkProviderSimsCategoryController( + mContext, KEY_PREFERENCE_CATEGORY_SIM, mLifecycle); } @Test public void getAvailabilityStatus_returnUnavailable() { - mNetworkProviderSimListController = null; + SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>()); assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo( CONDITIONALLY_UNAVAILABLE); @@ -93,10 +98,46 @@ public class NetworkProviderSimsCategoryControllerTest { @Test public void displayPreference_isVisible() { - when(mNetworkProviderSimListController.isAvailable()).thenReturn(true); - mCategoryController.init(mLifecycle); + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); mCategoryController.displayPreference(mPreferenceScreen); assertEquals(mPreferenceCategory.isVisible(), true); } + + @Test + public void updateState_setTitle_withTwoPhysicalSims_returnSims() { + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + setUpSubscriptionInfoForPhysicalSim(SUB_ID_2, SUB_2, mSubscriptionInfo2); + SubscriptionUtil.setAvailableSubscriptionsForTesting( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "provider_network_settings_title")); + } + + @Test + public void updateState_setTitle_withOnePhysicalSim_returnSim() { + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "sim_category_title")); + } + + private void setUpSubscriptionInfoForPhysicalSim(int subId, String displayName, + SubscriptionInfo subscriptionInfo) { + when(subscriptionInfo.isEmbedded()).thenReturn(false); + when(subscriptionInfo.getSubscriptionId()).thenReturn(subId); + when(subscriptionInfo.getDisplayName()).thenReturn(displayName); + } + } From 73855e0a59a2df21c4720d7eaa1812eb89d4fae2 Mon Sep 17 00:00:00 2001 From: Curtis Belmonte Date: Fri, 17 Sep 2021 17:13:31 -0700 Subject: [PATCH 5/7] Support configurable multi-stage UDFPS enrollment Implements multi-stage enrollment for UDFPS. This implementation supports both highlighting the progress bar when a help message is received and configuring the progress thresholds between enroll stages via an XML resource. Test: Manual Bug: 198928407 Bug: 200076382 Change-Id: Ied4dbcb4a523f477c5ca1a9146d24751c6473f35 --- .../FingerprintEnrollEnrolling.java | 178 +++++++++++++----- 1 file changed, 129 insertions(+), 49 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index 714e210f9f1..c2bcee33428 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -18,6 +18,7 @@ package com.android.settings.biometrics.fingerprint; import android.animation.Animator; import android.animation.ObjectAnimator; +import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Dialog; import android.app.settings.SettingsEnums; @@ -58,6 +59,8 @@ import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupcompat.util.WizardManagerHelper; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -69,11 +72,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { static final String TAG_SIDECAR = "sidecar"; private static final int PROGRESS_BAR_MAX = 10000; - private static final int FINISH_DELAY = 250; - /** - * Enroll with two center touches before going to guided enrollment. - */ - private static final int NUM_CENTER_TOUCHES = 2; + + private static final int STAGE_UNKNOWN = -1; + private static final int STAGE_CENTER = 0; + private static final int STAGE_GUIDED = 1; + private static final int STAGE_FINGERTIP = 2; + private static final int STAGE_EDGES = 3; + + @IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_EDGES}) + @Retention(RetentionPolicy.SOURCE) + private @interface EnrollStage {} /** * If we don't see progress during this time, we show an error message to remind the users that @@ -100,6 +108,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); + private FingerprintManager mFingerprintManager; private boolean mCanAssumeUdfps; @Nullable private ProgressBar mProgressBar; private ObjectAnimator mProgressAnim; @@ -125,9 +134,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); + mFingerprintManager = getSystemService(FingerprintManager.class); final List props = - fingerprintManager.getSensorPropertiesInternal(); + mFingerprintManager.getSensorPropertiesInternal(); mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType(); mAccessibilityManager = getSystemService(AccessibilityManager.class); @@ -273,7 +282,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { // UDFPS animations are owned by SystemUI if (progress >= PROGRESS_BAR_MAX) { // Wait for any animations in SysUI to finish, then proceed to next page - getMainThreadHandler().postDelayed(mDelayedFinishRunnable, FINISH_DELAY); + getMainThreadHandler().postDelayed(mDelayedFinishRunnable, getFinishDelay()); } return; } @@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } private void updateTitleAndDescription() { + if (mCanAssumeUdfps) { + updateTitleAndDescriptionForUdfps(); + return; + } + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { - if (mCanAssumeUdfps) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); + } else { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); + } + } + + private void updateTitleAndDescriptionForUdfps() { + switch (getCurrentStage()) { + case STAGE_CENTER: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + setDescriptionText(R.string.security_settings_udfps_enroll_start_message); + break; + + case STAGE_GUIDED: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + if (mIsAccessibilityEnabled) { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); + } + break; + + case STAGE_FINGERTIP: + setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title); + if (isStageHalfCompleted()) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_title); + } else { + setDescriptionText(""); + } + break; + + case STAGE_EDGES: + setHeaderText(R.string.security_settings_udfps_enroll_edge_title); + if (isStageHalfCompleted()) { + setDescriptionText( + R.string.security_settings_fingerprint_enroll_repeat_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_edge_message); + } + break; + + case STAGE_UNKNOWN: + default: // setHeaderText(R.string.security_settings_fingerprint_enroll_udfps_title); // Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle, // which gets announced for a11y upon entering the page. For UDFPS, we want to @@ -309,41 +365,61 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { getLayout().setHeaderText( R.string.security_settings_fingerprint_enroll_udfps_title); setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - final CharSequence description = getString( R.string.security_settings_udfps_enroll_a11y); getLayout().getHeaderTextView().setContentDescription(description); setTitle(description); - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); - } - } else if (mCanAssumeUdfps && !isCenterEnrollmentComplete()) { - if (mIsSetupWizard) { - setHeaderText(R.string.security_settings_udfps_enroll_title_one_more_time); - } else { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - } - setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - } else { - if (mCanAssumeUdfps) { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - if (mIsAccessibilityEnabled) { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); - } else { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); - } - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); - } + break; } } - private boolean isCenterEnrollmentComplete() { + @EnrollStage + private int getCurrentStage() { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + return STAGE_UNKNOWN; + } + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + if (progressSteps < getStageThresholdSteps(0)) { + return STAGE_CENTER; + } else if (progressSteps < getStageThresholdSteps(1)) { + return STAGE_GUIDED; + } else if (progressSteps < getStageThresholdSteps(2)) { + return STAGE_FINGERTIP; + } else { + return STAGE_EDGES; + } + } + + private boolean isStageHalfCompleted() { + // Prior to first enrollment step. if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { return false; } - final int stepsEnrolled = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); - return stepsEnrolled >= NUM_CENTER_TOUCHES; + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + int prevThresholdSteps = 0; + for (int i = 0; i < mFingerprintManager.getEnrollStageCount(); i++) { + final int thresholdSteps = getStageThresholdSteps(i); + if (progressSteps >= prevThresholdSteps && progressSteps < thresholdSteps) { + final int adjustedProgress = progressSteps - prevThresholdSteps; + final int adjustedThreshold = thresholdSteps - prevThresholdSteps; + return adjustedProgress >= adjustedThreshold / 2; + } + prevThresholdSteps = thresholdSteps; + } + + // After last enrollment step. + return true; + } + + private int getStageThresholdSteps(int index) { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet"); + return 1; + } + return Math.round(mSidecar.getEnrollmentSteps() + * mFingerprintManager.getEnrollStageThreshold(index)); } @Override @@ -489,25 +565,29 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mOrientationEventListener = null; } - private final Animator.AnimatorListener mProgressAnimationListener - = new Animator.AnimatorListener() { + private final Animator.AnimatorListener mProgressAnimationListener = + new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { } + @Override + public void onAnimationStart(Animator animation) { } - @Override - public void onAnimationRepeat(Animator animation) { } + @Override + public void onAnimationRepeat(Animator animation) { } - @Override - public void onAnimationEnd(Animator animation) { - if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { - mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); - } - } + @Override + public void onAnimationEnd(Animator animation) { + if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { + mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); + } + } - @Override - public void onAnimationCancel(Animator animation) { } - }; + @Override + public void onAnimationCancel(Animator animation) { } + }; + + private long getFinishDelay() { + return mCanAssumeUdfps ? 400L : 250L; + } // Give the user a chance to see progress completed before jumping to the next stage. private final Runnable mDelayedFinishRunnable = new Runnable() { From e7cca4cd813a46d9ac3ba2e7523561fc1358ae37 Mon Sep 17 00:00:00 2001 From: "Wesley.CW Wang" Date: Wed, 15 Sep 2021 22:56:38 +0800 Subject: [PATCH 6/7] Add PowerSaveWhitelistExceptIdle as Optimizted modes condition - Check PowerSaveWhitelistExceptIdle list before update each apps optimizaton mode to avoid duplicate remove action - Make those apps which under PowerSaveWhitelistExceptIdle list keep at optimized mode only BYPASS_INCLUSIVE_LANGUAGE_REASON=legacy naming, not edit by this code change Bug: 199892006 Test: make SettingsRoboTests Change-Id: I3cd10cf51b5132fc12a83e9554801ec4e8578cd1 Merged-In: I3cd10cf51b5132fc12a83e9554801ec4e8578cd1 --- .../settings/fuelgauge/AdvancedPowerUsageDetail.java | 12 +++++++----- .../settings/fuelgauge/BatteryOptimizeUtils.java | 7 +++++++ .../fuelgauge/OptimizedPreferenceController.java | 4 ++++ .../fuelgauge/RestrictedPreferenceController.java | 3 +++ .../fuelgauge/UnrestrictedPreferenceController.java | 3 +++ .../fuelgauge/AdvancedPowerUsageDetailTest.java | 10 ++++++++++ .../settings/fuelgauge/BatteryOptimizeUtilsTest.java | 12 ++++++++++++ .../fuelgauge/OptimizedPreferenceControllerTest.java | 10 ++++++++++ .../RestrictedPreferenceControllerTest.java | 10 ++++++++++ .../UnrestrictedPreferenceControllerTest.java | 10 ++++++++++ 10 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index be1ea31169f..c0670942834 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -19,8 +19,8 @@ package com.android.settings.fuelgauge; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; -import android.app.settings.SettingsEnums; import android.app.backup.BackupManager; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -361,18 +361,20 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements final String stateString; final String footerString; - if (!mBatteryOptimizeUtils.isValidPackageName()) { - //Present optimized only string when the package name is invalid. + if (!mBatteryOptimizeUtils.isValidPackageName() + || mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) { + // Present optimized only string when the package name is invalid or + // it's in allow list not idle app. stateString = context.getString(R.string.manager_battery_usage_optimized_only); footerString = context.getString( R.string.manager_battery_usage_footer_limited, stateString); } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) { - //Present unrestricted only string when the package is system or default active app. + // Present unrestricted only string when the package is system or default active app. stateString = context.getString(R.string.manager_battery_usage_unrestricted_only); footerString = context.getString( R.string.manager_battery_usage_footer_limited, stateString); } else { - //Present default string to normal app. + // Present default string to normal app. footerString = context.getString(R.string.manager_battery_usage_footer); } mFooterPreference.setTitle(footerString); diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java index db29ac6e549..11528a66186 100644 --- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java @@ -130,6 +130,13 @@ public class BatteryOptimizeUtils { || mPowerAllowListBackend.isDefaultActiveApp(mPackageName); } + /** + * Return {@code true} if this package is in allow list except idle app. + */ + public boolean isAllowlistedExceptIdleApp() { + return mPowerAllowListBackend.isAllowlistedExceptIdle(mPackageName); + } + String getPackageName() { return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName; } diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java index ffec50d4f53..ef2339729f5 100644 --- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java +++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java @@ -57,6 +57,10 @@ public class OptimizedPreferenceController extends AbstractPreferenceController Log.d(TAG, "is system or default app, disable pref"); ((RadioButtonPreference) preference).setChecked(false); preference.setEnabled(false); + } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) { + Log.d(TAG, "in allow list not idle app, optimized states only"); + preference.setEnabled(true); + ((RadioButtonPreference) preference).setChecked(true); } else if (mBatteryOptimizeUtils.getAppOptimizationMode() == BatteryOptimizeUtils.MODE_OPTIMIZED) { Log.d(TAG, "is optimized states"); diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java index d50926e6177..230b1fcb415 100644 --- a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java +++ b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java @@ -55,6 +55,9 @@ public class RestrictedPreferenceController extends AbstractPreferenceController Log.d(TAG, "is system or default app, disable pref"); ((RadioButtonPreference) preference).setChecked(false); preference.setEnabled(false); + } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) { + Log.d(TAG, "in allow list not idle app, disable perf"); + preference.setEnabled(false); } else if (mBatteryOptimizeUtils.getAppOptimizationMode() == BatteryOptimizeUtils.MODE_RESTRICTED) { Log.d(TAG, "is restricted states"); diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java index 1d66c6c6cdd..f8ee6513779 100644 --- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java +++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java @@ -53,6 +53,9 @@ public class UnrestrictedPreferenceController extends AbstractPreferenceControll if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) { Log.d(TAG, "is system or default app, unrestricted states only"); ((RadioButtonPreference) preference).setChecked(true); + } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) { + Log.d(TAG, "in allow list not idle app, disable perf"); + preference.setEnabled(false); } else if (mBatteryOptimizeUtils.getAppOptimizationMode() == BatteryOptimizeUtils.MODE_UNRESTRICTED) { Log.d(TAG, "is unrestricted states"); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index a2e78c3a2b5..ac85d976a4f 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -745,6 +745,16 @@ public class AdvancedPowerUsageDetailTest { .isEqualTo("This app requires optimized battery usage."); } + @Test + public void testInitPreferenceForTriState_isAllowlistedExceptIdleApp_hasCorrectString() { + when(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true); + + mFragment.initPreferenceForTriState(mContext); + + assertThat(mFooterPreference.getTitle().toString()) + .isEqualTo("This app requires optimized battery usage."); + } + @Test public void testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() { when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java index 53101c04d1b..c32be187e37 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java @@ -124,6 +124,18 @@ public class BatteryOptimizeUtilsTest { assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue(); } + @Test + public void testIsAllowlistedExpectIdle_isAllowlistedExceptIdle_returnTrue() { + when(mMockBackend.isAllowlistedExceptIdle(anyString())).thenReturn(true); + + assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isTrue(); + } + + @Test + public void testIsAllowlistedExpectIdle_notAllowlistedExpectIdle_returnFalse() { + assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isFalse(); + } + @Test public void testSetAppOptimizationMode_Restricted_verifyAction() { // Sets the current mode as MODE_UNRESTRICTED. diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java index 9df3ac90cb4..923855d3e30 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java @@ -93,6 +93,16 @@ public class OptimizedPreferenceControllerTest { assertThat(mPreference.isChecked()).isFalse(); } + @Test + public void testUpdateState_isAllowlistedExceptIdleApp_prefEnabled() { + when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isChecked()).isTrue(); + } + @Test public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() { mPreference.setKey(mController.KEY_OPTIMIZED_PREF); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java index 09861536edd..7b4271f564c 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java @@ -101,6 +101,16 @@ public class RestrictedPreferenceControllerTest { assertThat(mPreference.isChecked()).isFalse(); } + @Test + public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() { + when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true); + + mController.updateState(mPreference); + + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() { mPreference.setKey(mController.KEY_RESTRICTED_PREF); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java index 004e97ce6fe..505278419d8 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java @@ -101,6 +101,16 @@ public class UnrestrictedPreferenceControllerTest { assertThat(mPreference.isChecked()).isFalse(); } + @Test + public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() { + when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true); + + mController.updateState(mPreference); + + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() { mPreference.setKey(mController.KEY_UNRESTRICTED_PREF); From 7ffd6d81868a89537e85f22f874c9623f6dc6dd4 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 15 Sep 2021 17:14:38 +0800 Subject: [PATCH 7/7] Fix sometimes deep link does not show in 2-pane Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK starts the activity-alias 'DeepLinkHomepageActivity', however, if Settings app first time (from application cteation) starts from the activity-alias 'Settings', framework will uses 'Settings' instead of DeepLinkHomepageActivity to match pair rule. User will see full screen deep link for this case. This change registers deep link pair rule for both the activity-alias 'Settings' and 'DeepLinkHomepageActivity'. Bug: 200131691 Test: manual 1. Launch Settings from launcher. 2. Launch Settings from Settings shortcut widget. 3. Observe if the shortcut page shows in 2-pane. Change-Id: Ice9d09f3545a02603f529d5d19e621ae82302004 --- .../settings/homepage/SettingsHomepageActivity.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index f073a618e05..c065c75c7b9 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -24,7 +24,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; -import android.provider.Settings; import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; @@ -40,6 +39,7 @@ import androidx.fragment.app.FragmentTransaction; import androidx.window.embedding.SplitController; import com.android.settings.R; +import com.android.settings.Settings; import com.android.settings.Utils; import com.android.settings.accounts.AvatarViewMixin; import com.android.settings.core.CategoryMixin; @@ -180,12 +180,12 @@ public class SettingsHomepageActivity extends FragmentActivity implements final Intent intent = getIntent(); if (intent == null || !TextUtils.equals(intent.getAction(), - Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK)) { + android.provider.Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK)) { return; } final String intentUriString = intent.getStringExtra( - Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI); + android.provider.Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI); if (TextUtils.isEmpty(intentUriString)) { Log.e(TAG, "No EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI to deep link"); finish(); @@ -215,12 +215,17 @@ public class SettingsHomepageActivity extends FragmentActivity implements targetIntent.putExtra(EXTRA_IS_FROM_SETTINGS_HOMEPAGE, true); - // Set 2-pane pair rule for the external deep link page. + // Set 2-pane pair rule for the deep link page. ActivityEmbeddingRulesController.registerTwoPanePairRule(this, new ComponentName(Utils.SETTINGS_PACKAGE_NAME, ALIAS_DEEP_LINK), targetComponentName, true /* finishPrimaryWithSecondary */, true /* finishSecondaryWithPrimary */); + ActivityEmbeddingRulesController.registerTwoPanePairRule(this, + new ComponentName(Settings.class.getPackageName(), Settings.class.getName()), + targetComponentName, + true /* finishPrimaryWithSecondary */, + true /* finishSecondaryWithPrimary */); startActivity(targetIntent); }