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

Commit 0fe49450 authored by Andreas Gampe's avatar Andreas Gampe Committed by Android (Google) Code Review
Browse files

Merge "Frameworks/base: OtaDexopt needs to move artifacts on boot" into nyc-dev

parents 556b3226 abcbe2f6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -203,6 +203,11 @@ public final class Installer extends SystemService {
        mInstaller.execute("linkfile", relativePath, fromBase, toBase);
    }

    public void moveAb(String apkPath, String instructionSet, String outputPath)
            throws InstallerException {
        mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
    }

    private static void assertValidInstructionSet(String instructionSet)
            throws InstallerException {
        for (String abi : Build.SUPPORTED_ABIS) {
+50 −25
Original line number Diff line number Diff line
@@ -16,36 +16,28 @@

package com.android.server.pm;

import android.app.AppGlobals;
import static com.android.server.pm.Installer.DEXOPT_OTA;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;

import android.content.Context;
import android.content.Intent;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
import android.content.pm.ResolveInfo;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import dalvik.system.DexFile;
import com.android.internal.os.InstallerConnection.InstallerException;

import java.io.File;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import static com.android.server.pm.Installer.DEXOPT_OTA;

/**
 * A service for A/B OTA dexopting.
@@ -70,6 +62,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
        // Use the package manager install and install lock here for the OTA dex optimizer.
        mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
                packageManagerService.mInstallLock, context);

        // Now it's time to check whether we need to move any A/B artifacts.
        moveAbArtifacts(packageManagerService.mInstaller);
    }

    public static OtaDexoptService main(Context context,
@@ -150,20 +145,50 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
                false /* extractOnly */);
    }

    private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
        List<ResolveInfo> ris = null;
    private void moveAbArtifacts(Installer installer) {
        if (mDexoptPackages != null) {
            throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
        }

        // Look into all packages.
        Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
        for (PackageParser.Package pkg : pkgs) {
            if (pkg == null) {
                continue;
            }

            // Does the package have code? If not, there won't be any artifacts.
            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
                continue;
            }
            if (pkg.codePath == null) {
                Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
                continue;
            }

            // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
            // /data/ota and moved into the dalvik-cache already.
            if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
                continue;
            }

            final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
            final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
            final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
            for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                for (String path : paths) {
                    String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
                            getAbsolutePath();

                    // TODO: Check first whether there is an artifact, to save the roundtrip time.

                    try {
            ris = AppGlobals.getPackageManager().queryIntentReceivers(
                    intent, null, 0, userId);
        } catch (RemoteException e) {
                        installer.moveAb(path, dexCodeInstructionSet, oatDir);
                    } catch (InstallerException e) {
                    }
                }
        ArraySet<String> pkgNames = new ArraySet<String>(ris == null ? 0 : ris.size());
        if (ris != null) {
            for (ResolveInfo ri : ris) {
                pkgNames.add(ri.activityInfo.packageName);
            }
        }
        return pkgNames;
    }

    private static class OTADexoptPackageDexOptimizer extends
+10 −0
Original line number Diff line number Diff line
@@ -19209,4 +19209,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
    boolean isHistoricalPackageUsageAvailable() {
        return mPackageUsage.isHistoricalPackageUsageAvailable();
    }
    /**
     * Return a <b>copy</b> of the collection of packages known to the package manager.
     * @return A copy of the values of mPackages.
     */
    Collection<PackageParser.Package> getPackages() {
        synchronized (mPackages) {
            return new ArrayList<>(mPackages.values());
        }
    }
}
+18 −13
Original line number Diff line number Diff line
@@ -431,6 +431,24 @@ public final class SystemServer {
        mPackageManager = mSystemContext.getPackageManager();
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

        // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
        // A/B artifacts after boot, before anything else might touch/need them.
        // Note: this isn't needed during decryption (we don't have /data anyways).
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                traceBeginAndSlog("StartOtaDexOptService");
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {
                    reportWtf("starting OtaDexOptService", e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                }
            }
        }

        traceBeginAndSlog("StartUserManagerService");
        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -1124,19 +1142,6 @@ public final class SystemServer {
                    reportWtf("starting BackgroundDexOptService", e);
                }
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

                // Manages A/B OTA dexopting.
                boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                        false);
                if (!disableOtaDexopt) {
                    traceBeginAndSlog("StartOtaDexOptService");
                    try {
                        OtaDexoptService.main(mSystemContext, mPackageManagerService);
                    } catch (Throwable e) {
                        reportWtf("starting BackgroundDexOptService", e);
                    }
                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                }
            }

            mSystemServiceManager.startService(LauncherAppsService.class);