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

Commit 4eacaaa3 authored by Kenny Root's avatar Kenny Root
Browse files

Add statsd atom for reboot escrow success

In order to report the success or failure of the RebootEscrow HAL, add an atom
which can indicate when it succeeded or failed.

Bug: 63928581
Test: Trigger OTA flow and watch reboot with "statsd_testdrive 238"
Change-Id: I065e5660d9fd1f2324058a94cc3d624fdf125a89
parent 10076e75
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -333,6 +333,7 @@ message Atom {
        MediaProviderSchemaChange media_provider_schema_change = 236 [(module) = "mediaprovider"];
        MediaProviderSchemaChange media_provider_schema_change = 236 [(module) = "mediaprovider"];
        MediaProviderIdleMaintenance media_provider_idle_maintenance =
        MediaProviderIdleMaintenance media_provider_idle_maintenance =
            237 [(module) = "mediaprovider"];
            237 [(module) = "mediaprovider"];
        RebootEscrowRecoveryReported reboot_escrow_recovery_reported = 238;
    }
    }


    // Pulled events will start at field 10000.
    // Pulled events will start at field 10000.
@@ -7337,6 +7338,17 @@ message UpdateEngineSuccessfulUpdateReported {
    optional int32 reboot_count = 7;
    optional int32 reboot_count = 7;
}
}


/**
 * Reported when the RebootEscrow HAL has attempted to recover the escrowed
 * key to indicate whether it was successful or not.
 *
 * Logged from:
 *   frameworks/base/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
 */
message RebootEscrowRecoveryReported {
    optional bool successful = 1;
}

/**
/**
 * Global display pipeline metrics reported by SurfaceFlinger.
 * Global display pipeline metrics reported by SurfaceFlinger.
 * Pulled from:
 * Pulled from:
+43 −16
Original line number Original line Diff line number Diff line
@@ -25,11 +25,13 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.UserManager;
import android.os.UserManager;
import android.util.Slog;
import android.util.Slog;
import android.util.StatsLog;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.RebootEscrowListener;
import com.android.internal.widget.RebootEscrowListener;


import java.io.IOException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -109,20 +111,50 @@ class RebootEscrowManager {
    }
    }


    void loadRebootEscrowDataIfAvailable() {
    void loadRebootEscrowDataIfAvailable() {
        List<UserInfo> users = mUserManager.getUsers();
        List<UserInfo> rebootEscrowUsers = new ArrayList<>();
        for (UserInfo user : users) {
            if (mCallbacks.isUserSecure(user.id) && mStorage.hasRebootEscrow(user.id)) {
                rebootEscrowUsers.add(user);
            }
        }

        if (rebootEscrowUsers.isEmpty()) {
            return;
        }

        SecretKeySpec escrowKey = getAndClearRebootEscrowKey();
        if (escrowKey == null) {
            Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
            for (UserInfo user : users) {
                mStorage.removeRebootEscrow(user.id);
            }
            StatsLog.write(StatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, false);
            return;
        }

        boolean allUsersUnlocked = true;
        for (UserInfo user : rebootEscrowUsers) {
            allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey);
        }
        StatsLog.write(StatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, allUsersUnlocked);
    }

    private SecretKeySpec getAndClearRebootEscrowKey() {
        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
        if (rebootEscrow == null) {
        if (rebootEscrow == null) {
            return;
            return null;
        }
        }


        final SecretKeySpec escrowKey;
        try {
        try {
            byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
            byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
            if (escrowKeyBytes == null) {
            if (escrowKeyBytes == null) {
                return;
                Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key");
                return null;
            } else if (escrowKeyBytes.length != 32) {
            } else if (escrowKeyBytes.length != 32) {
                Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
                Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
                        + escrowKeyBytes.length);
                        + escrowKeyBytes.length);
                return;
                return null;
            }
            }


            // Make sure we didn't get the null key.
            // Make sure we didn't get the null key.
@@ -132,29 +164,22 @@ class RebootEscrowManager {
            }
            }
            if (zero == 0) {
            if (zero == 0) {
                Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
                Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
                return;
                return null;
            }
            }


            // Overwrite the existing key with the null key
            // Overwrite the existing key with the null key
            rebootEscrow.storeKey(new byte[32]);
            rebootEscrow.storeKey(new byte[32]);


            escrowKey = RebootEscrowData.fromKeyBytes(escrowKeyBytes);
            return RebootEscrowData.fromKeyBytes(escrowKeyBytes);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Slog.w(TAG, "Could not retrieve escrow data");
            Slog.w(TAG, "Could not retrieve escrow data");
            return;
            return null;
        }

        List<UserInfo> users = mUserManager.getUsers();
        for (UserInfo user : users) {
            if (mCallbacks.isUserSecure(user.id)) {
                restoreRebootEscrowForUser(user.id, escrowKey);
            }
        }
        }
    }
    }


    private void restoreRebootEscrowForUser(@UserIdInt int userId, SecretKeySpec escrowKey) {
    private boolean restoreRebootEscrowForUser(@UserIdInt int userId, SecretKeySpec escrowKey) {
        if (!mStorage.hasRebootEscrow(userId)) {
        if (!mStorage.hasRebootEscrow(userId)) {
            return;
            return false;
        }
        }


        try {
        try {
@@ -165,9 +190,11 @@ class RebootEscrowManager {


            mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
            mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
                    escrowData.getSyntheticPassword(), userId);
                    escrowData.getSyntheticPassword(), userId);
            return true;
        } catch (IOException e) {
        } catch (IOException e) {
            Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
            Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
        }
        }
        return false;
    }
    }


    void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion,
    void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion,