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

Commit bc215de9 authored by Felipe Leme's avatar Felipe Leme
Browse files

Make AccountManagerService more resilient to database corruption.

Currently, if a user accounts database is corrupted, the system will crash and
boot loop.

This CL mitigates the issue by removing the user instead.

Bug: 145710595
Test: adb shell chmod 000 /data/system_de/10/accounts_de.db && adb reboot

Change-Id: I47916fde4577709a2555586b8dc94090605595bd
(cherry picked from commit 8472b904ecef69ee12818fa1f69458875a58c8df)
parent 297a8423
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -1289,6 +1289,33 @@ public class AccountManagerService
    }

    protected UserAccounts getUserAccounts(int userId) {
        try {
            return getUserAccountsNotChecked(userId);
        } catch (RuntimeException e) {
            if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
                // Let it go...
                throw e;
            }
            // User accounts database is corrupted, we must wipe out the whole user, otherwise the
            // system will crash indefinitely
            Slog.wtf(TAG, "Removing user " + userId + " due to exception (" + e + ") reading its "
                    + "account database");
            if (userId == ActivityManager.getCurrentUser() && userId != UserHandle.USER_SYSTEM) {
                Slog.i(TAG, "Switching to system user first");
                try {
                    ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
                } catch (RemoteException re) {
                    Slog.e(TAG, "Could not switch to " + UserHandle.USER_SYSTEM + ": " + re);
                }
            }
            if (!getUserManager().removeUserEvenWhenDisallowed(userId)) {
                Slog.e(TAG, "could not remove user " + userId);
            }
            throw e;
        }
    }

    private UserAccounts getUserAccountsNotChecked(int userId) {
        synchronized (mUsers) {
            UserAccounts accounts = mUsers.get(userId);
            boolean validateAccounts = false;