Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7726744 authored by Gavin Corkery's avatar Gavin Corkery Committed by Android (Google) Code Review
Browse files

Merge "Attach logging package to staged rollback IDs"

parents d14cdd18 a3f2f6c7
Loading
Loading
Loading
Loading
+40 −28
Original line number Diff line number Diff line
@@ -36,9 +36,9 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FrameworkStatsLog;
@@ -56,9 +56,7 @@ import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@@ -156,12 +154,11 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
            PackageWatchdog.getInstance(mContext).scheduleCheckAndMitigateNativeCrashes();
        }

        List<Integer> rollbackIds = popLastStagedRollbackIds();
        Iterator<Integer> rollbackIterator = rollbackIds.iterator();
        while (rollbackIterator.hasNext()) {
            int rollbackId = rollbackIterator.next();
            WatchdogRollbackLogger.logRollbackStatusOnBoot(
                    mContext, rollbackId, rollbackManager.getRecentlyCommittedRollbacks());
        SparseArray<String> rollbackIds = popLastStagedRollbackIds();
        for (int i = 0; i < rollbackIds.size(); i++) {
            WatchdogRollbackLogger.logRollbackStatusOnBoot(mContext,
                    rollbackIds.keyAt(i), rollbackIds.valueAt(i),
                    rollbackManager.getRecentlyCommittedRollbacks());
        }
    }

@@ -224,7 +221,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
                        packageInstaller.getSessionInfo(sessionId);
                if (sessionInfo.isStagedSessionReady() && markStagedSessionHandled(rollbackId)) {
                    mContext.unregisterReceiver(listener);
                    saveStagedRollbackId(rollbackId);
                    saveStagedRollbackId(rollbackId, logPackage);
                    WatchdogRollbackLogger.logEvent(logPackage,
                            FrameworkStatsLog
                            .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
@@ -268,39 +265,54 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
        }
    }

    private void saveStagedRollbackId(int stagedRollbackId) {
    private void saveStagedRollbackId(int stagedRollbackId, @Nullable VersionedPackage logPackage) {
        writeStagedRollbackId(mLastStagedRollbackIdsFile, stagedRollbackId, logPackage);
    }

    static void writeStagedRollbackId(File file, int stagedRollbackId,
            @Nullable VersionedPackage logPackage) {
        try {
            FileOutputStream fos = new FileOutputStream(
                    mLastStagedRollbackIdsFile, /*append*/true);
            FileOutputStream fos = new FileOutputStream(file, true);
            PrintWriter pw = new PrintWriter(fos);
            pw.append(",").append(String.valueOf(stagedRollbackId));
            String logPackageName = logPackage != null ? logPackage.getPackageName() : "";
            pw.append(String.valueOf(stagedRollbackId)).append(",").append(logPackageName);
            pw.println();
            pw.flush();
            FileUtils.sync(fos);
            pw.close();
        } catch (IOException e) {
            Slog.e(TAG, "Failed to save last staged rollback id", e);
            mLastStagedRollbackIdsFile.delete();
            file.delete();
        }
    }

    private List<Integer> popLastStagedRollbackIds() {
        try (BufferedReader reader =
                     new BufferedReader(new FileReader(mLastStagedRollbackIdsFile))) {
            String line = reader.readLine();
            // line is of format : ",id1,id2,id3....,idn"
            String[] sessionIdsStr = line.split(",");
            ArrayList<Integer> result = new ArrayList<>();
            for (String sessionIdStr: sessionIdsStr) {
                if (!TextUtils.isEmpty(sessionIdStr.trim())) {
                    result.add(Integer.parseInt(sessionIdStr));
    private SparseArray<String> popLastStagedRollbackIds() {
        try {
            return readStagedRollbackIds(mLastStagedRollbackIdsFile);
        } finally {
            mLastStagedRollbackIdsFile.delete();
        }
    }
            return result;

    static SparseArray<String> readStagedRollbackIds(File file) {
        SparseArray<String> result = new SparseArray<>();
        try {
            String line;
            BufferedReader reader = new BufferedReader(new FileReader(file));
            while ((line = reader.readLine()) != null) {
                // Each line is of the format: "id,logging_package"
                String[] values = line.trim().split(",");
                String rollbackId = values[0];
                String logPackageName = "";
                if (values.length > 1) {
                    logPackageName = values[1];
                }
                result.put(Integer.parseInt(rollbackId), logPackageName);
            }
        } catch (Exception ignore) {
            return Collections.emptyList();
        } finally {
            mLastStagedRollbackIdsFile.delete();
            return new SparseArray<>();
        }
        return result;
    }


+17 −33
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;

@@ -43,7 +44,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.PackageWatchdog;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@@ -115,7 +115,7 @@ public final class WatchdogRollbackLogger {
    }


    static void logRollbackStatusOnBoot(Context context, int rollbackId,
    static void logRollbackStatusOnBoot(Context context, int rollbackId, String logPackageName,
            List<RollbackInfo> recentlyCommittedRollbacks) {
        PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();

@@ -132,23 +132,15 @@ public final class WatchdogRollbackLogger {
            return;
        }

        // Identify the logging parent for this rollback. When all configurations are correct,
        // each package in the rollback has a logging parent set in metadata.
        final Set<String> loggingPackageNames = new ArraySet<>();
        for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
            final String loggingParentName = getLoggingParentName(context,
                    packageRollback.getPackageName());
            if (loggingParentName != null) {
                loggingPackageNames.add(loggingParentName);
            }
        }

        // Use the version of the logging parent that was installed before
        // we rolled back for logging purposes.
        final List<VersionedPackage> oldLoggingPackages = new ArrayList<>();
        VersionedPackage oldLoggingPackage = null;
        if (!TextUtils.isEmpty(logPackageName)) {
            for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
            if (loggingPackageNames.contains(packageRollback.getPackageName())) {
                oldLoggingPackages.add(packageRollback.getVersionRolledBackFrom());
                if (logPackageName.equals(packageRollback.getPackageName())) {
                    oldLoggingPackage = packageRollback.getVersionRolledBackFrom();
                    break;
                }
            }
        }

@@ -159,13 +151,6 @@ public final class WatchdogRollbackLogger {
            return;
        }

        // If no logging packages are found, use a null package to ensure the rollback status
        // is still logged.
        if (oldLoggingPackages.isEmpty()) {
            oldLoggingPackages.add(null);
        }

        for (VersionedPackage oldLoggingPackage : oldLoggingPackages) {
        if (sessionInfo.isStagedSessionApplied()) {
            logEvent(oldLoggingPackage,
                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
@@ -176,7 +161,6 @@ public final class WatchdogRollbackLogger {
                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
        }
    }
    }

    /**
     * Logs that one or more apexd reverts have occurred, along with the crashing native process
+21 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
import android.content.pm.PackageManagerInternal;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;

@@ -432,6 +433,26 @@ public class RollbackUnitTest {
        return result;
    }

    @Test
    public void readAndWriteStagedRollbackIdsFile() throws Exception {
        File testFile = File.createTempFile("test", ".txt");
        RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 2468, null);
        RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 12345,
                new VersionedPackage("com.test.package", 1));
        RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 13579,
                new VersionedPackage("com.test.package2", 2));
        SparseArray<String> readInfo =
                RollbackPackageHealthObserver.readStagedRollbackIds(testFile);
        assertThat(readInfo.size()).isEqualTo(3);

        assertThat(readInfo.keyAt(0)).isEqualTo(2468);
        assertThat(readInfo.valueAt(0)).isEqualTo("");
        assertThat(readInfo.keyAt(1)).isEqualTo(12345);
        assertThat(readInfo.valueAt(1)).isEqualTo("com.test.package");
        assertThat(readInfo.keyAt(2)).isEqualTo(13579);
        assertThat(readInfo.valueAt(2)).isEqualTo("com.test.package2");
    }

    private static PackageRollbackInfo newPkgInfoFor(
            String packageName, long fromVersion, long toVersion, boolean isApex) {
        return new PackageRollbackInfo(new VersionedPackage(packageName, fromVersion),