From 8311f680657ec7dcea4a938e97f2acaea1940f12 Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Wed, 27 Apr 2022 12:24:24 -0700 Subject: [PATCH 1/6] Fix Settings getProfileIdsWithDisabled usage In two places, Settings uses getProfileIdsWithDisabled intending to restrict itself to *managed* profiles, but actually allows for any type of profile. Since the declared intent is to only deal with managed profiles, we update the code to only consider managed profiles. On devices that only have managed profiles (currently almost all devices), this cl is a no-op. Bug: 230495929 Bug: 230534572 Bug: 170249807 Test: com.android.settings.UtilsTest Test: make RunSettingsRoboTests -j Change-Id: Id04d45839ef61080b00ca2f91525718cb3a85120 --- src/com/android/settings/Utils.java | 28 +++++++++---------- ...edactNotificationPreferenceController.java | 15 ++++++---- .../AppStateNotificationBridgeTest.java | 21 ++++++-------- ...ProfileStatusPreferenceControllerTest.java | 6 +++- ...ectedServicesPreferenceControllerTest.java | 4 +++ ...tNotificationPreferenceControllerTest.java | 13 ++++++--- ...atternProfilePreferenceControllerTest.java | 7 ++++- 7 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 2988ddcaedb..990667e537e 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -85,7 +85,6 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.TtsSpan; import android.util.ArraySet; -import android.util.FeatureFlagUtils; import android.util.IconDrawableFactory; import android.util.Log; import android.view.LayoutInflater; @@ -435,18 +434,20 @@ public final class Utils extends com.android.settingslib.Utils { * {@link #getManagedProfile} this method returns enabled and disabled managed profiles. */ public static UserHandle getManagedProfileWithDisabled(UserManager userManager) { - // TODO: Call getManagedProfileId from here once Robolectric supports - // API level 24 and UserManager.getProfileIdsWithDisabled can be Mocked (to avoid having - // yet another implementation that loops over user profiles in this method). In the meantime - // we need to use UserManager.getProfiles that is available on API 23 (the one currently - // used for Settings Robolectric tests). - final int myUserId = UserHandle.myUserId(); - final List profiles = userManager.getProfiles(myUserId); + return getManagedProfileWithDisabled(userManager, UserHandle.myUserId()); + } + + /** + * Returns the managed profile of the given user or {@code null} if none is found. Unlike + * {@link #getManagedProfile} this method returns enabled and disabled managed profiles. + */ + private static UserHandle getManagedProfileWithDisabled(UserManager um, int parentUserId) { + final List profiles = um.getProfiles(parentUserId); final int count = profiles.size(); for (int i = 0; i < count; i++) { final UserInfo profile = profiles.get(i); if (profile.isManagedProfile() - && profile.getUserHandle().getIdentifier() != myUserId) { + && profile.getUserHandle().getIdentifier() != parentUserId) { return profile.getUserHandle(); } } @@ -455,15 +456,14 @@ public final class Utils extends com.android.settingslib.Utils { /** * Retrieves the id for the given user's managed profile. + * Unlike {@link #getManagedProfile} this method returns enabled and disabled managed profiles. * * @return the managed profile id or UserHandle.USER_NULL if there is none. */ public static int getManagedProfileId(UserManager um, int parentUserId) { - final int[] profileIds = um.getProfileIdsWithDisabled(parentUserId); - for (int profileId : profileIds) { - if (profileId != parentUserId) { - return profileId; - } + final UserHandle profile = getManagedProfileWithDisabled(um, parentUserId); + if (profile != null) { + return profile.getIdentifier(); } return UserHandle.USER_NULL; } diff --git a/src/com/android/settings/notification/RedactNotificationPreferenceController.java b/src/com/android/settings/notification/RedactNotificationPreferenceController.java index 2d2718478c2..0b9ad4413ce 100644 --- a/src/com/android/settings/notification/RedactNotificationPreferenceController.java +++ b/src/com/android/settings/notification/RedactNotificationPreferenceController.java @@ -22,6 +22,7 @@ import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFIC import android.app.KeyguardManager; import android.content.Context; +import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Handler; import android.os.Looper; @@ -42,6 +43,8 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; +import java.util.List; + /** * The controller of the sensitive notifications. */ @@ -74,11 +77,13 @@ public class RedactNotificationPreferenceController extends TogglePreferenceCont mKm = context.getSystemService(KeyguardManager.class); mProfileUserId = UserHandle.myUserId(); - final int[] profileIds = mUm.getProfileIdsWithDisabled(UserHandle.myUserId()); - - for (int profileId : profileIds) { - if (profileId != UserHandle.myUserId()) { - mProfileUserId = profileId; + final List profiles = mUm.getProfiles(UserHandle.myUserId()); + final int count = profiles.size(); + for (int i = 0; i < count; i++) { + final UserInfo profile = profiles.get(i); + if (profile.isManagedProfile() + && profile.getUserHandle().getIdentifier() != UserHandle.myUserId()) { + mProfileUserId = profile.getUserHandle().getIdentifier(); } } } diff --git a/tests/robotests/src/com/android/settings/applications/AppStateNotificationBridgeTest.java b/tests/robotests/src/com/android/settings/applications/AppStateNotificationBridgeTest.java index b725fc30c02..61dd569cf52 100644 --- a/tests/robotests/src/com/android/settings/applications/AppStateNotificationBridgeTest.java +++ b/tests/robotests/src/com/android/settings/applications/AppStateNotificationBridgeTest.java @@ -18,16 +18,11 @@ package com.android.settings.applications; import static android.text.format.DateUtils.DAY_IN_MILLIS; -import static com.android.settings.applications.AppStateNotificationBridge - .FILTER_APP_NOTIFICATION_BLOCKED; -import static com.android.settings.applications.AppStateNotificationBridge - .FILTER_APP_NOTIFICATION_FREQUENCY; -import static com.android.settings.applications.AppStateNotificationBridge - .FILTER_APP_NOTIFICATION_RECENCY; -import static com.android.settings.applications.AppStateNotificationBridge - .FREQUENCY_NOTIFICATION_COMPARATOR; -import static com.android.settings.applications.AppStateNotificationBridge - .RECENT_NOTIFICATION_COMPARATOR; +import static com.android.settings.applications.AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED; +import static com.android.settings.applications.AppStateNotificationBridge.FILTER_APP_NOTIFICATION_FREQUENCY; +import static com.android.settings.applications.AppStateNotificationBridge.FILTER_APP_NOTIFICATION_RECENCY; +import static com.android.settings.applications.AppStateNotificationBridge.FREQUENCY_NOTIFICATION_COMPARATOR; +import static com.android.settings.applications.AppStateNotificationBridge.RECENT_NOTIFICATION_COMPARATOR; import static com.google.common.truth.Truth.assertThat; @@ -47,12 +42,12 @@ import android.app.usage.UsageEvents; import android.app.usage.UsageEvents.Event; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.UserInfo; import android.os.Looper; import android.os.Parcel; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; -import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.Switch; @@ -71,6 +66,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -288,7 +284,8 @@ public class AppStateNotificationBridgeTest { @Test public void testLoadAllExtraInfo_multipleUsers() throws RemoteException { // has work profile - when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{1}); + when(mUserManager.getProfiles(anyInt())).thenReturn(Arrays.asList( + new UserInfo(1, "", UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE))); mBridge = new AppStateNotificationBridge(mContext, mState, mock(AppStateBaseBridge.Callback.class), mUsageStats, mUserManager, mBackend); diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintProfileStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintProfileStatusPreferenceControllerTest.java index efcba9d9584..0988795dd10 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintProfileStatusPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintProfileStatusPreferenceControllerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.hardware.fingerprint.FingerprintManager; import android.os.UserManager; @@ -39,6 +40,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowApplication; +import java.util.Arrays; + @RunWith(RobolectricTestRunner.class) public class FingerprintProfileStatusPreferenceControllerTest { @@ -71,7 +74,8 @@ public class FingerprintProfileStatusPreferenceControllerTest { mFeatureFactory = FakeFeatureFactory.setupForTest(); when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) .thenReturn(mLockPatternUtils); - when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {1234}); + when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList( + new UserInfo(1234, "", UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE))); mController = new FingerprintProfileStatusPreferenceController(mContext, TEST_PREF_KEY); } diff --git a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java index ae62724cea5..bed3346ffba 100644 --- a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; +import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -118,6 +119,9 @@ public class LocationInjectedServicesPreferenceControllerTest { final int fakeWorkProfileId = 123; ShadowUserManager.getShadow().setProfileIdsWithDisabled( new int[]{UserHandle.myUserId(), fakeWorkProfileId}); + ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0)); + ShadowUserManager.getShadow().addProfile(new UserInfo(fakeWorkProfileId, "", + UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE)); // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return non-null. final List enforcingUsers = new ArrayList<>(); diff --git a/tests/robotests/src/com/android/settings/notification/RedactNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RedactNotificationPreferenceControllerTest.java index 72a2c2451ee..8304d82be9f 100644 --- a/tests/robotests/src/com/android/settings/notification/RedactNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/RedactNotificationPreferenceControllerTest.java @@ -34,11 +34,11 @@ import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.internal.widget.LockPatternUtils; @@ -57,6 +57,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import java.util.Arrays; + @RunWith(RobolectricTestRunner.class) @Config(shadows = { ShadowUtils.class, @@ -95,7 +97,7 @@ public class RedactNotificationPreferenceControllerTest { when(mMockContext.getSystemService(UserManager.class)).thenReturn(mUm); when(mMockContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDpm); when(mMockContext.getSystemService(KeyguardManager.class)).thenReturn(mKm); - when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {0}); + when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList(new UserInfo(0, "", 0))); mController = new RedactNotificationPreferenceController( mMockContext, RedactNotificationPreferenceController.KEY_LOCKSCREEN_REDACT); @@ -105,7 +107,9 @@ public class RedactNotificationPreferenceControllerTest { mController.getPreferenceKey())).thenReturn(mPreference); assertThat(mController.mProfileUserId).isEqualTo(0); - when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {0, 10}); + when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList( + new UserInfo(5, "", 0), + new UserInfo(10, "", UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE))); mWorkController = new RedactNotificationPreferenceController(mMockContext, RedactNotificationPreferenceController.KEY_LOCKSCREEN_WORK_PROFILE_REDACT); mWorkPreference = new RestrictedSwitchPreference(mContext); @@ -137,7 +141,8 @@ public class RedactNotificationPreferenceControllerTest { @Test public void getAvailabilityStatus_noWorkProfile() { // reset controllers with no work profile - when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {UserHandle.myUserId()}); + when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList( + new UserInfo(UserHandle.myUserId(), "", 0))); mWorkController = new RedactNotificationPreferenceController(mMockContext, RedactNotificationPreferenceController.KEY_LOCKSCREEN_WORK_PROFILE_REDACT); mController = new RedactNotificationPreferenceController(mMockContext, diff --git a/tests/robotests/src/com/android/settings/security/VisiblePatternProfilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/VisiblePatternProfilePreferenceControllerTest.java index 11d70165794..ba50eb85992 100644 --- a/tests/robotests/src/com/android/settings/security/VisiblePatternProfilePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/security/VisiblePatternProfilePreferenceControllerTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.hardware.fingerprint.FingerprintManager; import android.os.UserManager; @@ -49,6 +50,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowApplication; +import java.util.Arrays; + @RunWith(RobolectricTestRunner.class) public class VisiblePatternProfilePreferenceControllerTest { @@ -82,7 +85,9 @@ public class VisiblePatternProfilePreferenceControllerTest { mFeatureFactory = FakeFeatureFactory.setupForTest(); when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) .thenReturn(mLockPatternUtils); - when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {FAKE_PROFILE_USER_ID}); + when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList(new UserInfo( + FAKE_PROFILE_USER_ID, "", UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE))); + mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); From d9453bf8c612ee315bb8036698cec8c9a02b78fe Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Wed, 4 May 2022 21:05:11 +0800 Subject: [PATCH 2/6] Show previous query upon configuration change Save the query string before configuration changed and set the previous query string upon the re-create. Fixes: 204158119 Test: robotest Change-Id: I48b2a4b272873665a653d2ebc4c02bb99d4b0d0d --- .../ManageApplications.java | 9 ++++ .../ManageApplicationsTest.java | 50 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 062bfc576b2..c081ef9af1e 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -173,6 +173,8 @@ public class ManageApplications extends InstrumentedFragment private static final String EXTRA_HAS_BRIDGE = "hasBridge"; private static final String EXTRA_FILTER_TYPE = "filterType"; @VisibleForTesting + static final String EXTRA_SEARCH_QUERY = "search_query"; + @VisibleForTesting static final String EXTRA_EXPAND_SEARCH_VIEW = "expand_search_view"; // attributes used as keys when passing values to AppInfoDashboardFragment activity @@ -253,6 +255,8 @@ public class ManageApplications extends InstrumentedFragment // Whether or not search view is expanded. @VisibleForTesting boolean mExpandSearch; + @VisibleForTesting + CharSequence mPreQuery; private View mRootView; private Spinner mFilterSpinner; @@ -358,6 +362,7 @@ public class ManageApplications extends InstrumentedFragment mFilterType = savedInstanceState.getInt(EXTRA_FILTER_TYPE, AppFilterRegistry.FILTER_APPS_ALL); mExpandSearch = savedInstanceState.getBoolean(EXTRA_EXPAND_SEARCH_VIEW); + mPreQuery = savedInstanceState.getCharSequence(EXTRA_SEARCH_QUERY); } mInvalidSizeStr = activity.getText(R.string.invalid_size_value); @@ -544,6 +549,7 @@ public class ManageApplications extends InstrumentedFragment outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem); if (mSearchView != null) { outState.putBoolean(EXTRA_EXPAND_SEARCH_VIEW, !mSearchView.isIconified()); + outState.putCharSequence(EXTRA_SEARCH_QUERY, mSearchView.getQuery()); } if (mApplications != null) { outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries); @@ -683,6 +689,9 @@ public class ManageApplications extends InstrumentedFragment if (mExpandSearch) { searchMenuItem.expandActionView(); } + if (!TextUtils.isEmpty(mPreQuery)) { + mSearchView.setQuery(mPreQuery, true); + } } updateOptionsMenu(); diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java index da17f1143bb..ec4f8f2e8b6 100644 --- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java +++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java @@ -188,6 +188,24 @@ public class ManageApplicationsTest { verify(searchMenu).expandActionView(); } + @Test + public void onCreateOptionsMenu_hasPreQuery_shouldSetQuery() { + final SearchView searchView = mock(SearchView.class); + final MenuItem searchMenu = mock(MenuItem.class); + final MenuItem helpMenu = mock(MenuItem.class); + when(searchMenu.getActionView()).thenReturn(searchView); + when(mMenu.findItem(R.id.search_app_list_menu)).thenReturn(searchMenu); + when(mMenu.add(anyInt() /* groupId */, anyInt() /* itemId */, anyInt() /* order */, + anyInt() /* titleRes */)).thenReturn(helpMenu); + doReturn("Test").when(mFragment).getText(anyInt() /* resId */); + doNothing().when(mFragment).updateOptionsMenu(); + + mFragment.mPreQuery = "test"; + mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class)); + + verify(searchView).setQuery("test", true); + } + @Test public void onQueryTextChange_shouldFilterSearchInApplicationsAdapter() { final ManageApplications.ApplicationsAdapter adapter = @@ -518,6 +536,38 @@ public class ManageApplicationsTest { assertThat(bundle.getBoolean(ManageApplications.EXTRA_EXPAND_SEARCH_VIEW)).isFalse(); } + @Test + public void onSaveInstanceState_noSearchView_shouldNotSaveQuery() { + final Bundle bundle = new Bundle(); + ReflectionHelpers.setField(mFragment, "mResetAppsHelper", mock(ResetAppsHelper.class)); + ReflectionHelpers.setField(mFragment, "mFilter", mock(AppFilterItem.class)); + ReflectionHelpers.setField(mFragment, "mApplications", + mock(ManageApplications.ApplicationsAdapter.class)); + + mFragment.onSaveInstanceState(bundle); + + assertThat(bundle.containsKey(ManageApplications.EXTRA_SEARCH_QUERY)).isFalse(); + } + + @Test + public void onSaveInstanceState_searchViewSet_shouldSaveQuery() { + final SearchView searchView = mock(SearchView.class); + final Bundle bundle = new Bundle(); + ReflectionHelpers.setField(mFragment, "mResetAppsHelper", mock(ResetAppsHelper.class)); + ReflectionHelpers.setField(mFragment, "mFilter", mock(AppFilterItem.class)); + ReflectionHelpers.setField(mFragment, "mApplications", + mock(ManageApplications.ApplicationsAdapter.class)); + ReflectionHelpers.setField(mFragment, "mSearchView", searchView); + when(searchView.isIconified()).thenReturn(true); + when(searchView.getQuery()).thenReturn("test"); + + mFragment.onSaveInstanceState(bundle); + + assertThat(bundle.containsKey(ManageApplications.EXTRA_SEARCH_QUERY)).isTrue(); + assertThat(bundle.getCharSequence(ManageApplications.EXTRA_SEARCH_QUERY)) + .isEqualTo("test"); + } + @Test public void createHeader_batteryListType_hasCorrectItems() { ReflectionHelpers.setField(mFragment, "mListType", ManageApplications.LIST_TYPE_HIGH_POWER); From 322d401aa8250feac291608932220d3fee2a1a8b Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Tue, 3 May 2022 14:00:29 +0000 Subject: [PATCH 3/6] Move set work lock message from header to footer Also update the string. Bug: 206083998 Bug: 230625178 Test: NA Change-Id: I3e442f6a43e01f3633255551aa42902bf24e4aa8 --- res/values/strings.xml | 2 +- .../settings/password/ChooseLockGeneric.java | 61 ++++++++++--------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index cfcb62e000c..5c4fbc4f674 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1402,7 +1402,7 @@ Choose your backup screen lock method - This lock can\u2019t be reset by your IT admin. LINK_BEGINSet a separate work lock insteadLINK_END + If you forget your screen lock, your IT admin can\u2019t reset it. Set a separate work lock If you forget this lock, ask your IT admin to reset it diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 841d1f9440b..a8d0160d620 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -66,7 +66,6 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockscreenCredential; import com.android.settings.EncryptionInterstitial; import com.android.settings.EventLogTags; -import com.android.settings.LinkifyUtils; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; @@ -77,7 +76,9 @@ import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.safetycenter.LockScreenSafetySource; import com.android.settings.search.SearchFeatureProvider; +import com.android.settings.utils.AnnotationSpan; import com.android.settingslib.RestrictedPreference; +import com.android.settingslib.widget.FooterPreference; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -400,32 +401,7 @@ public class ChooseLockGeneric extends SettingsActivity { WORK_PROFILE_SCREEN_LOCK_SETUP_MESSAGE, () -> getString(R.string.lock_settings_picker_profile_message))); } else { - int profileUserId = Utils.getManagedProfileId(mUserManager, mUserId); - if (mController.isScreenLockRestrictedByAdmin() - && profileUserId != UserHandle.USER_NULL) { - final StringBuilder description = new StringBuilder( - mDpm.getResources().getString( - WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK, - () -> getString( - R.string.lock_settings_picker_admin_restricted_personal_message))); - final LinkifyUtils.OnClickListener clickListener = () -> { - final Bundle extras = new Bundle(); - extras.putInt(Intent.EXTRA_USER_ID, profileUserId); - if (mUserPassword != null) { - extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, - mUserPassword); - } - new SubSettingLauncher(getActivity()) - .setDestination(ChooseLockGenericFragment.class.getName()) - .setSourceMetricsCategory(getMetricsCategory()) - .setArguments(extras) - .launch(); - finish(); - }; - LinkifyUtils.linkify(textView, description, clickListener); - } else { - textView.setText(""); - } + textView.setText(""); } } } @@ -630,10 +606,39 @@ public class ChooseLockGeneric extends SettingsActivity { protected void addPreferences() { addPreferencesFromResource(R.xml.security_settings_picker); - final Preference footer = findPreference(KEY_LOCK_SETTINGS_FOOTER); + int profileUserId = Utils.getManagedProfileId(mUserManager, mUserId); + final FooterPreference footer = findPreference(KEY_LOCK_SETTINGS_FOOTER); if (!TextUtils.isEmpty(mCallerAppName) && !mIsCallingAppAdmin) { footer.setVisible(true); footer.setTitle(getFooterString()); + } else if (!mForFace && !mForBiometrics && !mForFingerprint && !mIsManagedProfile + && mController.isScreenLockRestrictedByAdmin() + && profileUserId != UserHandle.USER_NULL) { + CharSequence description = + mDpm.getResources().getString(WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK, + () -> null); + if (description == null) { + description = getText( + R.string.lock_settings_picker_admin_restricted_personal_message); + } + final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo( + AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, (view) -> { + final Bundle extras = new Bundle(); + extras.putInt(Intent.EXTRA_USER_ID, profileUserId); + if (mUserPassword != null) { + extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, + mUserPassword); + } + new SubSettingLauncher(getActivity()) + .setDestination(ChooseLockGenericFragment.class.getName()) + .setSourceMetricsCategory(getMetricsCategory()) + .setArguments(extras) + .launch(); + finish(); + }); + CharSequence footerText = AnnotationSpan.linkify(description, linkInfo); + footer.setVisible(true); + footer.setTitle(footerText); } else { footer.setVisible(false); } From 130a64779eaa23aee5ee986d8f593cd03ed16466 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Thu, 5 May 2022 11:45:48 +0800 Subject: [PATCH 4/6] Fix Learn more link not work Old span text shall not be used in preference footer. Change implementation to use footer learnMore APIs Bug: 228101275 Test: Make sure "Learn more" can be clicked on Fingerprint setting page Change-Id: Ied2326b1a75fc02e7a3fe2321735f2f9f5ac066f --- res/values/strings.xml | 8 ++++++-- .../fingerprint/FingerprintSettings.java | 14 +++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index e333969e471..76ac7e94539 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1044,8 +1044,12 @@ You\u2019ve reached the maximum number of attempts - - Use your fingerprint to unlock your phone or verify it\u2019s you, like when you sign in to apps\n\nLearn more + + Use your fingerprint to unlock your tablet or verify it\u2019s you, like when you sign in to apps + + Use your fingerprint to unlock your device or verify it\u2019s you, like when you sign in to apps + + Use your fingerprint to unlock your phone or verify it\u2019s you, like when you sign in to apps diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java index 22821920722..408f8596aac 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java @@ -145,6 +145,7 @@ public class FingerprintSettings extends SubSettings { private Drawable mHighlightDrawable; private int mUserId; private CharSequence mFooterTitle; + private View.OnClickListener mLearnMoreListener = null; private boolean mEnrollClicked; private long mChallenge; @@ -372,9 +373,8 @@ public class FingerprintSettings extends SubSettings { mFooterTitle = AnnotationSpan.linkify(footerText, linkInfo, adminLinkInfo); } else { - mFooterTitle = AnnotationSpan.linkify( - getText(R.string.security_settings_fingerprint_v2_home_screen), - linkInfo, adminLinkInfo); + mFooterTitle = getText(R.string.security_settings_fingerprint_v2_home_screen_text); + mLearnMoreListener = (v) -> activity.startActivityForResult(helpIntent, 0); } @@ -474,8 +474,12 @@ public class FingerprintSettings extends SubSettings { if (context == null) { return; } - root.addPreference(new FooterPreference.Builder(context).setTitle( - mFooterTitle).build()); + final FooterPreference footer = new FooterPreference.Builder(context) + .setTitle(mFooterTitle).build(); + if (mLearnMoreListener != null) { + footer.setLearnMoreAction(mLearnMoreListener); + } + root.addPreference(footer); } private static String genKey(int id) { From e8bb9c9be31c09fc494f7d61bba745aeecd4a28c Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Thu, 5 May 2022 16:54:00 +0800 Subject: [PATCH 5/6] [BT Broadcast Sink] Add the function for leave and scan QRcode buttons Add function for 'leave broadcast' button Add function for 'Scan QR code' button Set 'level broadcast' button gray out when device does not have broadcast source Bug: 228259065 Test: build pass and manually test Change-Id: Iab4a45e73f49c3f755b95ea3fa38872daac7e745 --- .../BluetoothFindBroadcastsFragment.java | 40 ++++++++++++-- ...uetoothFindBroadcastsHeaderController.java | 53 +++++++++++++++---- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java index 9a26a57f0fc..07a31560d24 100644 --- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java @@ -75,6 +75,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment CachedBluetoothDevice mCachedDevice; @VisibleForTesting PreferenceCategory mBroadcastSourceListCategory; + BluetoothFindBroadcastsHeaderController mBluetoothFindBroadcastsHeaderController; private LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant; private BluetoothBroadcastSourcePreference mSelectedPreference; private Executor mExecutor; @@ -93,7 +94,6 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment @Override public void onSearchStartFailed(int reason) { Log.d(TAG, "onSearchStartFailed: " + reason); - } @Override @@ -240,6 +240,28 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment return SettingsEnums.PAGE_UNKNOWN; } + /** + * Starts to scan broadcast source by the BluetoothLeBroadcastAssistant. + */ + public void scanBroadcastSource() { + if (mLeBroadcastAssistant == null) { + Log.w(TAG, "scanBroadcastSource: LeBroadcastAssistant is null!"); + return; + } + mLeBroadcastAssistant.startSearchingForSources(getScanFilter()); + } + + /** + * Leaves the broadcast source by the BluetoothLeBroadcastAssistant. + */ + public void leaveBroadcastSession() { + if (mLeBroadcastAssistant == null || mCachedDevice == null) { + Log.w(TAG, "leaveBroadcastSession: LeBroadcastAssistant or CachedDevice is null!"); + return; + } + mLeBroadcastAssistant.removeSource(mCachedDevice.getDevice(), getSourceId()); + } + @Override protected String getLogTag() { return TAG; @@ -256,13 +278,18 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment if (mCachedDevice != null) { Lifecycle lifecycle = getSettingsLifecycle(); - controllers.add(new BluetoothFindBroadcastsHeaderController(context, this, - mCachedDevice, lifecycle, mManager)); + mBluetoothFindBroadcastsHeaderController = new BluetoothFindBroadcastsHeaderController( + context, this, mCachedDevice, lifecycle, mManager); + controllers.add(mBluetoothFindBroadcastsHeaderController); } return controllers; } - private LocalBluetoothLeBroadcastAssistant getLeBroadcastAssistant() { + /** + * Gets the LocalBluetoothLeBroadcastAssistant + * @return the LocalBluetoothLeBroadcastAssistant + */ + public LocalBluetoothLeBroadcastAssistant getLeBroadcastAssistant() { if (mManager == null) { Log.w(TAG, "getLeBroadcastAssistant: LocalBluetoothManager is null!"); return null; @@ -292,6 +319,11 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment } item.updateMetadataAndRefreshUi(source, isConnected); item.setOrder(isConnected ? 0 : 1); + + //refresh the header + if (mBluetoothFindBroadcastsHeaderController != null) { + mBluetoothFindBroadcastsHeaderController.refreshUi(); + } } private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference( diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java index dfdcae05109..1527f2145fe 100644 --- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java +++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java @@ -16,22 +16,24 @@ package com.android.settings.bluetooth; +import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.util.Log; +import android.content.Intent; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import com.android.settings.R; +import com.android.settingslib.bluetooth.BluetoothBroadcastUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.qrcode.QrCodeScanModeActivity; import com.android.settingslib.widget.LayoutPreference; /** @@ -52,11 +54,12 @@ public class BluetoothFindBroadcastsHeaderController extends BluetoothDetailsCon LinearLayout mBtnBroadcastLayout; Button mBtnLeaveBroadcast; Button mBtnScanQrCode; - + BluetoothFindBroadcastsFragment mBluetoothFindBroadcastsFragment; public BluetoothFindBroadcastsHeaderController(Context context, - PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle, - LocalBluetoothManager bluetoothManager) { + BluetoothFindBroadcastsFragment fragment, CachedBluetoothDevice device, + Lifecycle lifecycle, LocalBluetoothManager bluetoothManager) { super(context, fragment, device, lifecycle); + mBluetoothFindBroadcastsFragment = fragment; } @Override @@ -101,20 +104,41 @@ public class BluetoothFindBroadcastsHeaderController extends BluetoothDetailsCon mBtnFindBroadcast.setVisibility(View.VISIBLE); mBtnBroadcastLayout.setVisibility(View.GONE); } + + mBtnLeaveBroadcast.setEnabled(false); + if (mBluetoothFindBroadcastsFragment != null && mCachedDevice != null) { + LocalBluetoothLeBroadcastAssistant broadcastAssistant = + mBluetoothFindBroadcastsFragment.getLeBroadcastAssistant(); + if (broadcastAssistant != null + && broadcastAssistant.getConnectionStatus(mCachedDevice.getDevice()) + == BluetoothProfile.STATE_CONNECTED) { + mBtnLeaveBroadcast.setEnabled(true); + } + } } private void scanBroadcastSource() { - // TODO(b/228258236) : Call the LocalBluetoothLeBroadcastAssistant - // to start searching for source + // TODO(b/231543455) : Using the BluetoothDeviceUpdater to refactor it. + if (mBluetoothFindBroadcastsFragment == null) { + return; + } + mBluetoothFindBroadcastsFragment.scanBroadcastSource(); } private void leaveBroadcastSession() { - // TODO(b/228258236) : Call the LocalBluetoothLeBroadcastAssistant - // to leave the broadcast session + if (mBluetoothFindBroadcastsFragment == null) { + return; + } + mBluetoothFindBroadcastsFragment.leaveBroadcastSession(); } private void launchQrCodeScanner() { - // TODO(b/228259065) : Launch the QR code scanner page by intent + final Intent intent = new Intent(mContext, QrCodeScanModeActivity.class); + intent.setAction(BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER) + .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, false) + .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK, + mCachedDevice.getDevice()); + mContext.startActivity(intent); } @Override @@ -128,4 +152,11 @@ public class BluetoothFindBroadcastsHeaderController extends BluetoothDetailsCon public String getPreferenceKey() { return KEY_BROADCAST_HEADER; } + + /** + * Updates the UI + */ + public void refreshUi() { + updateHeaderLayout(); + } } From 358dd2b494a2f6110ee2c946f0f7b9446a36d83b Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Fri, 6 May 2022 04:07:50 +0000 Subject: [PATCH 6/6] Revert "Prevent side channel package installation enumeration" This reverts commit 263592e3dd2cba5769bdede8cc11244de94f4fd9. Reason for revert: Bug: b/231461076 Bug: b/231164585 Change-Id: I29211e5de9d7edef8c61125b8be047b6247c8773 --- AndroidManifest.xml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1f9c9086c48..4d3b6d0e3f9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1451,8 +1451,7 @@ + android:noHistory="true"> @@ -1522,7 +1521,6 @@ @@ -1536,8 +1534,7 @@ + android:exported="true"> @@ -1896,8 +1893,7 @@ + android:label="@string/usage_access_title">