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

Commit 3ec57ecc authored by Tianjie Xu's avatar Tianjie Xu Committed by Automerger Merge Worker
Browse files

Merge "Extend the metrics for resume on reboot" am: 1c5faf61 am: f593e712 am: 2184af92

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1556763

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I96ac197d6f09ff89f1a74471413e213f6649f126
parents f85ff9ee 2184af92
Loading
Loading
Loading
Loading
+42 −13
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ class RebootEscrowManager {
    @VisibleForTesting
    public static final String REBOOT_ESCROW_ARMED_KEY = "reboot_escrow_armed_count";

    static final String REBOOT_ESCROW_KEY_ARMED_TIMESTAMP = "reboot_escrow_key_stored_timestamp";

    /**
     * Number of boots until we consider the escrow data to be stale for the purposes of metrics.
     * <p>
@@ -144,8 +146,7 @@ class RebootEscrowManager {

        private RebootEscrowProviderInterface createRebootEscrowProvider() {
            RebootEscrowProviderInterface rebootEscrowProvider;
            if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
                    "server_based_ror_enabled", false)) {
            if (serverBasedResumeOnReboot()) {
                Slog.i(TAG, "Using server based resume on reboot");
                rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage);
            } else {
@@ -166,6 +167,11 @@ class RebootEscrowManager {
            handler.postDelayed(runnable, delayMillis);
        }

        public boolean serverBasedResumeOnReboot() {
            return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
                    "server_based_ror_enabled", false);
        }

        public Context getContext() {
            return mContext;
        }
@@ -204,10 +210,12 @@ class RebootEscrowManager {
                    DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS);
        }

        public void reportMetric(boolean success) {
            // TODO(b/179105110) design error code; and report the true value for other fields.
            FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, 0, 1, 1,
                    -1, 0, -1);
        public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount,
                int escrowDurationInSeconds, int vbmetaDigestStatus,
                int durationSinceBootCompleteInSeconds) {
            FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success,
                    errorCode, serviceType, attemptCount, escrowDurationInSeconds,
                    vbmetaDigestStatus, durationSinceBootCompleteInSeconds);
        }

        public RebootEscrowEventLog getEventLog() {
@@ -230,7 +238,7 @@ class RebootEscrowManager {
        mKeyStoreManager = injector.getKeyStoreManager();
    }

    private void onGetRebootEscrowKeyFailed(List<UserInfo> users) {
    private void onGetRebootEscrowKeyFailed(List<UserInfo> users, int attemptCount) {
        Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
        for (UserInfo user : users) {
            mStorage.removeRebootEscrow(user.id);
@@ -238,7 +246,7 @@ class RebootEscrowManager {

        // Clear the old key in keystore.
        mKeyStoreManager.clearKeyStoreEncryptionKey();
        onEscrowRestoreComplete(false);
        onEscrowRestoreComplete(false, attemptCount);
    }

    void loadRebootEscrowDataIfAvailable(Handler retryHandler) {
@@ -276,7 +284,7 @@ class RebootEscrowManager {
        }

        Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts");
        onGetRebootEscrowKeyFailed(users);
        onGetRebootEscrowKeyFailed(users, attemptNumber);
    }

    void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber,
@@ -299,7 +307,7 @@ class RebootEscrowManager {
        }

        if (escrowKey == null) {
            onGetRebootEscrowKeyFailed(users);
            onGetRebootEscrowKeyFailed(users, attemptNumber + 1);
            return;
        }

@@ -313,16 +321,35 @@ class RebootEscrowManager {
        // Clear the old key in keystore. A new key will be generated by new RoR requests.
        mKeyStoreManager.clearKeyStoreEncryptionKey();

        onEscrowRestoreComplete(allUsersUnlocked);
        onEscrowRestoreComplete(allUsersUnlocked, attemptNumber + 1);
    }

    private void reportMetricOnRestoreComplete(boolean success, int attemptCount) {
        int serviceType = mInjector.serverBasedResumeOnReboot()
                ? FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__SERVER_BASED
                : FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__HAL;

        long armedTimestamp = mStorage.getLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, -1,
                USER_SYSTEM);
        mStorage.removeKey(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, USER_SYSTEM);
        int escrowDurationInSeconds = armedTimestamp != -1
                ? (int) (System.currentTimeMillis() - armedTimestamp) / 1000 : -1;

        // TODO(b/179105110) design error code; and report the true value for other fields.
        int vbmetaDigestStatus = FrameworkStatsLog
                .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT;

        mInjector.reportMetric(success, 0 /* error code */, serviceType, attemptCount,
                escrowDurationInSeconds, vbmetaDigestStatus, -1);
    }

    private void onEscrowRestoreComplete(boolean success) {
    private void onEscrowRestoreComplete(boolean success, int attemptCount) {
        int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM);
        mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM);

        int bootCountDelta = mInjector.getBootCount() - previousBootCount;
        if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) {
            mInjector.reportMetric(success);
            reportMetricOnRestoreComplete(success, attemptCount);
        }
    }

@@ -478,6 +505,8 @@ class RebootEscrowManager {
        boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk);
        if (armedRebootEscrow) {
            mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
            mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, System.currentTimeMillis(),
                    USER_SYSTEM);
            mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
        }

+33 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -109,7 +110,8 @@ public class RebootEscrowManagerTests {
    public interface MockableRebootEscrowInjected {
        int getBootCount();

        void reportMetric(boolean success);
        void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount,
                int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootComplete);
    }

    static class MockInjector extends RebootEscrowManager.Injector {
@@ -119,6 +121,7 @@ public class RebootEscrowManagerTests {
        private final UserManager mUserManager;
        private final MockableRebootEscrowInjected mInjected;
        private final RebootEscrowKeyStoreManager mKeyStoreManager;
        private final boolean mServerBased;

        MockInjector(Context context, UserManager userManager,
                IRebootEscrow rebootEscrow,
@@ -128,6 +131,7 @@ public class RebootEscrowManagerTests {
            super(context, storage);
            mRebootEscrow = rebootEscrow;
            mServiceConnection = null;
            mServerBased = false;
            RebootEscrowProviderHalImpl.Injector halInjector =
                    new RebootEscrowProviderHalImpl.Injector() {
                        @Override
@@ -149,6 +153,7 @@ public class RebootEscrowManagerTests {
            super(context, storage);
            mServiceConnection = serviceConnection;
            mRebootEscrow = null;
            mServerBased = true;
            RebootEscrowProviderServerBasedImpl.Injector injector =
                    new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection);
            mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(storage, injector);
@@ -167,6 +172,11 @@ public class RebootEscrowManagerTests {
            return mUserManager;
        }

        @Override
        public boolean serverBasedResumeOnReboot() {
            return mServerBased;
        }

        @Override
        public RebootEscrowProviderInterface getRebootEscrowProvider() {
            return mRebootEscrowProvider;
@@ -195,8 +205,11 @@ public class RebootEscrowManagerTests {
        }

        @Override
        public void reportMetric(boolean success) {
            mInjected.reportMetric(success);
        public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount,
                int escrowDurationInSeconds, int vbmetaDigestStatus,
                int durationSinceBootComplete) {
            mInjected.reportMetric(success, errorCode, serviceType, attemptCount,
                    escrowDurationInSeconds, vbmetaDigestStatus, durationSinceBootComplete);
        }
    }

@@ -418,7 +431,9 @@ public class RebootEscrowManagerTests {

        when(mInjected.getBootCount()).thenReturn(1);
        ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class);
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture());
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(),
                eq(0) /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */,
                anyInt(), anyInt(), anyInt());
        when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue());

        mService.loadRebootEscrowDataIfAvailable(null);
@@ -451,7 +466,9 @@ public class RebootEscrowManagerTests {
        // pretend reboot happens here
        when(mInjected.getBootCount()).thenReturn(1);
        ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class);
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture());
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(),
                eq(0) /* error code */, eq(2) /* Server based */, eq(1) /* attempt count */,
                anyInt(), anyInt(), anyInt());

        when(mServiceConnection.unwrap(any(), anyLong()))
                .thenAnswer(invocation -> invocation.getArgument(0));
@@ -485,7 +502,8 @@ public class RebootEscrowManagerTests {
        // pretend reboot happens here
        when(mInjected.getBootCount()).thenReturn(1);
        ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class);
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture());
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(),
                anyInt(), anyInt(), eq(2) /* attempt count */, anyInt(), anyInt(), anyInt());

        when(mServiceConnection.unwrap(any(), anyLong()))
                .thenThrow(new IOException())
@@ -528,7 +546,8 @@ public class RebootEscrowManagerTests {

        mService.loadRebootEscrowDataIfAvailable(null);
        verify(mRebootEscrow).retrieveKey();
        verify(mInjected, never()).reportMetric(anyBoolean());
        verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(),
                anyInt(), anyInt(), anyInt());
    }

    @Test
@@ -554,7 +573,8 @@ public class RebootEscrowManagerTests {
        when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]);

        mService.loadRebootEscrowDataIfAvailable(null);
        verify(mInjected, never()).reportMetric(anyBoolean());
        verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(),
                anyInt(), anyInt(), anyInt());
    }

    @Test
@@ -588,7 +608,8 @@ public class RebootEscrowManagerTests {
        when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue());

        mService.loadRebootEscrowDataIfAvailable(null);
        verify(mInjected).reportMetric(eq(true));
        verify(mInjected).reportMetric(eq(true), eq(0) /* error code */, eq(1) /* HAL based */,
                eq(1) /* attempt count */, anyInt(), anyInt(), anyInt());
    }

    @Test
@@ -615,7 +636,9 @@ public class RebootEscrowManagerTests {

        when(mInjected.getBootCount()).thenReturn(1);
        ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class);
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture());
        doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(),
                anyInt() /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */,
                anyInt(), anyInt(), anyInt());
        when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> new byte[32]);
        mService.loadRebootEscrowDataIfAvailable(null);
        verify(mRebootEscrow).retrieveKey();