diff options
| author | 2023-10-23 14:00:58 +0000 | |
|---|---|---|
| committer | 2023-12-20 17:50:04 +0000 | |
| commit | 91fe9133ffa4817cbc504328d6f35970062083d6 (patch) | |
| tree | 01c5ab121c2e42319b7f20d163272158b1e82c30 | |
| parent | 68fb1e93a1cc90c01822b716d585f181658fba19 (diff) | |
Add resolver sheet support for private profile
Only show private space content when launched from private space
Do not show private space content when launched from other users( works
as before this change. Two tabs if work profile is available and a
single tab with personal apps otherwise)
Bug: 307515485
Test: manual
Test: atest FrameworksCoreTests:ResolverActivityTest
Change-Id: Ic63a94ac03bac929c7d2957793888507720cd2e3
4 files changed, 171 insertions, 7 deletions
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 9a1796fd3d97..c7797c719e2c 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -64,3 +64,10 @@ flag { bug: "296829976" is_fixed_read_only: true } + +flag { + name: "allow_resolver_sheet_for_private_space" + namespace: "profile_experiences" + description: "Add support for Private Space in resolver sheet" + bug: "307515485" +}
\ No newline at end of file diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 7534d2960b7c..7dcbbea7df90 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -249,6 +249,7 @@ public class ResolverActivity extends Activity implements private UserHandle mCloneProfileUserHandle; private UserHandle mTabOwnerUserHandleForLaunch; + private UserHandle mPrivateProfileUserHandle; protected final LatencyTracker mLatencyTracker = getLatencyTracker(); @@ -441,6 +442,7 @@ public class ResolverActivity extends Activity implements mPersonalProfileUserHandle = fetchPersonalProfileUserHandle(); mWorkProfileUserHandle = fetchWorkProfileUserProfile(); mCloneProfileUserHandle = fetchCloneProfileUserHandle(); + mPrivateProfileUserHandle = fetchPrivateProfileUserHandle(); mTabOwnerUserHandleForLaunch = fetchTabOwnerUserHandleForLaunch(); // The last argument of createResolverListAdapter is whether to do special handling @@ -648,7 +650,8 @@ public class ResolverActivity extends Activity implements initialIntents, rList, filterLastUsed, - /* userHandle */ getPersonalProfileUserHandle()); + getPersonalProfileUserHandle()); + QuietModeManager quietModeManager = createQuietModeManager(); return new ResolverMultiProfilePagerAdapter( /* context */ this, @@ -747,6 +750,9 @@ public class ResolverActivity extends Activity implements } protected UserHandle getPersonalProfileUserHandle() { + if (privateSpaceEnabled() && isLaunchedAsPrivateProfile()){ + return mPrivateProfileUserHandle; + } return mPersonalProfileUserHandle; } protected @Nullable UserHandle getWorkProfileUserHandle() { @@ -761,6 +767,10 @@ public class ResolverActivity extends Activity implements return mTabOwnerUserHandleForLaunch; } + protected UserHandle getPrivateProfileUserHandle() { + return mPrivateProfileUserHandle; + } + protected UserHandle fetchPersonalProfileUserHandle() { // ActivityManager.getCurrentUser() refers to the current Foreground user. When clone/work // profile is active, we always make the personal tab from the foreground user. @@ -795,12 +805,28 @@ public class ResolverActivity extends Activity implements return mCloneProfileUserHandle; } + protected @Nullable UserHandle fetchPrivateProfileUserHandle() { + mPrivateProfileUserHandle = null; + UserManager userManager = getSystemService(UserManager.class); + for (final UserInfo userInfo : + userManager.getProfiles(mPersonalProfileUserHandle.getIdentifier())) { + if (userInfo.isPrivateProfile()) { + mPrivateProfileUserHandle = userInfo.getUserHandle(); + break; + } + } + return mPrivateProfileUserHandle; + } + private UserHandle fetchTabOwnerUserHandleForLaunch() { - // If we are in work profile's process, return WorkProfile user as owner, otherwise we - // always return PersonalProfile user as owner - return UserHandle.of(UserHandle.myUserId()).equals(getWorkProfileUserHandle()) - ? getWorkProfileUserHandle() - : getPersonalProfileUserHandle(); + // If we are in work or private profile's process, return WorkProfile/PrivateProfile user + // as owner, otherwise we always return PersonalProfile user as owner + if (UserHandle.of(UserHandle.myUserId()).equals(getWorkProfileUserHandle())) { + return getWorkProfileUserHandle(); + } else if (privateSpaceEnabled() && isLaunchedAsPrivateProfile()) { + return getPrivateProfileUserHandle(); + } + return getPersonalProfileUserHandle(); } private boolean hasWorkProfile() { @@ -816,7 +842,15 @@ public class ResolverActivity extends Activity implements && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier()); } + protected final boolean isLaunchedAsPrivateProfile() { + return getPrivateProfileUserHandle() != null + && (UserHandle.myUserId() == getPrivateProfileUserHandle().getIdentifier()); + } + protected boolean shouldShowTabs() { + if (privateSpaceEnabled() && isLaunchedAsPrivateProfile()) { + return false; + } return hasWorkProfile() && ENABLE_TABBED_VIEW; } @@ -2619,6 +2653,11 @@ public class ResolverActivity extends Activity implements return resolveInfo.userHandle; } + private boolean privateSpaceEnabled() { + return mIsIntentPicker && android.os.Flags.allowPrivateProfile() + && android.multiuser.Flags.allowResolverSheetForPrivateSpace(); + } + /** * An a11y delegate that expands resolver drawer when gesture navigation reaches a partially * invisible target in the list. diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index b6813ffba312..b209c7c261ba 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -30,6 +30,7 @@ import static com.android.internal.app.MatcherUtils.first; import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo; import static com.android.internal.app.ResolverWrapperActivity.sOverrides; +import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static org.hamcrest.CoreMatchers.allOf; @@ -46,6 +47,7 @@ import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.flag.junit.SetFlagsRule; import android.text.TextUtils; import android.view.View; import android.widget.RelativeLayout; @@ -88,7 +90,8 @@ public class ResolverActivityTest { public ActivityTestRule<ResolverWrapperActivity> mActivityRule = new ActivityTestRule<>(ResolverWrapperActivity.class, false, false); - + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Before public void cleanOverrideData() { sOverrides.reset(); @@ -1156,6 +1159,97 @@ public class ResolverActivityTest { sOverrides.cloneProfileUserHandle))); } + @Test + public void testTriggerFromPrivateProfile_withoutWorkProfile() throws RemoteException { + mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, + android.multiuser.Flags.FLAG_ALLOW_RESOLVER_SHEET_FOR_PRIVATE_SPACE); + markPrivateProfileUserAvailable(); + Intent sendIntent = createSendImageIntent(); + List<ResolvedComponentInfo> privateResolvedComponentInfos = + createResolvedComponentsForTest(3, sOverrides.privateProfileUserHandle); + setupResolverControllers(privateResolvedComponentInfos); + final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); + waitForIdle(); + onView(withId(R.id.tabs)).check(matches(not(isDisplayed()))); + assertThat(activity.getPersonalListAdapter().getCount(), is(3)); + onView(withId(R.id.button_once)).check(matches(not(isEnabled()))); + onView(withId(R.id.button_always)).check(matches(not(isEnabled()))); + for (ResolvedComponentInfo resolvedInfo : privateResolvedComponentInfos) { + assertEquals(resolvedInfo.getResolveInfoAt(0).userHandle, + sOverrides.privateProfileUserHandle); + } + } + + @Test + public void testTriggerFromPrivateProfile_withWorkProfilePresent(){ + mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, + android.multiuser.Flags.FLAG_ALLOW_RESOLVER_SHEET_FOR_PRIVATE_SPACE); + ResolverActivity.ENABLE_TABBED_VIEW = false; + markPrivateProfileUserAvailable(); + markWorkProfileUserAvailable(); + Intent sendIntent = createSendImageIntent(); + List<ResolvedComponentInfo> privateResolvedComponentInfos = + createResolvedComponentsForTest(3, sOverrides.privateProfileUserHandle); + setupResolverControllers(privateResolvedComponentInfos); + final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); + waitForIdle(); + assertThat(activity.getPersonalListAdapter().getCount(), is(3)); + onView(withId(R.id.tabs)).check(matches(not(isDisplayed()))); + assertEquals(activity.getMultiProfilePagerAdapterCount(), 1); + for (ResolvedComponentInfo resolvedInfo : privateResolvedComponentInfos) { + assertEquals(resolvedInfo.getResolveInfoAt(0).userHandle, + sOverrides.privateProfileUserHandle); + } + } + + @Test + public void testPrivateProfile_triggerFromPrimaryUser_withWorkProfilePresent(){ + mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, + android.multiuser.Flags.FLAG_ALLOW_RESOLVER_SHEET_FOR_PRIVATE_SPACE); + markPrivateProfileUserAvailable(); + markWorkProfileUserAvailable(); + Intent sendIntent = createSendImageIntent(); + List<ResolvedComponentInfo> personalResolvedComponentInfos = + createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE); + List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4, + sOverrides.workProfileUserHandle); + setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); + final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); + waitForIdle(); + assertThat(activity.getAdapter().getCount(), is(2)); + assertThat(activity.getWorkListAdapter().getCount(), is(4)); + onView(withId(R.id.tabs)).check(matches(isDisplayed())); + for (ResolvedComponentInfo resolvedInfo : personalResolvedComponentInfos) { + assertEquals(resolvedInfo.getResolveInfoAt(0).userHandle, + activity.getPersonalProfileUserHandle()); + } + } + + @Test + public void testPrivateProfile_triggerFromWorkProfile(){ + mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, + android.multiuser.Flags.FLAG_ALLOW_RESOLVER_SHEET_FOR_PRIVATE_SPACE); + markPrivateProfileUserAvailable(); + markWorkProfileUserAvailable(); + Intent sendIntent = createSendImageIntent(); + + List<ResolvedComponentInfo> personalResolvedComponentInfos = + createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE); + List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4, + sOverrides.workProfileUserHandle); + setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); + final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); + waitForIdle(); + assertThat(activity.getAdapter().getCount(), is(2)); + assertThat(activity.getWorkListAdapter().getCount(), is(4)); + onView(withId(R.id.tabs)).check(matches(isDisplayed())); + for (ResolvedComponentInfo resolvedInfo : personalResolvedComponentInfos) { + assertTrue(resolvedInfo.getResolveInfoAt(0).userHandle.equals( + activity.getPersonalProfileUserHandle()) || resolvedInfo.getResolveInfoAt( + 0).userHandle.equals(activity.getWorkProfileUserHandle())); + } + } + private Intent createSendImageIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); @@ -1237,6 +1331,10 @@ public class ResolverActivityTest { ResolverWrapperActivity.sOverrides.cloneProfileUserHandle = UserHandle.of(11); } + private void markPrivateProfileUserAvailable() { + ResolverWrapperActivity.sOverrides.privateProfileUserHandle = UserHandle.of(12); + } + private void setupResolverControllers( List<ResolvedComponentInfo> personalResolvedComponentInfos, List<ResolvedComponentInfo> workResolvedComponentInfos) { @@ -1256,4 +1354,13 @@ public class ResolverActivityTest { eq(UserHandle.SYSTEM))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); } + + private void setupResolverControllers( + List<ResolvedComponentInfo> resolvedComponentInfos) { + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(resolvedComponentInfos)); + } } diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java index e193de0a3b20..862cbd5b5e01 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java @@ -88,6 +88,10 @@ public class ResolverWrapperActivity extends ResolverActivity { return ((ResolverListAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1)); } + int getMultiProfilePagerAdapterCount(){ + return mMultiProfilePagerAdapter.getCount(); + } + @Override public boolean isVoiceInteraction() { if (sOverrides.isVoiceInteraction != null) { @@ -144,6 +148,11 @@ public class ResolverWrapperActivity extends ResolverActivity { } @Override + protected UserHandle getPrivateProfileUserHandle() { + return sOverrides.privateProfileUserHandle; + } + + @Override protected UserHandle getTabOwnerUserHandleForLaunch() { if (sOverrides.tabOwnerUserHandleForLaunch == null) { return super.getTabOwnerUserHandleForLaunch(); @@ -176,6 +185,7 @@ public class ResolverWrapperActivity extends ResolverActivity { public Boolean isVoiceInteraction; public UserHandle workProfileUserHandle; public UserHandle cloneProfileUserHandle; + public UserHandle privateProfileUserHandle; public UserHandle tabOwnerUserHandleForLaunch; public Integer myUserId; public boolean hasCrossProfileIntents; @@ -191,6 +201,7 @@ public class ResolverWrapperActivity extends ResolverActivity { workResolverListController = mock(ResolverListController.class); workProfileUserHandle = null; cloneProfileUserHandle = null; + privateProfileUserHandle = null; tabOwnerUserHandleForLaunch = null; myUserId = null; hasCrossProfileIntents = true; |