diff options
| author | 2023-12-22 11:21:29 +0000 | |
|---|---|---|
| committer | 2023-12-22 11:21:29 +0000 | |
| commit | 7cfe304e40438e8fef5175eba59cff0bbea10ffe (patch) | |
| tree | d6e56a76b4452d47cae31450f7f872382200ad52 | |
| parent | e9d4b63179a7dfdab77fc0a0111c78a266dcea07 (diff) | |
| parent | 91fe9133ffa4817cbc504328d6f35970062083d6 (diff) | |
Merge "Add resolver sheet support for private profile" into main
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; |