1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.locksettings; 18 19 import static android.os.UserHandle.USER_SYSTEM; 20 21 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY; 22 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE; 23 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; 24 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY; 25 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER; 26 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH; 27 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_STORE_ESCROW_KEY; 28 import static com.android.internal.widget.LockSettingsInternal.ArmRebootEscrowErrorCode; 29 30 import android.annotation.IntDef; 31 import android.annotation.NonNull; 32 import android.annotation.UserIdInt; 33 import android.content.Context; 34 import android.content.pm.PackageManager; 35 import android.content.pm.UserInfo; 36 import android.net.ConnectivityManager; 37 import android.net.Network; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkRequest; 40 import android.os.Handler; 41 import android.os.PowerManager; 42 import android.os.SystemClock; 43 import android.os.SystemProperties; 44 import android.os.UserManager; 45 import android.provider.DeviceConfig; 46 import android.provider.Settings; 47 import android.util.Slog; 48 49 import com.android.internal.annotations.GuardedBy; 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.util.FrameworkStatsLog; 52 import com.android.internal.util.IndentingPrintWriter; 53 import com.android.internal.widget.RebootEscrowListener; 54 import com.android.server.pm.UserManagerInternal; 55 56 import java.io.IOException; 57 import java.lang.annotation.Retention; 58 import java.lang.annotation.RetentionPolicy; 59 import java.text.SimpleDateFormat; 60 import java.util.ArrayList; 61 import java.util.Collections; 62 import java.util.Date; 63 import java.util.HashSet; 64 import java.util.List; 65 import java.util.Locale; 66 import java.util.Objects; 67 import java.util.Set; 68 69 import javax.crypto.SecretKey; 70 71 /** 72 * This class aims to persists the synthetic password(SP) across reboot in a secure way. In 73 * particular, it manages the encryption of the sp before reboot, and decryption of the sp after 74 * reboot. Here are the meaning of some terms. 75 * SP: synthetic password 76 * K_s: The RebootEscrowKey, i.e. AES-GCM key stored in memory 77 * K_k: AES-GCM key in android keystore 78 * RebootEscrowData: The synthetic password and its encrypted blob. We encrypt SP with K_s first, 79 * then with K_k, i.e. E(K_k, E(K_s, SP)) 80 */ 81 class RebootEscrowManager { 82 private static final String TAG = "RebootEscrowManager"; 83 84 /** 85 * Used in the database storage to indicate the boot count at which the reboot escrow was 86 * previously armed. 87 */ 88 @VisibleForTesting 89 public static final String REBOOT_ESCROW_ARMED_KEY = "reboot_escrow_armed_count"; 90 91 static final String REBOOT_ESCROW_KEY_ARMED_TIMESTAMP = "reboot_escrow_key_stored_timestamp"; 92 static final String REBOOT_ESCROW_KEY_PROVIDER = "reboot_escrow_key_provider"; 93 94 /** 95 * The verified boot 2.0 vbmeta digest of the current slot, the property value is always 96 * available after boot. 97 */ 98 static final String VBMETA_DIGEST_PROP_NAME = "ro.boot.vbmeta.digest"; 99 /** 100 * The system prop contains vbmeta digest of the inactive slot. The build property is set after 101 * an OTA update. RebootEscrowManager will store it in disk before the OTA reboot, so the value 102 * is available for vbmeta digest verification after the device reboots. 103 */ 104 static final String OTHER_VBMETA_DIGEST_PROP_NAME = "ota.other.vbmeta_digest"; 105 static final String REBOOT_ESCROW_KEY_VBMETA_DIGEST = "reboot_escrow_key_vbmeta_digest"; 106 static final String REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST = 107 "reboot_escrow_key_other_vbmeta_digest"; 108 109 /** 110 * Number of boots until we consider the escrow data to be stale for the purposes of metrics. 111 * 112 * <p>If the delta between the current boot number and the boot number stored when the mechanism 113 * was armed is under this number and the escrow mechanism fails, we report it as a failure of 114 * the mechanism. 115 * 116 * <p>If the delta over this number and escrow fails, we will not report the metric as failed 117 * since there most likely was some other issue if the device rebooted several times before 118 * getting to the escrow restore code. 119 */ 120 private static final int BOOT_COUNT_TOLERANCE = 5; 121 122 /** 123 * The default retry specs for loading reboot escrow data. We will attempt to retry loading 124 * escrow data on temporarily errors, e.g. unavailable network. 125 */ 126 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3; 127 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30; 128 129 // 3 minutes. It's enough for the default 3 retries with 30 seconds interval 130 private static final int DEFAULT_LOAD_ESCROW_BASE_TIMEOUT_MILLIS = 180_000; 131 // 5 seconds. An extension of the overall RoR timeout to account for overhead. 132 private static final int DEFAULT_LOAD_ESCROW_TIMEOUT_EXTENSION_MILLIS = 5000; 133 134 @IntDef(prefix = {"ERROR_"}, value = { 135 ERROR_NONE, 136 ERROR_UNKNOWN, 137 ERROR_NO_PROVIDER, 138 ERROR_LOAD_ESCROW_KEY, 139 ERROR_RETRY_COUNT_EXHAUSTED, 140 ERROR_UNLOCK_ALL_USERS, 141 ERROR_PROVIDER_MISMATCH, 142 ERROR_KEYSTORE_FAILURE, 143 ERROR_NO_NETWORK, 144 ERROR_TIMEOUT_EXHAUSTED, 145 ERROR_NO_REBOOT_ESCROW_DATA, 146 }) 147 @Retention(RetentionPolicy.SOURCE) 148 @interface RebootEscrowErrorCode { 149 } 150 151 static final int ERROR_NONE = 0; 152 static final int ERROR_UNKNOWN = 1; 153 static final int ERROR_NO_PROVIDER = 2; 154 static final int ERROR_LOAD_ESCROW_KEY = 3; 155 static final int ERROR_RETRY_COUNT_EXHAUSTED = 4; 156 static final int ERROR_UNLOCK_ALL_USERS = 5; 157 static final int ERROR_PROVIDER_MISMATCH = 6; 158 static final int ERROR_KEYSTORE_FAILURE = 7; 159 static final int ERROR_NO_NETWORK = 8; 160 static final int ERROR_TIMEOUT_EXHAUSTED = 9; 161 static final int ERROR_NO_REBOOT_ESCROW_DATA = 10; 162 163 private @RebootEscrowErrorCode int mLoadEscrowDataErrorCode = ERROR_NONE; 164 165 /** 166 * Logs events for later debugging in bugreports. 167 */ 168 private final RebootEscrowEventLog mEventLog; 169 170 /** 171 * Used to track when the reboot escrow is wanted. Should stay true once escrow is requested 172 * unless clearRebootEscrow is called. This will allow all the active users to be unlocked 173 * after reboot. 174 */ 175 private boolean mRebootEscrowWanted; 176 177 /** Used to track when reboot escrow is ready. */ 178 private boolean mRebootEscrowReady; 179 180 /** Notified when mRebootEscrowReady changes. */ 181 private RebootEscrowListener mRebootEscrowListener; 182 183 /** Set when unlocking reboot escrow times out. */ 184 private boolean mRebootEscrowTimedOut = false; 185 186 /** 187 * Set when {@link #loadRebootEscrowDataWithRetry} is called to ensure the function is only 188 * called once. 189 */ 190 private boolean mLoadEscrowDataWithRetry = false; 191 192 /** 193 * Hold this lock when checking or generating the reboot escrow key. 194 */ 195 private final Object mKeyGenerationLock = new Object(); 196 197 /** 198 * Stores the reboot escrow data between when it's supplied and when 199 * {@link #armRebootEscrowIfNeeded()} is called. 200 */ 201 @GuardedBy("mKeyGenerationLock") 202 private RebootEscrowKey mPendingRebootEscrowKey; 203 204 private final UserManager mUserManager; 205 206 private final Injector mInjector; 207 208 private final LockSettingsStorage mStorage; 209 210 private final Callbacks mCallbacks; 211 212 private final RebootEscrowKeyStoreManager mKeyStoreManager; 213 214 private final Handler mHandler; 215 216 PowerManager.WakeLock mWakeLock; 217 218 private ConnectivityManager.NetworkCallback mNetworkCallback; 219 220 interface Callbacks { isUserSecure(int userId)221 boolean isUserSecure(int userId); 222 onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId)223 void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId); 224 } 225 226 static class Injector { 227 protected Context mContext; 228 private final RebootEscrowKeyStoreManager mKeyStoreManager; 229 private final LockSettingsStorage mStorage; 230 private RebootEscrowProviderInterface mRebootEscrowProvider; 231 private final UserManagerInternal mUserManagerInternal; 232 Injector( Context context, LockSettingsStorage storage, UserManagerInternal userManagerInternal)233 Injector( 234 Context context, 235 LockSettingsStorage storage, 236 UserManagerInternal userManagerInternal) { 237 mContext = context; 238 mStorage = storage; 239 mKeyStoreManager = new RebootEscrowKeyStoreManager(); 240 mUserManagerInternal = userManagerInternal; 241 } 242 createRebootEscrowProvider()243 private RebootEscrowProviderInterface createRebootEscrowProvider() { 244 RebootEscrowProviderInterface rebootEscrowProvider; 245 if (serverBasedResumeOnReboot()) { 246 Slog.i(TAG, "Using server based resume on reboot"); 247 rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage); 248 } else { 249 Slog.i(TAG, "Using HAL based resume on reboot"); 250 rebootEscrowProvider = new RebootEscrowProviderHalImpl(); 251 } 252 253 if (rebootEscrowProvider.hasRebootEscrowSupport()) { 254 return rebootEscrowProvider; 255 } 256 return null; 257 } 258 post(Handler handler, Runnable runnable)259 void post(Handler handler, Runnable runnable) { 260 handler.post(runnable); 261 } 262 postDelayed(Handler handler, Runnable runnable, long delayMillis)263 void postDelayed(Handler handler, Runnable runnable, long delayMillis) { 264 handler.postDelayed(runnable, delayMillis); 265 } 266 serverBasedResumeOnReboot()267 public boolean serverBasedResumeOnReboot() { 268 // Always use the server based RoR if the HAL isn't installed on device. 269 if (!mContext.getPackageManager().hasSystemFeature( 270 PackageManager.FEATURE_REBOOT_ESCROW)) { 271 return true; 272 } 273 274 return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, 275 "server_based_ror_enabled", false); 276 } 277 waitForInternet()278 public boolean waitForInternet() { 279 return DeviceConfig.getBoolean( 280 DeviceConfig.NAMESPACE_OTA, "wait_for_internet_ror", false); 281 } 282 isNetworkConnected()283 public boolean isNetworkConnected() { 284 final ConnectivityManager connectivityManager = 285 mContext.getSystemService(ConnectivityManager.class); 286 if (connectivityManager == null) { 287 return false; 288 } 289 290 Network activeNetwork = connectivityManager.getActiveNetwork(); 291 NetworkCapabilities networkCapabilities = 292 connectivityManager.getNetworkCapabilities(activeNetwork); 293 return networkCapabilities != null 294 && networkCapabilities.hasCapability( 295 NetworkCapabilities.NET_CAPABILITY_INTERNET) 296 && networkCapabilities.hasCapability( 297 NetworkCapabilities.NET_CAPABILITY_VALIDATED); 298 } 299 300 /** 301 * Request network with internet connectivity with timeout. 302 * 303 * @param networkCallback callback to be executed if connectivity manager exists. 304 * @return true if success 305 */ requestNetworkWithInternet( ConnectivityManager.NetworkCallback networkCallback)306 public boolean requestNetworkWithInternet( 307 ConnectivityManager.NetworkCallback networkCallback) { 308 final ConnectivityManager connectivityManager = 309 mContext.getSystemService(ConnectivityManager.class); 310 if (connectivityManager == null) { 311 return false; 312 } 313 NetworkRequest request = 314 new NetworkRequest.Builder() 315 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 316 .build(); 317 318 connectivityManager.requestNetwork( 319 request, networkCallback, getLoadEscrowTimeoutMillis()); 320 return true; 321 } 322 stopRequestingNetwork(ConnectivityManager.NetworkCallback networkCallback)323 public void stopRequestingNetwork(ConnectivityManager.NetworkCallback networkCallback) { 324 final ConnectivityManager connectivityManager = 325 mContext.getSystemService(ConnectivityManager.class); 326 if (connectivityManager == null) { 327 return; 328 } 329 connectivityManager.unregisterNetworkCallback(networkCallback); 330 } 331 getContext()332 public Context getContext() { 333 return mContext; 334 } 335 getUserManager()336 public UserManager getUserManager() { 337 return (UserManager) mContext.getSystemService(Context.USER_SERVICE); 338 } 339 getUserManagerInternal()340 public UserManagerInternal getUserManagerInternal() { 341 return mUserManagerInternal; 342 } 343 getKeyStoreManager()344 public RebootEscrowKeyStoreManager getKeyStoreManager() { 345 return mKeyStoreManager; 346 } 347 createRebootEscrowProviderIfNeeded()348 public RebootEscrowProviderInterface createRebootEscrowProviderIfNeeded() { 349 // Initialize for the provider lazily. Because the device_config and service 350 // implementation apps may change when system server is running. 351 if (mRebootEscrowProvider == null) { 352 mRebootEscrowProvider = createRebootEscrowProvider(); 353 } 354 355 return mRebootEscrowProvider; 356 } 357 getWakeLock()358 PowerManager.WakeLock getWakeLock() { 359 final PowerManager pm = mContext.getSystemService(PowerManager.class); 360 return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RebootEscrowManager"); 361 } 362 getRebootEscrowProvider()363 public RebootEscrowProviderInterface getRebootEscrowProvider() { 364 return mRebootEscrowProvider; 365 } 366 clearRebootEscrowProvider()367 public void clearRebootEscrowProvider() { 368 mRebootEscrowProvider = null; 369 } 370 getBootCount()371 public int getBootCount() { 372 return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 373 0); 374 } 375 getCurrentTimeMillis()376 public long getCurrentTimeMillis() { 377 return System.currentTimeMillis(); 378 } 379 getLoadEscrowDataRetryLimit()380 public int getLoadEscrowDataRetryLimit() { 381 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 382 "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT); 383 } 384 getLoadEscrowDataRetryIntervalSeconds()385 public int getLoadEscrowDataRetryIntervalSeconds() { 386 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 387 "load_escrow_data_retry_interval_seconds", 388 DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS); 389 } 390 391 @VisibleForTesting getLoadEscrowTimeoutMillis()392 public int getLoadEscrowTimeoutMillis() { 393 return DEFAULT_LOAD_ESCROW_BASE_TIMEOUT_MILLIS; 394 } 395 396 @VisibleForTesting getWakeLockTimeoutMillis()397 public int getWakeLockTimeoutMillis() { 398 return getLoadEscrowTimeoutMillis() + DEFAULT_LOAD_ESCROW_TIMEOUT_EXTENSION_MILLIS; 399 } 400 reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootCompleteInSeconds)401 public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, 402 int escrowDurationInSeconds, int vbmetaDigestStatus, 403 int durationSinceBootCompleteInSeconds) { 404 FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success, 405 errorCode, serviceType, attemptCount, escrowDurationInSeconds, 406 vbmetaDigestStatus, durationSinceBootCompleteInSeconds); 407 } 408 getEventLog()409 public RebootEscrowEventLog getEventLog() { 410 return new RebootEscrowEventLog(); 411 } 412 getVbmetaDigest(boolean other)413 public String getVbmetaDigest(boolean other) { 414 return other ? SystemProperties.get(OTHER_VBMETA_DIGEST_PROP_NAME) 415 : SystemProperties.get(VBMETA_DIGEST_PROP_NAME); 416 } 417 } 418 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage, Handler handler, UserManagerInternal userManagerInternal)419 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage, 420 Handler handler, UserManagerInternal userManagerInternal) { 421 this(new Injector(context, storage, userManagerInternal), callbacks, storage, handler); 422 } 423 424 @VisibleForTesting RebootEscrowManager(Injector injector, Callbacks callbacks, LockSettingsStorage storage, Handler handler)425 RebootEscrowManager(Injector injector, Callbacks callbacks, 426 LockSettingsStorage storage, Handler handler) { 427 mInjector = injector; 428 mCallbacks = callbacks; 429 mStorage = storage; 430 mUserManager = injector.getUserManager(); 431 mEventLog = injector.getEventLog(); 432 mKeyStoreManager = injector.getKeyStoreManager(); 433 mHandler = handler; 434 } 435 436 /** Wrapper function to set error code serialized through handler, */ setLoadEscrowDataErrorCode(@ebootEscrowErrorCode int value, Handler handler)437 private void setLoadEscrowDataErrorCode(@RebootEscrowErrorCode int value, Handler handler) { 438 if (mInjector.waitForInternet()) { 439 mInjector.post( 440 handler, 441 () -> { 442 mLoadEscrowDataErrorCode = value; 443 }); 444 } else { 445 mLoadEscrowDataErrorCode = value; 446 } 447 } 448 449 /** Wrapper function to compare and set error code serialized through handler. */ compareAndSetLoadEscrowDataErrorCode( @ebootEscrowErrorCode int expectedValue, @RebootEscrowErrorCode int newValue, Handler handler)450 private void compareAndSetLoadEscrowDataErrorCode( 451 @RebootEscrowErrorCode int expectedValue, 452 @RebootEscrowErrorCode int newValue, 453 Handler handler) { 454 if (expectedValue == mLoadEscrowDataErrorCode) { 455 setLoadEscrowDataErrorCode(newValue, handler); 456 } 457 } 458 onGetRebootEscrowKeyFailed( List<UserInfo> users, int attemptCount, Handler retryHandler)459 private void onGetRebootEscrowKeyFailed( 460 List<UserInfo> users, int attemptCount, Handler retryHandler) { 461 Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); 462 for (UserInfo user : users) { 463 mStorage.removeRebootEscrow(user.id); 464 } 465 466 onEscrowRestoreComplete(false, attemptCount, retryHandler); 467 } 468 getUsersToUnlock(List<UserInfo> users)469 private List<UserInfo> getUsersToUnlock(List<UserInfo> users) { 470 // System user must be unlocked to unlock any other user 471 if (mCallbacks.isUserSecure(USER_SYSTEM) && !mStorage.hasRebootEscrow(USER_SYSTEM)) { 472 Slog.i(TAG, "No reboot escrow data found for system user"); 473 return Collections.emptyList(); 474 } 475 476 Set<Integer> noEscrowDataUsers = new HashSet<>(); 477 for (UserInfo user : users) { 478 if (mCallbacks.isUserSecure(user.id) 479 && !mStorage.hasRebootEscrow(user.id)) { 480 Slog.d(TAG, "No reboot escrow data found for user " + user); 481 noEscrowDataUsers.add(user.id); 482 } 483 } 484 485 List<UserInfo> rebootEscrowUsers = new ArrayList<>(); 486 for (UserInfo user : users) { 487 // No lskf, no need to unlock. 488 if (!mCallbacks.isUserSecure(user.id)) { 489 continue; 490 } 491 // Don't unlock if user or user's parent does not have reboot data 492 int userId = user.id; 493 if (noEscrowDataUsers.contains(userId) 494 || noEscrowDataUsers.contains( 495 mInjector.getUserManagerInternal().getProfileParentId(userId))) { 496 continue; 497 } 498 rebootEscrowUsers.add(user); 499 } 500 return rebootEscrowUsers; 501 } 502 loadRebootEscrowDataIfAvailable(Handler retryHandler)503 void loadRebootEscrowDataIfAvailable(Handler retryHandler) { 504 List<UserInfo> users = mUserManager.getUsers(); 505 List<UserInfo> rebootEscrowUsers = getUsersToUnlock(users); 506 507 if (rebootEscrowUsers.isEmpty()) { 508 Slog.i(TAG, "No reboot escrow data found for users," 509 + " skipping loading escrow data"); 510 setLoadEscrowDataErrorCode(ERROR_NO_REBOOT_ESCROW_DATA, retryHandler); 511 reportMetricOnRestoreComplete( 512 /* success= */ false, /* attemptCount= */ 1, retryHandler); 513 clearMetricsStorage(); 514 return; 515 } 516 517 // Acquire the wake lock to make sure our scheduled task will run. 518 mWakeLock = mInjector.getWakeLock(); 519 if (mWakeLock != null) { 520 mWakeLock.setReferenceCounted(false); 521 mWakeLock.acquire(mInjector.getWakeLockTimeoutMillis()); 522 } 523 524 if (mInjector.waitForInternet()) { 525 // Timeout to stop retrying same as the wake lock timeout. 526 mInjector.postDelayed( 527 retryHandler, 528 () -> { 529 mRebootEscrowTimedOut = true; 530 }, 531 mInjector.getLoadEscrowTimeoutMillis()); 532 533 mInjector.post( 534 retryHandler, 535 () -> loadRebootEscrowDataOnInternet(retryHandler, users, rebootEscrowUsers)); 536 return; 537 } 538 539 mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry( 540 retryHandler, 0, users, rebootEscrowUsers)); 541 } 542 scheduleLoadRebootEscrowDataOrFail( Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)543 void scheduleLoadRebootEscrowDataOrFail( 544 Handler retryHandler, 545 int attemptNumber, 546 List<UserInfo> users, 547 List<UserInfo> rebootEscrowUsers) { 548 Objects.requireNonNull(retryHandler); 549 550 final int retryLimit = mInjector.getLoadEscrowDataRetryLimit(); 551 final int retryIntervalInSeconds = mInjector.getLoadEscrowDataRetryIntervalSeconds(); 552 553 if (attemptNumber < retryLimit && !mRebootEscrowTimedOut) { 554 Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber); 555 mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry( 556 retryHandler, attemptNumber, users, rebootEscrowUsers), 557 retryIntervalInSeconds * 1000); 558 return; 559 } 560 561 if (mInjector.waitForInternet()) { 562 if (mRebootEscrowTimedOut) { 563 Slog.w(TAG, "Failed to load reboot escrow data within timeout"); 564 compareAndSetLoadEscrowDataErrorCode( 565 ERROR_NONE, ERROR_TIMEOUT_EXHAUSTED, retryHandler); 566 } else { 567 Slog.w( 568 TAG, 569 "Failed to load reboot escrow data after " + attemptNumber + " attempts"); 570 compareAndSetLoadEscrowDataErrorCode( 571 ERROR_NONE, ERROR_RETRY_COUNT_EXHAUSTED, retryHandler); 572 } 573 onGetRebootEscrowKeyFailed(users, attemptNumber, retryHandler); 574 return; 575 } 576 577 Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); 578 if (mInjector.serverBasedResumeOnReboot() && !mInjector.isNetworkConnected()) { 579 mLoadEscrowDataErrorCode = ERROR_NO_NETWORK; 580 } else { 581 mLoadEscrowDataErrorCode = ERROR_RETRY_COUNT_EXHAUSTED; 582 } 583 onGetRebootEscrowKeyFailed(users, attemptNumber, retryHandler); 584 } 585 loadRebootEscrowDataOnInternet( Handler retryHandler, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)586 void loadRebootEscrowDataOnInternet( 587 Handler retryHandler, List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { 588 589 // HAL-Based RoR does not require network connectivity. 590 if (!mInjector.serverBasedResumeOnReboot()) { 591 loadRebootEscrowDataWithRetry( 592 retryHandler, /* attemptNumber = */ 0, users, rebootEscrowUsers); 593 return; 594 } 595 596 mNetworkCallback = 597 new ConnectivityManager.NetworkCallback() { 598 @Override 599 public void onAvailable(Network network) { 600 compareAndSetLoadEscrowDataErrorCode( 601 ERROR_NO_NETWORK, ERROR_NONE, retryHandler); 602 603 if (!mLoadEscrowDataWithRetry) { 604 mLoadEscrowDataWithRetry = true; 605 // Only kickoff retry mechanism on first onAvailable call. 606 loadRebootEscrowDataWithRetry( 607 retryHandler, 608 /* attemptNumber = */ 0, 609 users, 610 rebootEscrowUsers); 611 } 612 } 613 614 @Override 615 public void onUnavailable() { 616 Slog.w(TAG, "Failed to connect to network within timeout"); 617 compareAndSetLoadEscrowDataErrorCode( 618 ERROR_NONE, ERROR_NO_NETWORK, retryHandler); 619 onGetRebootEscrowKeyFailed(users, /* attemptCount= */ 0, retryHandler); 620 } 621 622 @Override 623 public void onLost(Network lostNetwork) { 624 // TODO(b/231660348): If network is lost, wait for network to become 625 // available again. 626 Slog.w(TAG, "Network lost, still attempting to load escrow key."); 627 compareAndSetLoadEscrowDataErrorCode( 628 ERROR_NONE, ERROR_NO_NETWORK, retryHandler); 629 } 630 }; 631 632 // Fallback to retrying without waiting for internet on failure. 633 boolean success = mInjector.requestNetworkWithInternet(mNetworkCallback); 634 if (!success) { 635 loadRebootEscrowDataWithRetry( 636 retryHandler, /* attemptNumber = */ 0, users, rebootEscrowUsers); 637 } 638 } 639 loadRebootEscrowDataWithRetry( Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)640 void loadRebootEscrowDataWithRetry( 641 Handler retryHandler, 642 int attemptNumber, 643 List<UserInfo> users, 644 List<UserInfo> rebootEscrowUsers) { 645 // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is 646 // generated before reboot. Note that we will clear the escrow key even if the keystore key 647 // is null. 648 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 649 if (kk == null) { 650 Slog.i(TAG, "Failed to load the key for resume on reboot from key store."); 651 } 652 653 RebootEscrowKey escrowKey; 654 try { 655 escrowKey = getAndClearRebootEscrowKey(kk, retryHandler); 656 } catch (IOException e) { 657 Slog.i(TAG, "Failed to load escrow key, scheduling retry.", e); 658 scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users, 659 rebootEscrowUsers); 660 return; 661 } 662 663 if (escrowKey == null) { 664 if (mLoadEscrowDataErrorCode == ERROR_NONE) { 665 // Specifically check if the RoR provider has changed after reboot. 666 int providerType = mInjector.serverBasedResumeOnReboot() 667 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 668 : RebootEscrowProviderInterface.TYPE_HAL; 669 if (providerType != mStorage.getInt(REBOOT_ESCROW_KEY_PROVIDER, -1, USER_SYSTEM)) { 670 setLoadEscrowDataErrorCode(ERROR_PROVIDER_MISMATCH, retryHandler); 671 } else { 672 setLoadEscrowDataErrorCode(ERROR_LOAD_ESCROW_KEY, retryHandler); 673 } 674 } 675 onGetRebootEscrowKeyFailed(users, attemptNumber + 1, retryHandler); 676 return; 677 } 678 679 mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA); 680 681 boolean allUsersUnlocked = true; 682 for (UserInfo user : rebootEscrowUsers) { 683 allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk); 684 } 685 686 if (!allUsersUnlocked) { 687 compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_UNLOCK_ALL_USERS, retryHandler); 688 } 689 onEscrowRestoreComplete(allUsersUnlocked, attemptNumber + 1, retryHandler); 690 } 691 clearMetricsStorage()692 private void clearMetricsStorage() { 693 mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); 694 mStorage.removeKey(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, USER_SYSTEM); 695 mStorage.removeKey(REBOOT_ESCROW_KEY_VBMETA_DIGEST, USER_SYSTEM); 696 mStorage.removeKey(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, USER_SYSTEM); 697 mStorage.removeKey(REBOOT_ESCROW_KEY_PROVIDER, USER_SYSTEM); 698 } 699 getVbmetaDigestStatusOnRestoreComplete()700 private int getVbmetaDigestStatusOnRestoreComplete() { 701 String currentVbmetaDigest = mInjector.getVbmetaDigest(false); 702 String vbmetaDigestStored = mStorage.getString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, 703 "", USER_SYSTEM); 704 String vbmetaDigestOtherStored = mStorage.getString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 705 "", USER_SYSTEM); 706 707 // The other vbmeta digest is never set, assume no slot switch is attempted. 708 if (vbmetaDigestOtherStored.isEmpty()) { 709 if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 710 return FrameworkStatsLog 711 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 712 } 713 return FrameworkStatsLog 714 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 715 } 716 717 // The other vbmeta digest is set, we expect to boot into the new slot. 718 if (currentVbmetaDigest.equals(vbmetaDigestOtherStored)) { 719 return FrameworkStatsLog 720 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 721 } else if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 722 return FrameworkStatsLog 723 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_FALLBACK_SLOT; 724 } 725 return FrameworkStatsLog 726 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 727 } 728 reportMetricOnRestoreComplete( boolean success, int attemptCount, Handler retryHandler)729 private void reportMetricOnRestoreComplete( 730 boolean success, int attemptCount, Handler retryHandler) { 731 int serviceType = mInjector.serverBasedResumeOnReboot() 732 ? FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__SERVER_BASED 733 : FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__HAL; 734 735 long armedTimestamp = mStorage.getLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, -1, 736 USER_SYSTEM); 737 int escrowDurationInSeconds = -1; 738 long currentTimeStamp = mInjector.getCurrentTimeMillis(); 739 if (armedTimestamp != -1 && currentTimeStamp > armedTimestamp) { 740 escrowDurationInSeconds = (int) (currentTimeStamp - armedTimestamp) / 1000; 741 } 742 743 int vbmetaDigestStatus = getVbmetaDigestStatusOnRestoreComplete(); 744 if (!success) { 745 compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_UNKNOWN, retryHandler); 746 } 747 748 Slog.i( 749 TAG, 750 "Reporting RoR recovery metrics, success: " 751 + success 752 + ", service type: " 753 + serviceType 754 + ", error code: " 755 + mLoadEscrowDataErrorCode); 756 // TODO(179105110) report the duration since boot complete. 757 mInjector.reportMetric( 758 success, 759 mLoadEscrowDataErrorCode, 760 serviceType, 761 attemptCount, 762 escrowDurationInSeconds, 763 vbmetaDigestStatus, 764 -1); 765 766 setLoadEscrowDataErrorCode(ERROR_NONE, retryHandler); 767 } 768 onEscrowRestoreComplete(boolean success, int attemptCount, Handler retryHandler)769 private void onEscrowRestoreComplete(boolean success, int attemptCount, Handler retryHandler) { 770 int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM); 771 772 int bootCountDelta = mInjector.getBootCount() - previousBootCount; 773 if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) { 774 reportMetricOnRestoreComplete(success, attemptCount, retryHandler); 775 } 776 // Clear the old key in keystore. A new key will be generated by new RoR requests. 777 mKeyStoreManager.clearKeyStoreEncryptionKey(); 778 // Clear the saved reboot escrow provider 779 mInjector.clearRebootEscrowProvider(); 780 clearMetricsStorage(); 781 782 if (mNetworkCallback != null) { 783 mInjector.stopRequestingNetwork(mNetworkCallback); 784 } 785 786 if (mWakeLock != null) { 787 mWakeLock.release(); 788 } 789 } 790 getAndClearRebootEscrowKey(SecretKey kk, Handler retryHandler)791 private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk, Handler retryHandler) 792 throws IOException { 793 RebootEscrowProviderInterface rebootEscrowProvider = 794 mInjector.createRebootEscrowProviderIfNeeded(); 795 if (rebootEscrowProvider == null) { 796 Slog.w( 797 TAG, 798 "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); 799 setLoadEscrowDataErrorCode(ERROR_NO_PROVIDER, retryHandler); 800 return null; 801 } 802 803 // Server based RoR always need the decryption key from keystore. 804 if (rebootEscrowProvider.getType() == RebootEscrowProviderInterface.TYPE_SERVER_BASED 805 && kk == null) { 806 setLoadEscrowDataErrorCode(ERROR_KEYSTORE_FAILURE, retryHandler); 807 return null; 808 } 809 810 // The K_s blob maybe encrypted by K_k as well. 811 RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(kk); 812 if (key != null) { 813 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK); 814 } 815 return key; 816 } 817 restoreRebootEscrowForUser(@serIdInt int userId, RebootEscrowKey ks, SecretKey kk)818 private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey ks, 819 SecretKey kk) { 820 if (!mStorage.hasRebootEscrow(userId)) { 821 return false; 822 } 823 824 try { 825 byte[] blob = mStorage.readRebootEscrow(userId); 826 mStorage.removeRebootEscrow(userId); 827 828 RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(ks, blob, kk); 829 830 mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(), 831 escrowData.getSyntheticPassword(), userId); 832 Slog.i(TAG, "Restored reboot escrow data for user " + userId); 833 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId); 834 return true; 835 } catch (IOException e) { 836 Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); 837 return false; 838 } 839 } 840 callToRebootEscrowIfNeeded(@serIdInt int userId, byte spVersion, byte[] syntheticPassword)841 void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion, 842 byte[] syntheticPassword) { 843 if (!mRebootEscrowWanted) { 844 return; 845 } 846 847 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 848 Slog.w(TAG, "Not storing escrow data, RebootEscrowProvider is unavailable"); 849 return; 850 } 851 852 RebootEscrowKey escrowKey = generateEscrowKeyIfNeeded(); 853 if (escrowKey == null) { 854 Slog.e(TAG, "Could not generate escrow key"); 855 return; 856 } 857 858 SecretKey kk = mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded(); 859 if (kk == null) { 860 Slog.e(TAG, "Failed to generate encryption key from keystore."); 861 return; 862 } 863 864 final RebootEscrowData escrowData; 865 try { 866 escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion, 867 syntheticPassword, kk); 868 } catch (IOException e) { 869 setRebootEscrowReady(false); 870 Slog.w(TAG, "Could not escrow reboot data", e); 871 return; 872 } 873 874 mStorage.writeRebootEscrow(userId, escrowData.getBlob()); 875 mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId); 876 877 setRebootEscrowReady(true); 878 } 879 generateEscrowKeyIfNeeded()880 private RebootEscrowKey generateEscrowKeyIfNeeded() { 881 synchronized (mKeyGenerationLock) { 882 if (mPendingRebootEscrowKey != null) { 883 return mPendingRebootEscrowKey; 884 } 885 886 RebootEscrowKey key; 887 try { 888 key = RebootEscrowKey.generate(); 889 } catch (IOException e) { 890 Slog.w(TAG, "Could not generate reboot escrow key"); 891 return null; 892 } 893 894 mPendingRebootEscrowKey = key; 895 return key; 896 } 897 } 898 clearRebootEscrowIfNeeded()899 private void clearRebootEscrowIfNeeded() { 900 mRebootEscrowWanted = false; 901 setRebootEscrowReady(false); 902 903 // We want to clear the internal data inside the provider, so always try to create the 904 // provider. 905 RebootEscrowProviderInterface rebootEscrowProvider = 906 mInjector.createRebootEscrowProviderIfNeeded(); 907 if (rebootEscrowProvider == null) { 908 Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request"); 909 } else { 910 rebootEscrowProvider.clearRebootEscrowKey(); 911 } 912 913 mInjector.clearRebootEscrowProvider(); 914 clearMetricsStorage(); 915 916 List<UserInfo> users = mUserManager.getUsers(); 917 for (UserInfo user : users) { 918 mStorage.removeRebootEscrow(user.id); 919 } 920 921 mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); 922 } 923 armRebootEscrowIfNeeded()924 @ArmRebootEscrowErrorCode int armRebootEscrowIfNeeded() { 925 if (!mRebootEscrowReady) { 926 return ARM_REBOOT_ERROR_ESCROW_NOT_READY; 927 } 928 929 RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); 930 if (rebootEscrowProvider == null) { 931 Slog.w(TAG, "Not storing escrow key, RebootEscrowProvider is unavailable"); 932 clearRebootEscrowIfNeeded(); 933 return ARM_REBOOT_ERROR_NO_PROVIDER; 934 } 935 936 int expectedProviderType = mInjector.serverBasedResumeOnReboot() 937 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 938 : RebootEscrowProviderInterface.TYPE_HAL; 939 int actualProviderType = rebootEscrowProvider.getType(); 940 if (expectedProviderType != actualProviderType) { 941 Slog.w(TAG, "Expect reboot escrow provider " + expectedProviderType 942 + ", but the RoR is prepared with " + actualProviderType 943 + ". Please prepare the RoR again."); 944 clearRebootEscrowIfNeeded(); 945 return ARM_REBOOT_ERROR_PROVIDER_MISMATCH; 946 } 947 948 RebootEscrowKey escrowKey; 949 synchronized (mKeyGenerationLock) { 950 escrowKey = mPendingRebootEscrowKey; 951 } 952 953 if (escrowKey == null) { 954 Slog.e(TAG, "Escrow key is null, but escrow was marked as ready"); 955 clearRebootEscrowIfNeeded(); 956 return ARM_REBOOT_ERROR_NO_ESCROW_KEY; 957 } 958 959 // We will use the same key from keystore to encrypt the escrow key and escrow data blob. 960 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 961 if (kk == null) { 962 Slog.e(TAG, "Failed to get encryption key from keystore."); 963 clearRebootEscrowIfNeeded(); 964 return ARM_REBOOT_ERROR_KEYSTORE_FAILURE; 965 } 966 967 // TODO(b/183140900) design detailed errors for store escrow key errors. 968 // We don't clear rebootEscrow here, because some errors may be recoverable, e.g. network 969 // unavailable for server based provider. 970 boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); 971 if (!armedRebootEscrow) { 972 return ARM_REBOOT_ERROR_STORE_ESCROW_KEY; 973 } 974 975 mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); 976 mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, mInjector.getCurrentTimeMillis(), 977 USER_SYSTEM); 978 // Store the vbmeta digest of both slots. 979 mStorage.setString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, mInjector.getVbmetaDigest(false), 980 USER_SYSTEM); 981 mStorage.setString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 982 mInjector.getVbmetaDigest(true), USER_SYSTEM); 983 mStorage.setInt(REBOOT_ESCROW_KEY_PROVIDER, actualProviderType, USER_SYSTEM); 984 mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); 985 986 return ARM_REBOOT_ERROR_NONE; 987 } 988 setRebootEscrowReady(boolean ready)989 private void setRebootEscrowReady(boolean ready) { 990 if (mRebootEscrowReady != ready) { 991 mHandler.post(() -> mRebootEscrowListener.onPreparedForReboot(ready)); 992 } 993 mRebootEscrowReady = ready; 994 } 995 prepareRebootEscrow()996 boolean prepareRebootEscrow() { 997 clearRebootEscrowIfNeeded(); 998 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 999 Slog.w(TAG, "No reboot escrow provider, skipping resume on reboot preparation."); 1000 return false; 1001 } 1002 1003 mRebootEscrowWanted = true; 1004 mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF); 1005 return true; 1006 } 1007 clearRebootEscrow()1008 boolean clearRebootEscrow() { 1009 clearRebootEscrowIfNeeded(); 1010 return true; 1011 } 1012 setRebootEscrowListener(RebootEscrowListener listener)1013 void setRebootEscrowListener(RebootEscrowListener listener) { 1014 mRebootEscrowListener = listener; 1015 } 1016 1017 @VisibleForTesting 1018 public static class RebootEscrowEvent { 1019 static final int FOUND_ESCROW_DATA = 1; 1020 static final int SET_ARMED_STATUS = 2; 1021 static final int CLEARED_LSKF_REQUEST = 3; 1022 static final int RETRIEVED_STORED_KEK = 4; 1023 static final int REQUESTED_LSKF = 5; 1024 static final int STORED_LSKF_FOR_USER = 6; 1025 static final int RETRIEVED_LSKF_FOR_USER = 7; 1026 1027 final int mEventId; 1028 final Integer mUserId; 1029 final long mWallTime; 1030 final long mTimestamp; 1031 RebootEscrowEvent(int eventId)1032 RebootEscrowEvent(int eventId) { 1033 this(eventId, null); 1034 } 1035 RebootEscrowEvent(int eventId, Integer userId)1036 RebootEscrowEvent(int eventId, Integer userId) { 1037 mEventId = eventId; 1038 mUserId = userId; 1039 mTimestamp = SystemClock.uptimeMillis(); 1040 mWallTime = System.currentTimeMillis(); 1041 } 1042 getEventDescription()1043 String getEventDescription() { 1044 switch (mEventId) { 1045 case FOUND_ESCROW_DATA: 1046 return "Found escrow data"; 1047 case SET_ARMED_STATUS: 1048 return "Set armed status"; 1049 case CLEARED_LSKF_REQUEST: 1050 return "Cleared request for LSKF"; 1051 case RETRIEVED_STORED_KEK: 1052 return "Retrieved stored KEK"; 1053 case REQUESTED_LSKF: 1054 return "Requested LSKF"; 1055 case STORED_LSKF_FOR_USER: 1056 return "Stored LSKF for user"; 1057 case RETRIEVED_LSKF_FOR_USER: 1058 return "Retrieved LSKF for user"; 1059 default: 1060 return "Unknown event ID " + mEventId; 1061 } 1062 } 1063 } 1064 1065 @VisibleForTesting 1066 public static class RebootEscrowEventLog { 1067 private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16]; 1068 private int mNextIndex = 0; 1069 addEntry(int eventId)1070 void addEntry(int eventId) { 1071 addEntryInternal(new RebootEscrowEvent(eventId)); 1072 } 1073 addEntry(int eventId, int userId)1074 void addEntry(int eventId, int userId) { 1075 addEntryInternal(new RebootEscrowEvent(eventId, userId)); 1076 } 1077 addEntryInternal(RebootEscrowEvent event)1078 private void addEntryInternal(RebootEscrowEvent event) { 1079 final int index = mNextIndex; 1080 mEntries[index] = event; 1081 mNextIndex = (mNextIndex + 1) % mEntries.length; 1082 } 1083 dump(@onNull IndentingPrintWriter pw)1084 void dump(@NonNull IndentingPrintWriter pw) { 1085 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); 1086 1087 for (int i = 0; i < mEntries.length; ++i) { 1088 RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length]; 1089 if (event == null) { 1090 continue; 1091 } 1092 1093 pw.print("Event #"); 1094 pw.println(i); 1095 1096 pw.println(" time=" + sdf.format(new Date(event.mWallTime)) 1097 + " (timestamp=" + event.mTimestamp + ")"); 1098 1099 pw.print(" event="); 1100 pw.println(event.getEventDescription()); 1101 1102 if (event.mUserId != null) { 1103 pw.print(" user="); 1104 pw.println(event.mUserId); 1105 } 1106 } 1107 } 1108 } 1109 dump(@onNull IndentingPrintWriter pw)1110 void dump(@NonNull IndentingPrintWriter pw) { 1111 pw.print("mRebootEscrowWanted="); 1112 pw.println(mRebootEscrowWanted); 1113 1114 pw.print("mRebootEscrowReady="); 1115 pw.println(mRebootEscrowReady); 1116 1117 pw.print("mRebootEscrowListener="); 1118 pw.println(mRebootEscrowListener); 1119 1120 pw.print("mLoadEscrowDataErrorCode="); 1121 pw.println(mLoadEscrowDataErrorCode); 1122 1123 boolean keySet; 1124 synchronized (mKeyGenerationLock) { 1125 keySet = mPendingRebootEscrowKey != null; 1126 } 1127 1128 pw.print("mPendingRebootEscrowKey is "); 1129 pw.println(keySet ? "set" : "not set"); 1130 1131 RebootEscrowProviderInterface provider = mInjector.getRebootEscrowProvider(); 1132 String providerType = provider == null ? "null" : String.valueOf(provider.getType()); 1133 pw.print("RebootEscrowProvider type is " + providerType); 1134 1135 pw.println(); 1136 pw.println("Event log:"); 1137 pw.increaseIndent(); 1138 mEventLog.dump(pw); 1139 pw.println(); 1140 pw.decreaseIndent(); 1141 } 1142 } 1143