summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Olivier Nshimiye <onshimiye@google.com> 2023-12-22 11:21:29 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-12-22 11:21:29 +0000
commit7cfe304e40438e8fef5175eba59cff0bbea10ffe (patch)
treed6e56a76b4452d47cae31450f7f872382200ad52
parente9d4b63179a7dfdab77fc0a0111c78a266dcea07 (diff)
parent91fe9133ffa4817cbc504328d6f35970062083d6 (diff)
Merge "Add resolver sheet support for private profile" into main
-rw-r--r--core/java/android/content/pm/multiuser.aconfig7
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java51
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java109
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java11
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;