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

Commit 65b79f0b authored by Satoshi Niwa's avatar Satoshi Niwa
Browse files

Refactor BackupEligibilityRules to use UserManagerInternal

Replace the usage of the public UserManager API with UserManagerInternal within BackupEligibilityRules.

Calling UserManager.getMainUser() from the backup service context results in a SecurityException as it lacks the necessary QUERY_USERS permission.
This change resolves the crash by switching to the internal service, which bypasses permission checks for calls from within the system server.

This aligns with the standard practice for core system services interacting with user management and prevents permission-denial crashes.

Test: atest BackupEligibilityRulesTest
Test: com.google.android.gts.backup.BackupManagerTest
Bug: 421975240
Flag: EXEMPT bug fix
Change-Id: I43666d83dd0093d329892c52f38670dd47a35934
parent 1b827075
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -45,10 +45,12 @@ import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.SetUtils;
import com.android.server.backup.transport.BackupTransportClient;
import com.android.server.backup.transport.TransportConnection;
import com.android.server.pm.UserManagerInternal;

import com.google.android.collect.Sets;

@@ -86,7 +88,7 @@ public class BackupEligibilityRules {

    private final PackageManager mPackageManager;
    private final PackageManagerInternal mPackageManagerInternal;
    private final UserManager mUserManager;
    private final UserManagerInternal mUserManagerInternal;
    private final int mUserId;
    @BackupDestination  private final int mBackupDestination;
    private final boolean mSkipRestoreForLaunchedApps;
@@ -136,7 +138,7 @@ public class BackupEligibilityRules {
        mPackageManagerInternal = packageManagerInternal;
        mUserId = userId;
        mBackupDestination = backupDestination;
        mUserManager = context.getSystemService(UserManager.class);
        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
        mSkipRestoreForLaunchedApps = skipRestoreForLaunchedApps;
    }

@@ -204,14 +206,14 @@ public class BackupEligibilityRules {
            return true;
        }

        if (mUserManager.isProfile()) {
        if (mUserManagerInternal.getUserInfo(mUserId).isProfile()) {
            return systemPackagesAllowedForProfileUser.contains(packageName);
        }

        // In Headless System User Mode, certain packages are only backed up for the main user.
        if (UserManager.isHeadlessSystemUserMode()) {
            UserHandle mainUser = mUserManager.getMainUser();
            if (mainUser != null && mainUser.getIdentifier() == mUserId) {
            int mainUserId = mUserManagerInternal.getMainUserId();
            if (mainUserId != UserHandle.USER_NULL && mainUserId == mUserId) {
                return systemPackagesAllowedForHsumMainUser.contains(packageName);
            }
        }
+16 −7
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.SigningInfo;
import android.content.pm.UserInfo;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -45,7 +46,9 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.pm.UserManagerInternal;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -82,7 +85,8 @@ public class BackupEligibilityRulesTest {
    @Mock private PackageManagerInternal mMockPackageManagerInternal;
    @Mock private PackageManager mPackageManager;
    @Mock private Context mContext;
    @Mock private UserManager mUserManager;
    @Mock private UserManagerInternal mUserManagerInternal;
    @Mock private UserInfo mUserInfo;

    private BackupEligibilityRules mBackupEligibilityRules;
    private int mUserId;
@@ -91,6 +95,9 @@ public class BackupEligibilityRulesTest {
    public void setUp() throws Exception {
        mUserId = UserHandle.USER_SYSTEM;
        mockHeadlessSystemUserMode(false);
        LocalServices.removeServiceForTest(UserManagerInternal.class);
        LocalServices.addService(UserManagerInternal.class, mUserManagerInternal);
        when(mUserManagerInternal.getUserInfo(mUserId)).thenReturn(mUserInfo);
        mockContextForFullUser();
        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
    }
@@ -140,8 +147,9 @@ public class BackupEligibilityRulesTest {
        mockHeadlessSystemUserMode(true);

        // Current user is the main user.
        when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER);
        when(mUserManagerInternal.getMainUserId()).thenReturn(NON_SYSTEM_USER_ID);
        mUserId = NON_SYSTEM_USER_ID;
        when(mUserManagerInternal.getUserInfo(mUserId)).thenReturn(mUserInfo);

        mockContextForFullUser();
        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
@@ -162,8 +170,9 @@ public class BackupEligibilityRulesTest {
        mockHeadlessSystemUserMode(true);

        // Current user is a non-main user.
        when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER);
        when(mUserManagerInternal.getMainUserId()).thenReturn(NON_SYSTEM_USER_ID);
        mUserId = NON_SYSTEM_USER_ID + 1;
        when(mUserManagerInternal.getUserInfo(mUserId)).thenReturn(mUserInfo);

        mockContextForFullUser();
        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
@@ -950,23 +959,23 @@ public class BackupEligibilityRulesTest {

    private void setUpForNonSystemUser() {
        mUserId = NON_SYSTEM_USER_ID;
        when(mUserManagerInternal.getUserInfo(mUserId)).thenReturn(mUserInfo);
        mockContextForFullUser();
        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
    }

    private void setUpForProfileUser() {
        mUserId = NON_SYSTEM_USER_ID;
        when(mUserManagerInternal.getUserInfo(mUserId)).thenReturn(mUserInfo);
        mockContextForProfile();
        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
    }

    private void mockContextForProfile() {
        when(mUserManager.isProfile()).thenReturn(true);
        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
        when(mUserInfo.isProfile()).thenReturn(true);
    }

    private void mockContextForFullUser() {
        when(mUserManager.isProfile()).thenReturn(false);
        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
        when(mUserInfo.isProfile()).thenReturn(false);
    }
}