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

Commit 74f8d199 authored by Martin Stjernholm's avatar Martin Stjernholm Committed by Android (Google) Code Review
Browse files

Merge changes from topic "reason-boot-after-ml"

* changes:
  Align the boot dexopt pass in the legacy code with ART Service.
  Clean up old code that only applied to upgrades from Android older than N.
  Break out the legacy to ART Service reason conversion code.
  Give access to the DexOptHelper object in the onDexoptDone callback.
  Use ART Service to clear app profiles when it is enabled.
parents 12917797 f4e855bd
Loading
Loading
Loading
Loading
+31 −12
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;

import android.annotation.NonNull;
@@ -586,13 +587,16 @@ public class AppDataHelper {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        // TODO(b/251903639): Call into ART Service.
        if (useArtService()) {
            destroyAppProfilesWithArtService(pkg);
        } else {
            try {
                mArtManagerService.clearAppProfiles(pkg);
            } catch (LegacyDexoptDisabledException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) {
        if (pkg == null) {
@@ -629,7 +633,9 @@ public class AppDataHelper {
    }

    private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
        // TODO(b/251903639): Call into ART Service.
        if (useArtService()) {
            destroyAppProfilesWithArtService(pkg);
        } else {
            try {
                mInstaller.destroyAppProfiles(pkg.getPackageName());
            } catch (LegacyDexoptDisabledException e) {
@@ -638,6 +644,19 @@ public class AppDataHelper {
                Slog.w(TAG, String.valueOf(e));
            }
        }
    }

    private void destroyAppProfilesWithArtService(AndroidPackage pkg) {
        try (PackageManagerLocal.FilteredSnapshot snapshot =
                        getPackageManagerLocal().withFilteredSnapshot()) {
            try {
                DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, pkg.getPackageName());
            } catch (IllegalArgumentException e) {
                // Package isn't found, but that should only happen due to race.
                Slog.w(TAG, e);
            }
        }
    }

    /**
     * Returns {@code true} if app's internal storage should be created for this {@code pkg}.
+26 −66
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.server.pm.ApexManager.ActiveApexInfo;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_MAINLINE_UPDATE;
import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_OTA;
import static com.android.server.pm.PackageManagerService.REASON_CMDLINE;
import static com.android.server.pm.PackageManagerService.REASON_FIRST_BOOT;
@@ -36,11 +37,8 @@ import static com.android.server.pm.PackageManagerServiceUtils.getPackageManager

import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.Context;
import android.content.Intent;
@@ -53,14 +51,11 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.server.LocalManagerRegistry;
import com.android.server.art.ArtManagerLocal;
@@ -86,7 +81,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -100,18 +94,6 @@ public final class DexOptHelper {

    private final PackageManagerService mPm;

    public boolean isDexOptDialogShown() {
        synchronized (mLock) {
            return mDexOptDialogShown;
        }
    }

    // TODO: Is this lock really necessary?
    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private boolean mDexOptDialogShown;

    DexOptHelper(PackageManagerService pm) {
        mPm = pm;
    }
@@ -129,7 +111,7 @@ public final class DexOptHelper {
     * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
     * and {@code numberOfPackagesFailed}.
     */
    public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog,
    public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates,
            final int compilationReason, boolean bootComplete)
            throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
@@ -221,18 +203,6 @@ public final class DexOptHelper {
                        + numberOfPackagesToDexopt + ": " + pkg.getPackageName());
            }

            if (showDialog) {
                try {
                    ActivityManager.getService().showBootMessage(
                            mPm.mContext.getResources().getString(R.string.android_upgrading_apk,
                                    numberOfPackagesVisited, numberOfPackagesToDexopt), true);
                } catch (RemoteException e) {
                }
                synchronized (mLock) {
                    mDexOptDialogShown = true;
                }
            }

            int pkgCompilationReason = compilationReason;
            if (useProfileForDexopt) {
                // Use background dexopt mode to try and use the profile. Note that this does not
@@ -290,7 +260,7 @@ public final class DexOptHelper {
     * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and
     * compiles it if needed.
     */
    private void checkAndDexOptSystemUi() throws LegacyDexoptDisabledException {
    private void checkAndDexOptSystemUi(int reason) throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        Computer snapshot = mPm.snapshotComputer();
        String sysUiPackageName =
@@ -301,10 +271,6 @@ public final class DexOptHelper {
            return;
        }

        // It could also be after mainline update, but we're not introducing a new reason just for
        // this special case.
        int reason = REASON_BOOT_AFTER_OTA;

        String defaultCompilerFilter = getCompilerFilterForReason(reason);
        String targetCompilerFilter =
                SystemProperties.get("dalvik.vm.systemuicompilerfilter", defaultCompilerFilter);
@@ -347,29 +313,30 @@ public final class DexOptHelper {
                compilerFilter, null /* splitName */, dexoptFlags));
    }

    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
    /**
     * Called during startup to do any boot time dexopting. This can occasionally be time consuming
     * (30+ seconds) and the function will block until it is complete.
     */
    public void performPackageDexOptUpgradeIfNeeded() throws LegacyDexoptDisabledException {
        PackageManagerServiceUtils.enforceSystemOrRoot(
                "Only the system can request package update");

        // The default is "true".
        if (!"false".equals(DeviceConfig.getProperty("runtime", "dexopt_system_ui_on_boot"))) {
            // System UI is important to user experience, so we check it after a mainline update or
            // an OTA. It may need to be re-compiled in these cases.
            if (hasBcpApexesChanged() || mPm.isDeviceUpgrading()) {
                checkAndDexOptSystemUi();
            }
        int reason;
        if (mPm.isFirstBoot()) {
            reason = REASON_FIRST_BOOT; // First boot or factory reset.
        } else if (mPm.isDeviceUpgrading()) {
            reason = REASON_BOOT_AFTER_OTA;
        } else if (hasBcpApexesChanged()) {
            reason = REASON_BOOT_AFTER_MAINLINE_UPDATE;
        } else {
            return;
        }

        // We need to re-extract after an OTA.
        boolean causeUpgrade = mPm.isDeviceUpgrading();

        // First boot or factory reset.
        // Note: we also handle devices that are upgrading to N right now as if it is their
        //       first boot, as they do not have profile data.
        boolean causeFirstBoot = mPm.isFirstBoot() || mPm.isPreNUpgrade();
        // System UI is important to user experience, so we check it after a mainline update
        // or an OTA. It may need to be re-compiled in these cases.
        checkAndDexOptSystemUi(reason);

        if (!causeUpgrade && !causeFirstBoot) {
        if (reason != REASON_BOOT_AFTER_OTA && reason != REASON_FIRST_BOOT) {
            return;
        }

@@ -378,9 +345,7 @@ public final class DexOptHelper {
                getPackagesForDexopt(snapshot.getPackageStates().values(), mPm);

        final long startTime = System.nanoTime();
        final int[] stats = performDexOptUpgrade(pkgSettings, mPm.isPreNUpgrade() /* showDialog */,
                causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT_AFTER_OTA,
                false /* bootComplete */);
        final int[] stats = performDexOptUpgrade(pkgSettings, reason, false /* bootComplete */);

        final int elapsedTimeSeconds =
                (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
@@ -946,13 +911,10 @@ public final class DexOptHelper {
        }
    }

    private static class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
        @NonNull private final PackageManagerService mPm;

        DexoptDoneHandler(@NonNull PackageManagerService pm) { mPm = pm; }

    private class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
        /**
         * Called after every package dexopt operation done by {@link ArtManagerLocal}.
         * Called after every package dexopt operation done by {@link ArtManagerLocal} (when ART
         * Service is in use).
         */
        @Override
        public void onDexoptDone(@NonNull DexoptResult result) {
@@ -983,10 +945,8 @@ public final class DexOptHelper {
        }

        ArtManagerLocal artManager = new ArtManagerLocal(systemContext);
        // There doesn't appear to be any checks that @NonNull is heeded, so use requireNonNull
        // below to ensure we don't store away a null that we'll fail on later.
        artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */,
                Runnable::run, new DexoptDoneHandler(Objects.requireNonNull(pm)));
        artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */, Runnable::run,
                pm.getDexOptHelper().new DexoptDoneHandler());
        LocalManagerRegistry.addManager(ArtManagerLocal.class, artManager);

        artManager.scheduleBackgroundDexoptJob();
+13 −18
Original line number Diff line number Diff line
@@ -552,6 +552,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    private static final int REQUIRED_VERIFIERS_MAX_COUNT = 2;

    // Compilation reasons.
    // TODO(b/260124949): Clean this up with the legacy dexopt code.
    public static final int REASON_FIRST_BOOT = 0;
    public static final int REASON_BOOT_AFTER_OTA = 1;
    public static final int REASON_POST_BOOT = 2;
@@ -565,7 +566,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    public static final int REASON_AB_OTA = 10;
    public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 11;
    public static final int REASON_CMDLINE = 12;
    public static final int REASON_SHARED = 13;
    public static final int REASON_BOOT_AFTER_MAINLINE_UPDATE = 13;
    public static final int REASON_SHARED = 14;

    public static final int REASON_LAST = REASON_SHARED;

@@ -588,7 +590,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    private final int mDefParseFlags;
    private final String[] mSeparateProcesses;
    private final boolean mIsUpgrade;
    private final boolean mIsPreNUpgrade;
    private final boolean mIsPreNMR1Upgrade;
    private final boolean mIsPreQUpgrade;

@@ -1734,7 +1735,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        mInstantAppResolverConnection = testParams.instantAppResolverConnection;
        mInstantAppResolverSettingsComponent = testParams.instantAppResolverSettingsComponent;
        mIsPreNMR1Upgrade = testParams.isPreNmr1Upgrade;
        mIsPreNUpgrade = testParams.isPreNupgrade;
        mIsPreQUpgrade = testParams.isPreQupgrade;
        mIsUpgrade = testParams.isUpgrade;
        mMetrics = testParams.Metrics;
@@ -2069,10 +2069,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            mPromoteSystemApps =
                    mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

            // When upgrading from pre-N, we need to handle package extraction like first boot,
            // as there is no profiling data available.
            mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

            mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
            mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;

@@ -2954,15 +2950,14 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                }
                if (doTrim) {
                    if (!isFirstBoot()) {
                        if (mDexOptHelper.isDexOptDialogShown()) {
                        try {
                            ActivityManager.getService().showBootMessage(
                                    mContext.getResources().getString(
                                                R.string.android_upgrading_fstrim), true);
                                            R.string.android_upgrading_fstrim),
                                    true);
                        } catch (RemoteException e) {
                        }
                    }
                    }
                    sm.runMaintenance();
                }
            } else {
@@ -2997,6 +2992,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        return mDexManager;
    }

    /*package*/ DexOptHelper getDexOptHelper() {
        return mDexOptHelper;
    }

    /*package*/ DynamicCodeLogger getDynamicCodeLogger() {
        return mDynamicCodeLogger;
    }
@@ -7476,10 +7475,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        return mPlatformPackage;
    }

    boolean isPreNUpgrade() {
        return mIsPreNUpgrade;
    }

    boolean isPreNMR1Upgrade() {
        return mIsPreNMR1Upgrade;
    }
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ public class PackageManagerServiceCompilerMapping {
        "ab-ota",
        "inactive",
        "cmdline",
        "boot-after-mainline-update",
        // "shared" must be the last entry
        "shared"
    };
+0 −1
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ public final class PackageManagerServiceTestParams {
    public InstantAppResolverConnection instantAppResolverConnection;
    public ComponentName instantAppResolverSettingsComponent;
    public boolean isPreNmr1Upgrade;
    public boolean isPreNupgrade;
    public boolean isPreQupgrade;
    public boolean isUpgrade;
    public LegacyPermissionManagerInternal legacyPermissionManagerInternal;
Loading