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

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

Merge "Delay loadEscrowData from locksettings" am: 60edeec0

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I0ef3ce66e9771bc8864c84c91330c2947a74c673
parents 0072df0d 60edeec0
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -280,6 +280,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            super.onBootPhase(phase);
            if (phase == PHASE_ACTIVITY_MANAGER_READY) {
                mLockSettingsService.migrateOldDataAfterSystemReady();
                mLockSettingsService.loadEscrowData();
            }
        }

@@ -832,11 +833,15 @@ public class LockSettingsService extends ILockSettings.Stub {
        mSpManager.initWeaverService();
        getAuthSecretHal();
        mDeviceProvisionedObserver.onSystemReady();
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable();

        // TODO: maybe skip this for split system user mode.
        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
    }

    private void loadEscrowData() {
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler);
    }

    private void getAuthSecretHal() {
        try {
            mAuthSecretService = IAuthSecret.getService(/* retry */ true);
+68 −8
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -39,6 +40,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

import javax.crypto.SecretKey;

@@ -75,6 +77,13 @@ class RebootEscrowManager {
     */
    private static final int BOOT_COUNT_TOLERANCE = 5;

    /**
     * The default retry specs for loading reboot escrow data. We will attempt to retry loading
     * escrow data on temporarily errors, e.g. unavailable network.
     */
    private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3;
    private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30;

    /**
     * Logs events for later debugging in bugreports.
     */
@@ -148,6 +157,14 @@ class RebootEscrowManager {
            return null;
        }

        void post(Handler handler, Runnable runnable) {
            handler.post(runnable);
        }

        void postDelayed(Handler handler, Runnable runnable, long delayMillis) {
            handler.postDelayed(runnable, delayMillis);
        }

        public Context getContext() {
            return mContext;
        }
@@ -199,7 +216,18 @@ class RebootEscrowManager {
        mKeyStoreManager = injector.getKeyStoreManager();
    }

    void loadRebootEscrowDataIfAvailable() {
    private void onGetRebootEscrowKeyFailed(List<UserInfo> users) {
        Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
        for (UserInfo user : users) {
            mStorage.removeRebootEscrow(user.id);
        }

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

    void loadRebootEscrowDataIfAvailable(Handler retryHandler) {
        List<UserInfo> users = mUserManager.getUsers();
        List<UserInfo> rebootEscrowUsers = new ArrayList<>();
        for (UserInfo user : users) {
@@ -212,17 +240,49 @@ class RebootEscrowManager {
            return;
        }

        mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry(
                retryHandler, 0, users, rebootEscrowUsers));
    }

    void scheduleLoadRebootEscrowDataOrFail(Handler retryHandler, int attemptNumber,
            List<UserInfo> users, List<UserInfo> rebootEscrowUsers) {
        Objects.requireNonNull(retryHandler);

        final int retryLimit = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA,
                "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT);
        final int retryIntervalInSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA,
                "load_escrow_data_retry_interval_seconds",
                DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS);

        if (attemptNumber < retryLimit) {
            Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber);
            mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry(
                    retryHandler, attemptNumber, users, rebootEscrowUsers),
                    retryIntervalInSeconds * 1000);
            return;
        }

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

    void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber,
            List<UserInfo> users, List<UserInfo> rebootEscrowUsers) {
        // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is
        // generated before reboot. Note that we will clear the escrow key even if the keystore key
        // is null.
        SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey();
        RebootEscrowKey escrowKey = getAndClearRebootEscrowKey(kk);
        if (kk == null || 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);
        RebootEscrowKey escrowKey;
        try {
            escrowKey = getAndClearRebootEscrowKey(kk);
        } catch (IOException e) {
            scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users,
                    rebootEscrowUsers);
            return;
        }
            onEscrowRestoreComplete(false);

        if (kk == null || escrowKey == null) {
            onGetRebootEscrowKeyFailed(users);
            return;
        }

@@ -249,7 +309,7 @@ class RebootEscrowManager {
        }
    }

    private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) {
    private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException {
        RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
        if (rebootEscrowProvider == null) {
            Slog.w(TAG,
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import javax.crypto.SecretKey;
 * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL.
 */
class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface {
    private static final String TAG = "RebootEscrowProvider";
    private static final String TAG = "RebootEscrowProviderHal";

    private final Injector mInjector;

+5 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.locksettings;

import java.io.IOException;

import javax.crypto.SecretKey;

/**
@@ -33,9 +35,10 @@ public interface RebootEscrowProviderInterface {

    /**
     * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted,
     * use the input key to decrypt the RebootEscrowKey. Returns null on failure.
     * use the input key to decrypt the RebootEscrowKey. Returns null on failure. Throws an
     * IOException if the failure is non-fatal, and a retry may succeed.
     */
    RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey);
    RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException;

    /**
     * Clears the stored RebootEscrowKey.
+11 −6
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import javax.crypto.SecretKey;
 * encrypt & decrypt the blob.
 */
class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterface {
    private static final String TAG = "RebootEscrowProvider";
    private static final String TAG = "RebootEscrowProviderServerBased";

    // Timeout for service binding
    private static final long DEFAULT_SERVICE_TIMEOUT_IN_SECONDS = 10;
@@ -50,6 +50,8 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa

    private final Injector mInjector;

    private byte[] mServerBlob;

    static class Injector {
        private ResumeOnRebootServiceConnection mServiceConnection = null;

@@ -124,17 +126,20 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa
    }

    @Override
    public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) {
        byte[] serverBlob = mStorage.readRebootEscrowServerBlob();
    public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException {
        if (mServerBlob == null) {
            mServerBlob = mStorage.readRebootEscrowServerBlob();
        }
        // Delete the server blob in storage.
        mStorage.removeRebootEscrowServerBlob();
        if (serverBlob == null) {
        if (mServerBlob == null) {
            Slog.w(TAG, "Failed to read reboot escrow server blob from storage");
            return null;
        }

        Slog.i(TAG, "Loaded reboot escrow server blob from storage");
        try {
            byte[] escrowKeyBytes = unwrapServerBlob(serverBlob, decryptionKey);
            byte[] escrowKeyBytes = unwrapServerBlob(mServerBlob, decryptionKey);
            if (escrowKeyBytes == null) {
                Slog.w(TAG, "Decrypted reboot escrow key bytes should not be null");
                return null;
@@ -145,7 +150,7 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa
            }

            return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
        } catch (TimeoutException | RemoteException | IOException e) {
        } catch (TimeoutException | RemoteException e) {
            Slog.w(TAG, "Failed to decrypt the server blob ", e);
            return null;
        }
Loading