Merge changes I0877f915,If6889737 into rvc-dev
* changes: RebootEscrow: create event log RebootEscrow: add bugreport dump
This commit is contained in:
committed by
Android (Google) Code Review
commit
e1741183b9
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
@@ -62,6 +68,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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user