1.背景
最近遇到了一些系统关机重启的问题;例:
1.Ohana界面点击进入多任务界面,滑动多任务界面应用列表出现自动关机重启
2.点击运行哔哩哔哩应用,测试机自动关机重启
3.使用过程中设备自动关机
…
我遇到的这几个问题设备重启的原因都是相同的,即:
查看mainlog,发现设备重启得原因为:
01-14 07:31:54.939 1574 8753 I ShutdownThread: Rebooting, reason: Rollback staged install
分析dmesglog发现导致Rollback的原因为:
[ 27.206782] (1)[1:init]init: starting service ‘vendor.tlocd’…
[ 27.225054] (1)[1:init]init: Service ‘vendor.tlocd’ (pid 5546) exited with status 1
[ 27.225080] (1)[1:init]init: Sending signal 9 to service ‘vendor.tlocd’ (pid 5546) process group…
[ 27.225252] (1)[1:init]libprocessgroup: Successfully killed process cgroup uid 1000 pid 5546 in 0ms
[ 27.225379] (1)[1:init]init: updatable process ‘vendor.tlocd’ exited 4 times in 4 minutes
[ 27.226357] (1)[741:apexd]apexd: Native process ‘vendor.tlocd’ is crashing. Attempting a revert
查看vendor.tlocd的pid为5546,在mainlog中的log为:
01-14 07:31:02.638 5546 5546 F linker : CANNOT LINK EXECUTABLE “/vendor/bin/tloc_daemon”: library “libloc_api_v02.so” not found: needed by main executable
即vendor.tlocd 的service缺少libloc_api_v02.so库的链接,该service在4分钟内退出了4次,导致了Rollback,引起了设备的重启
2.机制及原理
查看mainlog,发现设备重启得原因为:
01-14 07:31:54.939 1574 8753 I ShutdownThread: Rebooting, reason: Rollback staged install
从源码角度分析,该log打印的位置为:
2.1/frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
652 /**
653 * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
654 * or {@link #shutdown(Context, String, boolean)} instead.
655 *
656 * @param context Context used to vibrate or null without vibration
657 * @param reboot true to reboot or false to shutdown
658 * @param reason reason for reboot/shutdown
659 */
660 public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
661 if (reboot) {
662 Log.i(TAG, "Rebooting, reason: " + reason);
663 PowerManagerService.lowLevelReboot(reason);
664 Log.e(TAG, "Reboot failed, will attempt shutdown instead");
665 reason = null;
666 } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
667 // vibrate before shutting down
668 Vibrator vibrator = new SystemVibrator(context);
669 try {
670 vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
671 } catch (Exception e) {
672 // Failure to vibrate shouldn't interrupt shutdown. Just log it.
673 Log.w(TAG, "Failed to vibrate during shutdown.", e);
674 }
675
676 // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
677 try {
678 Thread.sleep(SHUTDOWN_VIBRATE_MS);
679 } catch (InterruptedException unused) {
680 }
681 }
682 // Shutdown power
683 Log.i(TAG, "Performing low-level shutdown...");
684 PowerManagerService.lowLevelShutdown(reason);
685 }
这里是打印log的地方:
Log.i(TAG, "Rebooting, reason: " + reason);
2.2/frameworks/base/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
209 private void handleStagedSessionChange(RollbackManager rollbackManager, int rollbackId,
210 BroadcastReceiver listener, @Nullable VersionedPackage logPackage) {
211 PackageInstaller packageInstaller =
212 mContext.getPackageManager().getPackageInstaller();
213 List<RollbackInfo> recentRollbacks =
214 rollbackManager.getRecentlyCommittedRollbacks();
215 for (int i = 0; i < recentRollbacks.size(); i++) {
216 RollbackInfo recentRollback = recentRollbacks.get(i);
217 int sessionId = recentRollback.getCommittedSessionId();
218 if ((rollbackId == recentRollback.getRollbackId())
219 && (sessionId != PackageInstaller.SessionInfo.INVALID_ID)) {
220 PackageInstaller.SessionInfo sessionInfo =
221 packageInstaller.getSessionInfo(sessionId);
222 if (sessionInfo.isStagedSessionReady() && markStagedSessionHandled(rollbackId)) {
223 mContext.unregisterReceiver(listener);
224 saveStagedRollbackId(rollbackId, logPackage);
225 WatchdogRollbackLogger.logEvent(logPackage,
226 FrameworkStatsLog
227 .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
228 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
229 "");
230 } else if (sessionInfo.isStagedSessionFailed()
231 && markStagedSessionHandled(rollbackId)) {
232 WatchdogRollbackLogger.logEvent(logPackage,
233 FrameworkStatsLog
234 .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
235 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
236 "");
237 mContext.unregisterReceiver(listener);
238 }
239 }
240 }
241
242 // Wait for all pending staged sessions to get handled before rebooting.
243 if (isPendingStagedSessionsEmpty()) {
244 mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
245 }
246 }
即,这里是log中的reason:
243 if (isPendingStagedSessionsEmpty()) {
244 mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
245 }
需要查看一下RollbackPackageHealthObserver.java中的handleStagedSessionChange被调用的位置
343 /**
344 * Rolls back the session that owns {@code failedPackage}
345 *
346 * @param rollback {@code rollbackInfo} of the {@code failedPackage}
347 * @param failedPackage the package that needs to be rolled back
348 */
349 private void rollbackPackage(RollbackInfo rollback, VersionedPackage failedPackage,
350 @FailureReasons int rollbackReason) {
351 final RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
352 int reasonToLog = WatchdogRollbackLogger.mapFailureReasonToMetric(rollbackReason);
353 final String failedPackageToLog;
354 if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
355 failedPackageToLog = SystemProperties.get(
356 "sys.init.updatable_crashing_process_name", "");
357 } else {
358 failedPackageToLog = failedPackage.getPackageName();
359 }
360 VersionedPackage logPackageTemp = null;
361 if (isModule(failedPackage.getPackageName())) {
362 logPackageTemp = WatchdogRollbackLogger.getLogPackage(mContext, failedPackage);
363 }
364
365 final VersionedPackage logPackage = logPackageTemp;
366 WatchdogRollbackLogger.logEvent(logPackage,
367 FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
368 reasonToLog, failedPackageToLog);
369 final LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
370 int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
371 RollbackManager.STATUS_FAILURE);
372 if (status == RollbackManager.STATUS_SUCCESS) {
373 if (rollback.isStaged()) {
374 int rollbackId = rollback.getRollbackId();
375 synchronized (mPendingStagedRollbackIds) {
376 mPendingStagedRollbackIds.add(rollbackId);
377 }
378 BroadcastReceiver listener =
379 listenForStagedSessionReady(rollbackManager, rollbackId,
380 logPackage);
381 handleStagedSessionChange(rollbackManager, rollbackId, listener,
382 logPackage);
383 } else {
384 WatchdogRollbackLogger.logEvent(logPackage,
385 FrameworkStatsLog
386 .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
387 reasonToLog, failedPackageToLog);
388 }
389 } else {
390 if (rollback.isStaged()) {
391 markStagedSessionHandled(rollback.getRollbackId());
392 }
393 WatchdogRollbackLogger.logEvent(logPackage,
394 FrameworkStatsLog
395 .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
396 reasonToLog, failedPackageToLog);
397 }
398 });
399
400 mHandler.post(() ->
401 rollbackManager.commitRollback(rollback.getRollbackId(),
402 Collections.singletonList(failedPackage),
403 rollbackReceiver.getIntentSender()));
404 }
即,handleStagedSessionChange是在RollbackPackageHealthObserver.java中的rollbackPackage方法中调用的(条件为status == RollbackManager.STATUS_SUCCESS且rollback.isStaged());
补充下:
这里看一下rollbackManager的commitRollback方法:
342 @Override
343 public void commitRollback(int rollbackId, ParceledListSlice causePackages,
344 String callerPackageName, IntentSender statusReceiver) {
345 enforceManageRollbacks("commitRollback");
346
347 final int callingUid = Binder.getCallingUid();
348 AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
349 appOps.checkPackage(callingUid, callerPackageName);
350
351 getHandler().post(() ->
352 commitRollbackInternal(rollbackId, causePackages.getList(),
353 callerPackageName, statusReceiver));
354 }
其实也就是获取package,然后去通过commitRollbackInternal处理。
386 /**
387 * Performs the actual work to commit a rollback.
388 * The work is done on the current thread. This may be a long running
389 * operation.
390 */
391 @WorkerThread
392 private void commitRollbackInternal(int rollbackId, List<VersionedPackage> causePackages,
393 String callerPackageName, IntentSender statusReceiver) {
394 Slog.i(TAG, "commitRollback id=" + rollbackId + " caller=" + callerPackageName);
395
396 Rollback rollback = getRollbackForId(rollbackId);
397 if (rollback == null) {
398 sendFailure(
399 mContext, statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
400 "Rollback unavailable");
401 return;
402 }
403 rollback.commit(mContext, causePackages, callerPackageName, statusReceiver);
404 }
rollback的commit将会去具体的更改某个rollback的状态:
466 /**
467 * Commits the rollback.
468 */
469 void commit(final Context context, List<VersionedPackage> causePackages,
470 String callerPackageName, IntentSender statusReceiver) {
471 synchronized (mLock) {
472 if (!isAvailable()) {
473 sendFailure(context, statusReceiver,
474 RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
475 "Rollback unavailable");
476 return;
477 }
478
479 if (containsApex() && wasCreatedAtLowerExtensionVersion()) {
480 PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
481 if (extensionVersionReductionWouldViolateConstraint(mExtensionVersions, pmi)) {
482 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
483 "Rollback may violate a minExtensionVersion constraint");
484 return;
485 }
486 }
487
488 // Get a context to use to install the downgraded version of the package.
489 Context pkgContext;
490 try {
491 pkgContext = context.createPackageContextAsUser(callerPackageName, 0,
492 UserHandle.of(mUserId));
493 } catch (PackageManager.NameNotFoundException e) {
494 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
495 "Invalid callerPackageName");
496 return;
497 }
498
499 PackageManager pm = pkgContext.getPackageManager();
500 try {
501 PackageInstaller packageInstaller = pm.getPackageInstaller();
502 PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
503 PackageInstaller.SessionParams.MODE_FULL_INSTALL);
504 parentParams.setRequestDowngrade(true);
505 parentParams.setMultiPackage();
506 if (isStaged()) {
507 parentParams.setStaged();
508 }
509 parentParams.setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK);
510
511 int parentSessionId = packageInstaller.createSession(parentParams);
512 PackageInstaller.Session parentSession = packageInstaller.openSession(
513 parentSessionId);
514
515 for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
516 if (pkgRollbackInfo.isApkInApex()) {
517 // No need to issue a downgrade install request for apk-in-apex. It will
518 // be rolled back when its parent apex is downgraded.
519 continue;
520 }
521 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
522 PackageInstaller.SessionParams.MODE_FULL_INSTALL);
523 String installerPackageName = mInstallerPackageName;
524 if (TextUtils.isEmpty(mInstallerPackageName)) {
525 installerPackageName = pm.getInstallerPackageName(
526 pkgRollbackInfo.getPackageName());
527 }
528 if (installerPackageName != null) {
529 params.setInstallerPackageName(installerPackageName);
530 }
531 params.setRequestDowngrade(true);
532 params.setRequiredInstalledVersionCode(
533 pkgRollbackInfo.getVersionRolledBackFrom().getLongVersionCode());
534 if (isStaged()) {
535 params.setStaged();
536 }
537 if (pkgRollbackInfo.isApex()) {
538 params.setInstallAsApex();
539 }
540 int sessionId = packageInstaller.createSession(params);
541 PackageInstaller.Session session = packageInstaller.openSession(sessionId);
542 File[] packageCodePaths = RollbackStore.getPackageCodePaths(
543 this, pkgRollbackInfo.getPackageName());
544 if (packageCodePaths == null) {
545 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
546 "Backup copy of package: "
547 + pkgRollbackInfo.getPackageName() + " is inaccessible");
548 return;
549 }
550
551 for (File packageCodePath : packageCodePaths) {
552 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(packageCodePath,
553 ParcelFileDescriptor.MODE_READ_ONLY)) {
554 final long token = Binder.clearCallingIdentity();
555 try {
556 session.write(packageCodePath.getName(), 0,
557 packageCodePath.length(),
558 fd);
559 } finally {
560 Binder.restoreCallingIdentity(token);
561 }
562 }
563 }
564 parentSession.addChildSessionId(sessionId);
565 }
566
567 final LocalIntentReceiver receiver = new LocalIntentReceiver(
568 (Intent result) -> {
569 int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
570 PackageInstaller.STATUS_FAILURE);
571 if (status != PackageInstaller.STATUS_SUCCESS) {
572 // Committing the rollback failed, but we still have all the info we
573 // need to try rolling back again, so restore the rollback state to
574 // how it was before we tried committing.
575 // TODO: Should we just kill this rollback if commit failed?
576 // Why would we expect commit not to fail again?
577 // TODO: Could this cause a rollback to be resurrected
578 // if it should otherwise have expired by now?
579 synchronized (mLock) {
580 mState = ROLLBACK_STATE_AVAILABLE;
581 mRestoreUserDataInProgress = false;
582 info.setCommittedSessionId(-1);
583 }
584 sendFailure(context, statusReceiver,
585 RollbackManager.STATUS_FAILURE_INSTALL,
586 "Rollback downgrade install failed: "
587 + result.getStringExtra(
588 PackageInstaller.EXTRA_STATUS_MESSAGE));
589 return;
590 }
591
592 synchronized (mLock) {
593 if (!isStaged()) {
594 // All calls to restoreUserData should have
595 // completed by now for a non-staged install.
596 mRestoreUserDataInProgress = false;
597 }
598
599 info.getCausePackages().addAll(causePackages);
600 RollbackStore.deletePackageCodePaths(this);
601 RollbackStore.saveRollback(this);
602 }
603
604 // Send success.
605 try {
606 final Intent fillIn = new Intent();
607 fillIn.putExtra(
608 RollbackManager.EXTRA_STATUS,
609 RollbackManager.STATUS_SUCCESS);
610 statusReceiver.sendIntent(context, 0, fillIn, null, null);
611 } catch (IntentSender.SendIntentException e) {
612 // Nowhere to send the result back to, so don't bother.
613 }
614
615 Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
616
617 for (UserInfo userInfo : UserManager.get(context).getUsers(true)) {
618 context.sendBroadcastAsUser(broadcast,
619 userInfo.getUserHandle(),
620 Manifest.permission.MANAGE_ROLLBACKS);
621 }
622 }
623 );
624
625 mState = ROLLBACK_STATE_COMMITTED;
626 info.setCommittedSessionId(parentSessionId);
627 mRestoreUserDataInProgress = true;
628 parentSession.commit(receiver.getIntentSender());
629 } catch (IOException e) {
630 Slog.e(TAG, "Rollback failed", e);
631 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
632 "IOException: " + e.toString());
633 }
634 }
635 }
接下来需要查看一下rollbackPackage方法被调用的位置;
406 private void rollbackAll() {
407 Slog.i(TAG, "Rolling back all available rollbacks");
408 RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
409 List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks();
410
411 // Add all rollback ids to mPendingStagedRollbackIds, so that we do not reboot before all
412 // pending staged rollbacks are handled.
413 synchronized (mPendingStagedRollbackIds) {
414 for (RollbackInfo rollback : rollbacks) {
415 if (rollback.isStaged()) {
416 mPendingStagedRollbackIds.add(rollback.getRollbackId());
417 }
418 }
419 }
420
421 for (RollbackInfo rollback : rollbacks) {
422 VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
423 rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
424 }
425 }
426}
427
即,rollbackPackage是被RollbackPackageHealthObserver.java中的rollbackAll调用的
接下来需要看一下rollbackAll是被谁调用的;
113 public boolean execute(@Nullable VersionedPackage failedPackage,
114 @FailureReasons int rollbackReason) {
115 if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
116 rollbackAll();
117 return true;
118 }
119
120 RollbackInfo rollback = getAvailableRollback(failedPackage);
121 if (rollback == null) {
122 Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage);
123 return false;
124 }
125 rollbackPackage(rollback, failedPackage, rollbackReason);
126 // Assume rollback executed successfully
127 return true;
128 }
即rollbackAll是被RollbackPackageHealthObserver.java的execute方法调用的
接下来需要看一下execute方法是被谁调用的
2.3/frameworks/base/services/core/java/com/android/server/PackageWatchdog.java
416 /**
417 * For native crashes or explicit health check failures, call directly into each observer to
418 * mitigate the error without going through failure threshold logic.
419 */
420 private void handleFailureImmediately(List<VersionedPackage> packages,
421 @FailureReasons int failureReason) {
422 VersionedPackage failingPackage = packages.size() > 0 ? packages.get(0) : null;
423 PackageHealthObserver currentObserverToNotify = null;
424 int currentObserverImpact = Integer.MAX_VALUE;
425 for (ObserverInternal observer: mAllObservers.values()) {
426 PackageHealthObserver registeredObserver = observer.registeredObserver;
427 if (registeredObserver != null) {
428 int impact = registeredObserver.onHealthCheckFailed(
429 failingPackage, failureReason);
430 if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
431 && impact < currentObserverImpact) {
432 currentObserverToNotify = registeredObserver;
433 currentObserverImpact = impact;
434 }
435 }
436 }
437 if (currentObserverToNotify != null) {
438 currentObserverToNotify.execute(failingPackage, failureReason);
439 }
440 }
RollbackPackageHealthObserver 实现了PackageHealthObserver接口;在PackageWatchdog.java中的 handleFailureImmediately方法里,currentObserverToNotify为PackageHealthObserver的实例
即,RollbackPackageHealthObserver.java的execute方法是在PackageWatchdog.java中的 handleFailureImmediately方法中调用的
需要看一下handleFailureImmediately是被谁调用的
这里面我们主要关注的是NATIVE_CRASH
359 /**
360 * Called when a process fails due to a crash, ANR or explicit health check.
361 *
362 * <p>For each package contained in the process, one registered observer with the least user
363 * impact will be notified for mitigation.
364 *
365 * <p>This method could be called frequently if there is a severe problem on the device.
366 */
367 public void onPackageFailure(List<VersionedPackage> packages,
368 @FailureReasons int failureReason) {
369 if (packages == null) {
370 Slog.w(TAG, "Could not resolve a list of failing packages");
371 return;
372 }
373 mLongTaskHandler.post(() -> {
374 synchronized (mLock) {
375 if (mAllObservers.isEmpty()) {
376 return;
377 }
378 boolean requiresImmediateAction = (failureReason == FAILURE_REASON_NATIVE_CRASH
379 || failureReason == FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
380 if (requiresImmediateAction) {
381 handleFailureImmediately(packages, failureReason);
382 } else {
383 for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
384 VersionedPackage versionedPackage = packages.get(pIndex);
385 // Observer that will receive failure for versionedPackage
386 PackageHealthObserver currentObserverToNotify = null;
387 int currentObserverImpact = Integer.MAX_VALUE;
388
389 // Find observer with least user impact
390 for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
391 ObserverInternal observer = mAllObservers.valueAt(oIndex);
392 PackageHealthObserver registeredObserver = observer.registeredObserver;
393 if (registeredObserver != null
394 && observer.onPackageFailureLocked(
395 versionedPackage.getPackageName())) {
396 int impact = registeredObserver.onHealthCheckFailed(
397 versionedPackage, failureReason);
398 if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
399 && impact < currentObserverImpact) {
400 currentObserverToNotify = registeredObserver;
401 currentObserverImpact = impact;
402 }
403 }
404 }
405
406 // Execute action with least user impact
407 if (currentObserverToNotify != null) {
408 currentObserverToNotify.execute(versionedPackage, failureReason);
409 }
410 }
411 }
412 }
413 });
414 }
即 handleFailureImmediately是被PackageWatchdog.java的 onPackageFailure方法调用的
当package failureReason 的原因为Native_Crash和FAILURE_REASON_EXPLICIT_HEALTH_CHECK时,将会立刻对问题进行处理。
需要看一下onPackageFailure是被谁调用的;
503 /**
504 * This method should be only called on mShortTaskHandler, since it modifies
505 * {@link #mNumberOfNativeCrashPollsRemaining}.
506 */
507 private void checkAndMitigateNativeCrashes() {
508 mNumberOfNativeCrashPollsRemaining--;
509 // Check if native watchdog reported a crash
510 if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
511 // We rollback everything available when crash is unattributable
512 onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH);
513 // we stop polling after an attempt to execute rollback, regardless of whether the
514 // attempt succeeds or not
515 } else {
516 if (mNumberOfNativeCrashPollsRemaining > 0) {
517 mShortTaskHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
518 NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
519 }
520 }
521 }
即,onPackageFailure是被PackageWatchdog.java的 checkAndMitigateNativeCrashes方法调用的;
补充:
sys.init.updatable_crashing这个prop是什么?
这个prop是定义在什么地方?
源码位置/system/core/init/
310#endif
311 const bool is_process_updatable = !pre_apexd_ && is_apex_updatable;
312
313 // If we crash > 4 times in 4 minutes or before boot_completed,
314 // reboot into bootloader or set crashing property
315 boot_clock::time_point now = boot_clock::now();
316 if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) {
317 bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
318 if (now < time_crashed_ + 4min || !boot_completed) {
319 if (++crash_count_ > 4) {
320 if (flags_ & SVC_CRITICAL) {
321 // Aborts into bootloader
322 LOG(FATAL) << "critical process '" << name_ << "' exited 4 times "
323 << (boot_completed ? "in 4 minutes" : "before boot completed");
324 } else {
325 LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
326 << (boot_completed ? "in 4 minutes" : "before boot completed");
327 // Notifies update_verifier and apexd
328 SetProperty("sys.init.updatable_crashing_process_name", name_);
329 SetProperty("sys.init.updatable_crashing", "1");
330 }
331 }
332 } else {
333 time_crashed_ = now;
334 crash_count_ = 1;
335 }
336 }
这里其实是对Crash的一个检查,如果在开机以后,规定时间内有四次以上的crash,然后就会触发这个prop的定义。
同时会记录当前进程的名字:sys.init.updatable_crashing_process_name。
需要查看一下checkAndMitigateNativeCrashes是被谁调用的
523 /**
524 * Since this method can eventually trigger a rollback, it should be called
525 * only once boot has completed {@code onBootCompleted} and not earlier, because the install
526 * session must be entirely completed before we try to rollback.
527 */
528 public void scheduleCheckAndMitigateNativeCrashes() {
529 Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
530 + "and mitigate native crashes");
531 mShortTaskHandler.post(()->checkAndMitigateNativeCrashes());
532 }
即,checkAndMitigateNativeCrashes是被PackageWatchdog.java中的scheduleCheckAndMitigateNativeCrashes方法调用的
需要看一下scheduleCheckAndMitigateNativeCrashes是被谁调用的;
2.4/frameworks/base/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
150 private void onBootCompleted() {
151 RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
152 if (!rollbackManager.getAvailableRollbacks().isEmpty()) {
153 // TODO(gavincorkery): Call into Package Watchdog from outside the observer
154 PackageWatchdog.getInstance(mContext).scheduleCheckAndMitigateNativeCrashes();
155 }
156
157 SparseArray<String> rollbackIds = popLastStagedRollbackIds();
158 for (int i = 0; i < rollbackIds.size(); i++) {
159 WatchdogRollbackLogger.logRollbackStatusOnBoot(mContext,
160 rollbackIds.keyAt(i), rollbackIds.valueAt(i),
161 rollbackManager.getRecentlyCommittedRollbacks());
162 }
163 }
即scheduleCheckAndMitigateNativeCrashes是被RollbackPackageHealthObserver.java 中的 onBootCompleted方法调用的
需要看一下onBootCompleted是被谁调用的;
146 public void onBootCompletedAsync() {
147 mHandler.post(()->onBootCompleted());
148 }
onBootCompleted是被RollbackPackageHealthObserver.java 中的onBootCompletedAsync调用的
需要看下onBootCompletedAsync是被谁调用的;
2.5/frameworks/base/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
531 @AnyThread
532 void onBootCompleted() {
533 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
534 mExecutor, properties -> updateRollbackLifetimeDurationInMillis());
535
536 getHandler().post(() -> {
537 updateRollbackLifetimeDurationInMillis();
538 runExpiration();
539
540 // Check to see if any rollback-enabled staged sessions or staged
541 // rollback sessions been applied.
542 List<Rollback> enabling = new ArrayList<>();
543 List<Rollback> restoreInProgress = new ArrayList<>();
544 Set<String> apexPackageNames = new HashSet<>();
545 synchronized (mLock) {
546 Iterator<Rollback> iter = mRollbacks.iterator();
547 while (iter.hasNext()) {
548 Rollback rollback = iter.next();
549 if (!rollback.isStaged()) {
550 // We only care about staged rollbacks here
551 continue;
552 }
553
554 PackageInstaller.SessionInfo session = mContext.getPackageManager()
555 .getPackageInstaller().getSessionInfo(rollback.getStagedSessionId());
556 if (session == null || session.isStagedSessionFailed()) {
557 iter.remove();
558 rollback.delete(mAppDataRollbackHelper);
559 continue;
560 }
561
562 if (session.isStagedSessionApplied()) {
563 if (rollback.isEnabling()) {
564 enabling.add(rollback);
565 } else if (rollback.isRestoreUserDataInProgress()) {
566 restoreInProgress.add(rollback);
567 }
568 }
569 apexPackageNames.addAll(rollback.getApexPackageNames());
570 }
571 }
572
573 for (Rollback rollback : enabling) {
574 makeRollbackAvailable(rollback);
575 }
576
577 for (Rollback rollback : restoreInProgress) {
578 rollback.setRestoreUserDataInProgress(false);
579 }
580
581 for (String apexPackageName : apexPackageNames) {
582 // We will not recieve notifications when an apex is updated,
583 // so check now in case any rollbacks ought to be expired. The
584 // onPackagedReplace function is safe to call if the package
585 // hasn't actually been updated.
586 onPackageReplaced(apexPackageName);
587 }
588
589 synchronized (mLock) {
590 mOrphanedApkSessionIds.clear();
591 }
592
593 mPackageHealthObserver.onBootCompletedAsync();
594 });
595 }
onBootCompletedAsync是被RollbackManagerServiceImpl.java中的onBootCompleted方法调用的
这段主要说的是在系统启动过程中,我们将会对rollback的功能开启,各个session的状态,以及实际的packageName进行replaced,restore userdata的操作
需要看一下onBootCompleted是被谁调用的;
2.6/frameworks/base/services/core/java/com/android/server/rollback/RollbackManagerService.java
23/**
24 * Service that manages APK level rollbacks. Publishes
25 * Context.ROLLBACK_SERVICE.
26 *
27 * @hide
28 */
29public final class RollbackManagerService extends SystemService {
30
31 private RollbackManagerServiceImpl mService;
32
33 public RollbackManagerService(Context context) {
34 super(context);
35 }
36
37 @Override
38 public void onStart() {
39 mService = new RollbackManagerServiceImpl(getContext());
40 publishBinderService(Context.ROLLBACK_SERVICE, mService);
41 }
42
43 @Override
44 public void onUnlockUser(int user) {
45 mService.onUnlockUser(user);
46 }
47
48 @Override
49 public void onBootPhase(int phase) {
50 if (phase == SystemService.PHASE_BOOT_COMPLETED) {
51 mService.onBootCompleted();
52 }
53 }
54}
即onBootCompleted是被RollbackManagerService.java中的onBootPhase方法调用的
可以看到的是,在PHASE_BOOT_COMPLETED时,将会调用onBootCompleted的函数,这个函数是在系统启动完成后,针对全局发出的通知
3.总结(Rollback的调用流程)
上面的流程分析是倒着来的,通过重启的log来看rollback的流程,下面的是正向的流程:
RollbackManagerService.java的onBootPhase()
–>RollbackManagerServiceImpl.java的onBootCompleted()
–>RollbackPackageHealthObserver.java的onBootCompletedAsync()–>onBootCompleted()
–>PackageWatchdog.java的scheduleCheckAndMitigateNativeCrashes()–>checkAndMitigateNativeCrashes()–>onPackageFailure()–>handleFailureImmediately
–>RollbackPackageHealthObserver.java的execute()–>rollbackAll()–>rollbackPackage–>handleStagedSessionChange()