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

Commit e8099f4d authored by Aditya's avatar Aditya
Browse files

Add package install check before adding userId to list.

DocsUi returns null label and badge for profiles that don't have the
com.google.android.documentsui package installed. This change adds a
check to ensure that only profiles with the package installed are added
to the user list, preventing crashes caused by operations on null badges
or labels.

Bug: 387266472
Test: manual
Flag: EXEMPT bugfix
Change-Id: Ia731cb56796bb2a870fe37d642a062980f756c15
parent 69497e69
Loading
Loading
Loading
Loading
+63 −8
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.util.Log;

import androidx.annotation.GuardedBy;
import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresPermission;
import androidx.annotation.VisibleForTesting;

import com.android.documentsui.base.Features;
@@ -91,7 +92,8 @@ public interface UserManagerState {
     *
     * @param userId {@link UserId} for the profile for which the availability status changed
     * @param action {@link Intent}.ACTION_PROFILE_UNAVAILABLE and {@link
     *     Intent}.ACTION_PROFILE_AVAILABLE, {@link Intent}.ACTION_PROFILE_ADDED} and {@link
     *               Intent}.ACTION_PROFILE_AVAILABLE, {@link Intent}.ACTION_PROFILE_ADDED} and
     *               {@link
     *               Intent}.ACTION_PROFILE_REMOVED}
     */
    void onProfileActionStatusChange(String action, UserId userId);
@@ -354,16 +356,69 @@ public interface UserManagerState {
            }
        }

        /**
         * Checks if a package is installed for a given user.
         *
         * @param userHandle The ID of the user.
         * @return {@code true} if the package is installed for the user, {@code false} otherwise.
         */
        @RequiresPermission(anyOf = {
                "android.permission.MANAGE_USERS",
                "android.permission.INTERACT_ACROSS_USERS"
        })
        private boolean isPackageInstalledForUser(UserHandle userHandle) {
            String packageName = mContext.getPackageName();
            try {
                Context userPackageContext = mContext.createPackageContextAsUser(
                        mContext.getPackageName(), 0 /* flags */, userHandle);
                return userPackageContext != null;
            } catch (PackageManager.NameNotFoundException e) {
                Log.w(TAG, "Package " + packageName + " not found for user " + userHandle);
                return false;
            }
        }

        /**
         * Checks if quiet mode is enabled for a given user.
         *
         * @param userHandle The UserHandle of the profile to check.
         * @return {@code true} if quiet mode is enabled, {@code false} otherwise.
         */
        private boolean isQuietModeEnabledForUser(UserHandle userHandle) {
            return UserId.of(userHandle.getIdentifier()).isQuietModeEnabled(mContext);
        }

        /**
         * Checks if a profile should be allowed, taking into account quiet mode and package
         * installation.
         *
         * @param userHandle The UserHandle of the profile to check.
         * @return {@code true} if the profile should be allowed, {@code false} otherwise.
         */
        @SuppressLint("NewApi")
        @RequiresPermission(anyOf = {
                "android.permission.MANAGE_USERS",
                "android.permission.INTERACT_ACROSS_USERS"
        })
        private boolean isProfileAllowed(UserHandle userHandle) {
            final UserProperties userProperties =
                    mUserManager.getUserProperties(userHandle);
            final UserProperties userProperties = mUserManager.getUserProperties(userHandle);

            // 1. Check if the package is installed for the user
            if (!isPackageInstalledForUser(userHandle)) {
                Log.w(TAG, "Package " + mContext.getPackageName()
                        + " is not installed for user " + userHandle);
                return false;
            }

            // 2. Check user properties and quiet mode
            if (userProperties.getShowInSharingSurfaces()
                    == UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) {
                return !UserId.of(userHandle).isQuietModeEnabled(mContext)
                        || userProperties.getShowInQuietMode()
                // Return true if profile is not in quiet mode or if it is in quiet mode
                // then its user properties do not require it to be hidden
                return !isQuietModeEnabledForUser(userHandle) || userProperties.getShowInQuietMode()
                        != UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
            }

            return false;
        }

+15 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class UserManagerStateTest {
    private static final String PERSONAL = "Personal";
    private static final String WORK = "Work";
    private static final String PRIVATE = "Private";
    private static final String PACKAGE_NAME = "com.android.documentsui";

    /**
     * Assume that the current user is SYSTEM_USER.
@@ -158,6 +159,20 @@ public class UserManagerStateTest {
                .thenReturn(mDevicePolicyManager);
        when(mMockContext.getResources()).thenReturn(
                InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());

        when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mSystemUser)).thenReturn(
                mMockContext);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mManagedUser)).thenReturn(
                mMockContext);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mPrivateUser)).thenReturn(
                mMockContext);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mOtherUser)).thenReturn(
                mMockContext);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mNormalUser)).thenReturn(
                mMockContext);
        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mPrimaryUser)).thenReturn(
                mMockContext);
    }

    @Test