diff --git a/core/java/android/app/admin/DevicePolicyResources.java b/core/java/android/app/admin/DevicePolicyResources.java index 052f670b71bd6..77ba560f29a19 100644 --- a/core/java/android/app/admin/DevicePolicyResources.java +++ b/core/java/android/app/admin/DevicePolicyResources.java @@ -1662,14 +1662,16 @@ public final class DevicePolicyResources { /** * Label returned from * {@link android.content.pm.CrossProfileApps#getProfileSwitchingLabel(UserHandle)} - * that calling app can show to user for the semantic of switching to work profile. + * that calling app can show to user for the semantic of switching to work profile, and + * accepts the app name as a param. */ public static final String SWITCH_TO_WORK_LABEL = PREFIX + "SWITCH_TO_WORK_LABEL"; /** * Label returned from * {@link android.content.pm.CrossProfileApps#getProfileSwitchingLabel(UserHandle)} - * that calling app can show to user for the semantic of switching to personal profile. + * that calling app can show to user for the semantic of switching to personal profile, + * and accepts the app name as a param. */ public static final String SWITCH_TO_PERSONAL_LABEL = PREFIX + "SWITCH_TO_PERSONAL_LABEL"; diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index d6951eec904f4..7ac8f37c645e4 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -18,6 +18,7 @@ package android.content.pm; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_PERSONAL_LABEL; import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_WORK_LABEL; +import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import android.annotation.NonNull; import android.annotation.Nullable; @@ -40,6 +41,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.text.TextUtils; import com.android.internal.R; import com.android.internal.util.UserIcons; @@ -329,19 +331,40 @@ public class CrossProfileApps { final boolean isManagedProfile = mUserManager.isManagedProfile(userHandle.getIdentifier()); final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + final String callingAppLabel = getCallingApplicationLabel().toString(); return dpm.getResources().getString( getUpdatableProfileSwitchingLabelId(isManagedProfile), - () -> getDefaultProfileSwitchingLabel(isManagedProfile)); + () -> getDefaultProfileSwitchingLabel(isManagedProfile, callingAppLabel), + callingAppLabel); + } + + private CharSequence getCallingApplicationLabel() { + PackageManager pm = mContext.getPackageManager(); + // If there is a label for the launcher intent, then use that as it is typically shorter. + // Otherwise, just use the top-level application name. + Intent launchIntent = pm.getLaunchIntentForPackage(mContext.getPackageName()); + List infos = + pm.queryIntentActivities( + launchIntent, PackageManager.ResolveInfoFlags.of(MATCH_DEFAULT_ONLY)); + if (infos.size() > 0) { + return infos.get(0).loadLabel(pm); + } + return mContext.getApplicationInfo() + .loadSafeLabel( + pm, + /* ellipsizeDip= */ 0, + TextUtils.SAFE_STRING_FLAG_SINGLE_LINE + | TextUtils.SAFE_STRING_FLAG_TRIM); } private String getUpdatableProfileSwitchingLabelId(boolean isManagedProfile) { return isManagedProfile ? SWITCH_TO_WORK_LABEL : SWITCH_TO_PERSONAL_LABEL; } - private String getDefaultProfileSwitchingLabel(boolean isManagedProfile) { + private String getDefaultProfileSwitchingLabel(boolean isManagedProfile, String label) { final int stringRes = isManagedProfile - ? R.string.managed_profile_label : R.string.user_owner_label; - return mResources.getString(stringRes); + ? R.string.managed_profile_app_label : R.string.user_owner_app_label; + return mResources.getString(stringRes, label); } @@ -366,10 +389,18 @@ public class CrossProfileApps { if (isManagedProfile) { return mContext.getPackageManager().getUserBadgeForDensityNoBackground( userHandle, /* density= */ 0); - } else { - return UserIcons.getDefaultUserIcon( - mResources, UserHandle.USER_SYSTEM, true /* light */); } + Drawable personalProfileIcon = UserIcons.getDefaultUserIcon( + mResources, UserHandle.USER_SYSTEM, /* light= */ true); + // Using the same colors as the managed profile icon. + int colorId = mContext.getResources().getConfiguration().isNightModeActive() + ? R.color.profile_badge_1_dark + : R.color.profile_badge_1; + // First set the color filter to null so that it does not override + // the tint. + personalProfileIcon.setColorFilter(null); + personalProfileIcon.setTint(mResources.getColor(colorId, /* theme= */ null)); + return personalProfileIcon; } /** diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index c6462f15ec509..a49ea0bd55fb0 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -861,6 +861,12 @@ Switch to work profile + + Switch to personal %1$s + + + Switch to work %1$s + Contacts diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b7df6a482983c..ae107fd648d3b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1068,7 +1068,9 @@ + + diff --git a/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java index 5e076076d2f45..661b210f3e185 100644 --- a/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java +++ b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java @@ -20,15 +20,18 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_PER import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_WORK_LABEL; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyResourcesManager; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.UserHandle; @@ -76,15 +79,21 @@ public class CrossProfileAppsTest { private Drawable mDrawable; @Mock private PackageManager mPackageManager; + + @Mock private ApplicationInfo mApplicationInfo; + + private Configuration mConfiguration; + private CrossProfileApps mCrossProfileApps; @Before public void initCrossProfileApps() { - mCrossProfileApps = new CrossProfileApps(mContext, mService); + mCrossProfileApps = spy(new CrossProfileApps(mContext, mService)); } @Before public void mockContext() { + mConfiguration = new Configuration(); when(mContext.getPackageName()).thenReturn(MY_PACKAGE); when(mContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); @@ -94,6 +103,8 @@ public class CrossProfileAppsTest { mDevicePolicyManager); when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager); when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); + when(mResources.getConfiguration()).thenReturn(mConfiguration); } @Before @@ -115,17 +126,20 @@ public class CrossProfileAppsTest { @Test public void getProfileSwitchingLabel_managedProfile() { setValidTargetProfile(MANAGED_PROFILE); + when(mApplicationInfo.loadSafeLabel(any(), anyFloat(), anyInt())).thenReturn("app"); mCrossProfileApps.getProfileSwitchingLabel(MANAGED_PROFILE); - verify(mDevicePolicyResourcesManager).getString(eq(SWITCH_TO_WORK_LABEL), any()); + verify(mDevicePolicyResourcesManager).getString(eq(SWITCH_TO_WORK_LABEL), any(), eq("app")); } @Test public void getProfileSwitchingLabel_personalProfile() { setValidTargetProfile(PERSONAL_PROFILE); + when(mApplicationInfo.loadSafeLabel(any(), anyFloat(), anyInt())).thenReturn("app"); mCrossProfileApps.getProfileSwitchingLabel(PERSONAL_PROFILE); - verify(mDevicePolicyResourcesManager).getString(eq(SWITCH_TO_PERSONAL_LABEL), any()); + verify(mDevicePolicyResourcesManager) + .getString(eq(SWITCH_TO_PERSONAL_LABEL), any(), eq("app")); } @Test(expected = SecurityException.class)