diff options
| -rw-r--r-- | services/core/java/com/android/server/locksettings/LockSettingsService.java | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/locksettings/RebootEscrowManager.java | 144 |
2 files changed, 150 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 1b4ec8a8fa32..01af83914800 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -3193,6 +3193,12 @@ public class LockSettingsService extends ILockSettings.Stub { mStrongAuth.dump(pw); pw.println(); pw.decreaseIndent(); + + pw.println("RebootEscrow:"); + pw.increaseIndent(); + mRebootEscrowManager.dump(pw); + pw.println(); + pw.decreaseIndent(); } /** diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index dabf88670639..8d4efed8604b 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -18,6 +18,7 @@ package com.android.server.locksettings; import static android.os.UserHandle.USER_SYSTEM; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; @@ -25,6 +26,7 @@ import android.content.pm.UserInfo; import android.hardware.rebootescrow.IRebootEscrow; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.UserManager; import android.provider.Settings; import android.util.Slog; @@ -32,11 +34,15 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.util.IndentingPrintWriter; import com.android.internal.widget.RebootEscrowListener; import java.io.IOException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; class RebootEscrowManager { @@ -63,6 +69,11 @@ class RebootEscrowManager { private static final int BOOT_COUNT_TOLERANCE = 5; /** + * Logs events for later debugging in bugreports. + */ + private final RebootEscrowEventLog mEventLog; + + /** * Used to track when the reboot escrow is wanted. Should stay true once escrow is requested * unless clearRebootEscrow is called. This will allow all the active users to be unlocked * after reboot. @@ -135,6 +146,10 @@ class RebootEscrowManager { public void reportMetric(boolean success) { FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success); } + + public RebootEscrowEventLog getEventLog() { + return new RebootEscrowEventLog(); + } } RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) { @@ -148,6 +163,7 @@ class RebootEscrowManager { mCallbacks = callbacks; mStorage = storage; mUserManager = injector.getUserManager(); + mEventLog = injector.getEventLog(); } void loadRebootEscrowDataIfAvailable() { @@ -173,6 +189,8 @@ class RebootEscrowManager { return; } + mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA); + boolean allUsersUnlocked = true; for (UserInfo user : rebootEscrowUsers) { allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey); @@ -221,6 +239,7 @@ class RebootEscrowManager { // Overwrite the existing key with the null key rebootEscrow.storeKey(new byte[32]); + mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK); return RebootEscrowKey.fromKeyBytes(escrowKeyBytes); } catch (RemoteException e) { Slog.w(TAG, "Could not retrieve escrow data"); @@ -242,6 +261,7 @@ class RebootEscrowManager { mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(), escrowData.getSyntheticPassword(), userId); Slog.i(TAG, "Restored reboot escrow data for user " + userId); + mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId); return true; } catch (IOException e) { Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); @@ -278,6 +298,7 @@ class RebootEscrowManager { } mStorage.writeRebootEscrow(userId, escrowData.getBlob()); + mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId); setRebootEscrowReady(true); } @@ -322,6 +343,8 @@ class RebootEscrowManager { for (UserInfo user : users) { mStorage.removeRebootEscrow(user.id); } + + mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); } boolean armRebootEscrowIfNeeded() { @@ -356,6 +379,7 @@ class RebootEscrowManager { if (armedRebootEscrow) { mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); + mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); } return armedRebootEscrow; @@ -375,6 +399,7 @@ class RebootEscrowManager { clearRebootEscrowIfNeeded(); mRebootEscrowWanted = true; + mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF); return true; } @@ -390,4 +415,123 @@ class RebootEscrowManager { void setRebootEscrowListener(RebootEscrowListener listener) { mRebootEscrowListener = listener; } + + @VisibleForTesting + public static class RebootEscrowEvent { + static final int FOUND_ESCROW_DATA = 1; + static final int SET_ARMED_STATUS = 2; + static final int CLEARED_LSKF_REQUEST = 3; + static final int RETRIEVED_STORED_KEK = 4; + static final int REQUESTED_LSKF = 5; + static final int STORED_LSKF_FOR_USER = 6; + static final int RETRIEVED_LSKF_FOR_USER = 7; + + final int mEventId; + final Integer mUserId; + final long mWallTime; + final long mTimestamp; + + RebootEscrowEvent(int eventId) { + this(eventId, null); + } + + RebootEscrowEvent(int eventId, Integer userId) { + mEventId = eventId; + mUserId = userId; + mTimestamp = SystemClock.uptimeMillis(); + mWallTime = System.currentTimeMillis(); + } + + String getEventDescription() { + switch (mEventId) { + case FOUND_ESCROW_DATA: + return "Found escrow data"; + case SET_ARMED_STATUS: + return "Set armed status"; + case CLEARED_LSKF_REQUEST: + return "Cleared request for LSKF"; + case RETRIEVED_STORED_KEK: + return "Retrieved stored KEK"; + case REQUESTED_LSKF: + return "Requested LSKF"; + case STORED_LSKF_FOR_USER: + return "Stored LSKF for user"; + case RETRIEVED_LSKF_FOR_USER: + return "Retrieved LSKF for user"; + default: + return "Unknown event ID " + mEventId; + } + } + } + + @VisibleForTesting + public static class RebootEscrowEventLog { + private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16]; + private int mNextIndex = 0; + + void addEntry(int eventId) { + addEntryInternal(new RebootEscrowEvent(eventId)); + } + + void addEntry(int eventId, int userId) { + addEntryInternal(new RebootEscrowEvent(eventId, userId)); + } + + private void addEntryInternal(RebootEscrowEvent event) { + final int index = mNextIndex; + mEntries[index] = event; + mNextIndex = (mNextIndex + 1) % mEntries.length; + } + + void dump(@NonNull IndentingPrintWriter pw) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); + + for (int i = 0; i < mEntries.length; ++i) { + RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length]; + if (event == null) { + continue; + } + + pw.print("Event #"); + pw.println(i); + + pw.println(" time=" + sdf.format(new Date(event.mWallTime)) + + " (timestamp=" + event.mTimestamp + ")"); + + pw.print(" event="); + pw.println(event.getEventDescription()); + + if (event.mUserId != null) { + pw.print(" user="); + pw.println(event.mUserId); + } + } + } + } + + void dump(@NonNull IndentingPrintWriter pw) { + pw.print("mRebootEscrowWanted="); + pw.println(mRebootEscrowWanted); + + pw.print("mRebootEscrowReady="); + pw.println(mRebootEscrowReady); + + pw.print("mRebootEscrowListener="); + pw.println(mRebootEscrowListener); + + boolean keySet; + synchronized (mKeyGenerationLock) { + keySet = mPendingRebootEscrowKey != null; + } + + pw.print("mPendingRebootEscrowKey is "); + pw.println(keySet ? "set" : "not set"); + + pw.println(); + pw.println("Event log:"); + pw.increaseIndent(); + mEventLog.dump(pw); + pw.println(); + pw.decreaseIndent(); + } } |