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

Commit 65423958 authored by Anna Bauza's avatar Anna Bauza
Browse files

Fix high volume of binder calls in ContentProvider.

ContentProvider.getUserIdFromAuthority can return USER_NULL when it can't parse auth as int, which can cause high volume of binder calls. This CL fixes this issue by avoiding calling into system server for invalid user ids.

This CL also fixes a bug in UserManager.getUserProperties where it can throw an exception when the user id is not supported. This CL fixes this issue by throwing an IllegalArgumentException instead.

This CL is a part of the effort to reduce the number of binder calls in the system server.

Bug: 350416200
Change-Id: Ied72302db0c141fe9ff398009331ce44a0fad2e7
Test: atest com.android.server.pm.UserManagerTest
Flag: android.multiuser.cache_user_serial_number
parent 38d30647
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2774,6 +2774,10 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
                        + " provider from user:" + mContext.getUserId());
            }
            if (userId != UserHandle.USER_CURRENT
                    // getUserIdFromAuthority can return USER_NULL when can't cast the userId to
                    // an int, which can cause high volume of binder calls.
                    && (!android.multiuser.Flags.fixGetUserPropertyCache()
                        || userId != UserHandle.USER_NULL)
                    && userId != mContext.getUserId()
                    // Since userId specified in content uri, the provider userId would be
                    // determined from it.
+6 −1
Original line number Diff line number Diff line
@@ -3927,7 +3927,12 @@ public class UserManager {
            android.Manifest.permission.QUERY_USERS,
            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
    public @NonNull UserProperties getUserProperties(@NonNull UserHandle userHandle) {
        return mUserPropertiesCache.query(userHandle.getIdentifier());
        final int userId = userHandle.getIdentifier();
        // Avoid calling into system server for invalid user ids.
        if (android.multiuser.Flags.fixGetUserPropertyCache() && userId < 0) {
            throw new IllegalArgumentException("Cannot access properties for user " + userId);
        }
        return mUserPropertiesCache.query(userId);
    }

    /**
+17 −0
Original line number Diff line number Diff line
@@ -1060,6 +1060,23 @@ public final class UserManagerTest {
        assertThrows(SecurityException.class, userProps::getAlwaysVisible);
    }

    /**
     * Test that UserManager.getUserProperties throws the IllegalArgumentException for unsupported
     * arguments such as UserHandle.NULL, UserHandle.CURRENT or UserHandle.ALL.
     **/
    @MediumTest
    @Test
    public void testThrowUserPropertiesForUnsupportedUserHandles() throws Exception {
        assertThrows(IllegalArgumentException.class, () ->
            mUserManager.getUserProperties(UserHandle.of(UserHandle.USER_NULL)));
        assertThrows(IllegalArgumentException.class, () ->
            mUserManager.getUserProperties(UserHandle.CURRENT));
        assertThrows(IllegalArgumentException.class, () ->
            mUserManager.getUserProperties(UserHandle.CURRENT_OR_SELF));
        assertThrows(IllegalArgumentException.class, () ->
            mUserManager.getUserProperties(UserHandle.ALL));
    }

    // Make sure only max managed profiles can be created
    @MediumTest
    @Test