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

Commit da73d553 authored by Keun young Park's avatar Keun young Park
Browse files

Add unit test for BackgroundDexOptService

- cleaned up DexOptHeler inside service to allow easier testing

Bug: 156537504
Test: run the added test
      atest com.android.server.pm.BackgroundDexOptServiceUnitTest
Change-Id: Ie44d79498e71d429f927a5f8301aa38894ab33bf
parent 26951518
Loading
Loading
Loading
Loading
+45 −43
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ public final class BackgroundDexOptService {

    private final Injector mInjector;

    private final DexOptHelper mDexOptHelper;

    private final Object mLock = new Object();

    // Thread currently running dexopt. This will be null if dexopt is not running.
@@ -168,13 +170,15 @@ public final class BackgroundDexOptService {
        void onPackagesUpdated(ArraySet<String> updatedPackages);
    }

    public BackgroundDexOptService(Context context, DexManager dexManager) {
        this(new Injector(context, dexManager));
    public BackgroundDexOptService(Context context, DexManager dexManager,
            PackageManagerService pm) {
        this(new Injector(context, dexManager, pm));
    }

    @VisibleForTesting
    public BackgroundDexOptService(Injector injector) {
        mInjector = injector;
        mDexOptHelper = mInjector.getDexOptHelper();
        LocalServices.addService(BackgroundDexOptService.class, this);
        mDowngradeUnusedAppsThresholdInMillis = mInjector.getDowngradeUnusedAppsThresholdInMillis();
    }
@@ -251,15 +255,13 @@ public final class BackgroundDexOptService {
                resetStatesForNewDexOptRunLocked(Thread.currentThread());
            }
            PackageManagerService pm = mInjector.getPackageManagerService();
            DexOptHelper dexOptHelper = new DexOptHelper(pm);
            ArraySet<String> packagesToOptimize;
            if (packageNames == null) {
                packagesToOptimize = dexOptHelper.getOptimizablePackages();
                packagesToOptimize = mDexOptHelper.getOptimizablePackages();
            } else {
                packagesToOptimize = new ArraySet<>(packageNames);
            }
            return runIdleOptimization(pm, dexOptHelper, packagesToOptimize,
                    /* isPostBootUpdate= */ false);
            return runIdleOptimization(pm, packagesToOptimize, /* isPostBootUpdate= */ false);
        } finally {
            Binder.restoreCallingIdentity(identity);
            markDexOptCompleted();
@@ -320,8 +322,7 @@ public final class BackgroundDexOptService {
            return false;
        }

        DexOptHelper dexOptHelper = new DexOptHelper(pm);
        ArraySet<String> pkgs = dexOptHelper.getOptimizablePackages();
        ArraySet<String> pkgs = mDexOptHelper.getOptimizablePackages();
        if (pkgs.isEmpty()) {
            Slog.i(TAG, "No packages to optimize");
            markPostBootUpdateCompleted(params);
@@ -347,7 +348,7 @@ public final class BackgroundDexOptService {
                        tr.traceBegin("jobExecution");
                        boolean completed = false;
                        try {
                            completed = runIdleOptimization(pm, dexOptHelper, pkgs,
                            completed = runIdleOptimization(pm, pkgs,
                                    params.getJobId() == JOB_POST_BOOT_UPDATE);
                        } finally { // Those cleanup should be done always.
                            tr.traceEnd();
@@ -461,7 +462,7 @@ public final class BackgroundDexOptService {
    @GuardedBy("mLock")
    private void controlDexOptBlockingLocked(boolean block) {
        PackageManagerService pm = mInjector.getPackageManagerService();
        new DexOptHelper(pm).controlDexOptBlocking(block);
        mDexOptHelper.controlDexOptBlocking(block);
    }

    private void scheduleAJob(int jobId) {
@@ -511,10 +512,10 @@ public final class BackgroundDexOptService {
    }

    /** Returns true if completed */
    private boolean runIdleOptimization(PackageManagerService pm, DexOptHelper dexOptHelper,
            ArraySet<String> pkgs, boolean isPostBootUpdate) {
    private boolean runIdleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
            boolean isPostBootUpdate) {
        long lowStorageThreshold = getLowStorageThreshold();
        int status = idleOptimizePackages(pm, dexOptHelper, pkgs, lowStorageThreshold,
        int status = idleOptimizePackages(pm, pkgs, lowStorageThreshold,
                isPostBootUpdate);
        logStatus(status);
        synchronized (mLock) {
@@ -562,8 +563,8 @@ public final class BackgroundDexOptService {
    }

    @Status
    private int idleOptimizePackages(PackageManagerService pm, DexOptHelper dexOptHelper,
            ArraySet<String> pkgs, long lowStorageThreshold, boolean isPostBootUpdate) {
    private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
            long lowStorageThreshold, boolean isPostBootUpdate) {
        ArraySet<String> updatedPackages = new ArraySet<>();
        ArraySet<String> updatedPackagesDueToSecondaryDex = new ArraySet<>();

@@ -600,7 +601,7 @@ public final class BackgroundDexOptService {
                            // Should be aborted by the scheduler.
                            return abortCode;
                        }
                        @DexOptResult int downgradeResult = downgradePackage(pm, dexOptHelper, pkg,
                        @DexOptResult int downgradeResult = downgradePackage(pm, pkg,
                                /* isForPrimaryDex= */ true, isPostBootUpdate);
                        if (downgradeResult == PackageDexOptimizer.DEX_OPT_PERFORMED) {
                            updatedPackages.add(pkg);
@@ -611,7 +612,7 @@ public final class BackgroundDexOptService {
                            return status;
                        }
                        if (supportSecondaryDex) {
                            downgradeResult = downgradePackage(pm, dexOptHelper, pkg,
                            downgradeResult = downgradePackage(pm, pkg,
                                    /* isForPrimaryDex= */false, isPostBootUpdate);
                            status = convertPackageDexOptimizerStatusToInternal(downgradeResult);
                            if (status != STATUS_OK) {
@@ -625,9 +626,8 @@ public final class BackgroundDexOptService {
                }
            }

            @Status int primaryResult = optimizePackages(dexOptHelper, pkgs,
                    lowStorageThreshold, /*isForPrimaryDex=*/ true, updatedPackages,
                    isPostBootUpdate);
            @Status int primaryResult = optimizePackages(pkgs, lowStorageThreshold,
                    /*isForPrimaryDex=*/ true, updatedPackages, isPostBootUpdate);
            if (primaryResult != STATUS_OK) {
                return primaryResult;
            }
@@ -636,9 +636,9 @@ public final class BackgroundDexOptService {
                return STATUS_OK;
            }

            @Status int secondaryResult = optimizePackages(dexOptHelper, pkgs,
                    lowStorageThreshold, /*isForPrimaryDex*/ false,
                    updatedPackagesDueToSecondaryDex, isPostBootUpdate);
            @Status int secondaryResult = optimizePackages(pkgs, lowStorageThreshold,
                    /*isForPrimaryDex*/ false, updatedPackagesDueToSecondaryDex,
                    isPostBootUpdate);
            return secondaryResult;
        } finally {
            // Always let the pinner service know about changes.
@@ -651,9 +651,8 @@ public final class BackgroundDexOptService {
    }

    @Status
    private int optimizePackages(DexOptHelper dexOptHelper,
            ArraySet<String> pkgs, long lowStorageThreshold, boolean isForPrimaryDex,
            ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
    private int optimizePackages(ArraySet<String> pkgs, long lowStorageThreshold,
            boolean isForPrimaryDex, ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
        for (String pkg : pkgs) {
            int abortCode = abortIdleOptimizations(lowStorageThreshold);
            if (abortCode != STATUS_OK) {
@@ -661,8 +660,7 @@ public final class BackgroundDexOptService {
                return abortCode;
            }

            @DexOptResult int result = optimizePackage(dexOptHelper, pkg, isForPrimaryDex,
                    isPostBootUpdate);
            @DexOptResult int result = optimizePackage(pkg, isForPrimaryDex, isPostBootUpdate);
            if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
                updatedPackages.add(pkg);
            } else if (result != PackageDexOptimizer.DEX_OPT_SKIPPED) {
@@ -681,8 +679,8 @@ public final class BackgroundDexOptService {
     * @return PackageDexOptimizer.DEX_*
     */
    @DexOptResult
    private int downgradePackage(PackageManagerService pm, DexOptHelper dexOptHelper, String pkg,
            boolean isForPrimaryDex, boolean isPostBootUpdate) {
    private int downgradePackage(PackageManagerService pm, String pkg, boolean isForPrimaryDex,
            boolean isPostBootUpdate) {
        if (DEBUG) {
            Slog.d(TAG, "Downgrading " + pkg);
        }
@@ -704,10 +702,10 @@ public final class BackgroundDexOptService {
                // remove their compiler artifacts from dalvik cache.
                pm.deleteOatArtifactsOfPackage(pkg);
            } else {
                result = performDexOptPrimary(dexOptHelper, pkg, reason, dexoptFlags);
                result = performDexOptPrimary(pkg, reason, dexoptFlags);
            }
        } else {
            result = performDexOptSecondary(dexOptHelper, pkg, reason, dexoptFlags);
            result = performDexOptSecondary(pkg, reason, dexoptFlags);
        }

        if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -733,15 +731,13 @@ public final class BackgroundDexOptService {
     *
     * Optimize package if needed. Note that there can be no race between
     * concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
     * @param dexOptHelper An instance of DexOptHelper
     * @param pkg The package to be downgraded.
     * @param isForPrimaryDex Apps can have several dex file, primary and secondary.
     * @param isPostBootUpdate is post boot update or not.
     * @return PackageDexOptimizer#DEX_OPT_*
     */
    @DexOptResult
    private int optimizePackage(DexOptHelper dexOptHelper, String pkg,
            boolean isForPrimaryDex, boolean isPostBootUpdate) {
    private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) {
        int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT
                : PackageManagerService.REASON_BACKGROUND_DEXOPT;
        int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE;
@@ -753,27 +749,27 @@ public final class BackgroundDexOptService {
        // System server share the same code path as primary dex files.
        // PackageManagerService will select the right optimization path for it.
        if (isForPrimaryDex || PLATFORM_PACKAGE_NAME.equals(pkg)) {
            return performDexOptPrimary(dexOptHelper, pkg, reason, dexoptFlags);
            return performDexOptPrimary(pkg, reason, dexoptFlags);
        } else {
            return performDexOptSecondary(dexOptHelper, pkg, reason, dexoptFlags);
            return performDexOptSecondary(pkg, reason, dexoptFlags);
        }
    }

    @DexOptResult
    private int performDexOptPrimary(DexOptHelper dexOptHelper, String pkg, int reason,
    private int performDexOptPrimary(String pkg, int reason,
            int dexoptFlags) {
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/ true,
                () -> dexOptHelper.performDexOptWithStatus(
                () -> mDexOptHelper.performDexOptWithStatus(
                        new DexoptOptions(pkg, reason, dexoptFlags)));
    }

    @DexOptResult
    private int performDexOptSecondary(DexOptHelper dexOptHelper, String pkg, int reason,
    private int performDexOptSecondary(String pkg, int reason,
            int dexoptFlags) {
        DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason,
                dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX);
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/ false,
                () -> dexOptHelper.performDexOpt(dexoptOptions)
                () -> mDexOptHelper.performDexOpt(dexoptOptions)
                    ? PackageDexOptimizer.DEX_OPT_PERFORMED : PackageDexOptimizer.DEX_OPT_FAILED
        );
    }
@@ -911,11 +907,13 @@ public final class BackgroundDexOptService {
    static final class Injector {
        private final Context mContext;
        private final DexManager mDexManager;
        private final PackageManagerService mPackageManagerService;
        private final File mDataDir = Environment.getDataDirectory();

        Injector(Context context, DexManager dexManager) {
        Injector(Context context, DexManager dexManager, PackageManagerService pm) {
            mContext = context;
            mDexManager = dexManager;
            mPackageManagerService = pm;
        }

        Context getContext() {
@@ -923,7 +921,11 @@ public final class BackgroundDexOptService {
        }

        PackageManagerService getPackageManagerService() {
            return (PackageManagerService) ServiceManager.getService("package");
            return mPackageManagerService;
        }

        DexOptHelper getDexOptHelper() {
            return new DexOptHelper(getPackageManagerService());
        }

        JobScheduler getJobScheduler() {
+1 −1
Original line number Diff line number Diff line
@@ -1487,7 +1487,7 @@ public class PackageManagerService extends IPackageManager.Stub
                new DefaultSystemWrapper(),
                LocalServices::getService,
                context::getSystemService,
                (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager()));
                (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm));

        if (Build.VERSION.SDK_INT <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
+480 −0

File added.

Preview size limit exceeded, changes collapsed.