RollCallBack机制及原理

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值