Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67d2ec38 authored by Anthony Alridge's avatar Anthony Alridge
Browse files

Update UI for account switcher

The text is updated to include the app name.
(strings will be updated following go/android-late-strings)

The personal profile icon is tinted with the same
color as the work badge (blue).

Tints are set using setColorFilter(...) so that they
are not overridden by callers using setTint.

Bug: 261717754
Test: Manual - screenshots in bug
Change-Id: I0eac34e908bb0fe6430abb2a9c05e6d5e9b414e0
parent 96e51591
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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";
+38 −7
Original line number Diff line number Diff line
@@ -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<ResolveInfo> 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;
    }

    /**
+6 −0
Original line number Diff line number Diff line
@@ -861,6 +861,12 @@
    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <string name="managed_profile_label">Switch to work profile</string>

    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <string name="user_owner_app_label">Switch to personal <xliff:g id="app_name" example="Gmail">%1$s</xliff:g></string>

    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <string name="managed_profile_app_label">Switch to work <xliff:g id="app_name" example="Gmail">%1$s</xliff:g></string>

    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permgrouplab_contacts">Contacts</string>
    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+2 −0
Original line number Diff line number Diff line
@@ -1068,7 +1068,9 @@
  <java-symbol type="string" name="action_bar_home_subtitle_description_format" />
  <java-symbol type="string" name="wireless_display_route_description" />
  <java-symbol type="string" name="user_owner_label" />
  <java-symbol type="string" name="user_owner_app_label" />
  <java-symbol type="string" name="managed_profile_label" />
  <java-symbol type="string" name="managed_profile_app_label" />
  <java-symbol type="string" name="managed_profile_label_badge" />
  <java-symbol type="string" name="managed_profile_label_badge_2" />
  <java-symbol type="string" name="managed_profile_label_badge_3" />
+17 −3
Original line number Diff line number Diff line
@@ -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)