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

Commit 67c8b01f authored by Jeff Sharkey's avatar Jeff Sharkey Committed by android-build-merger
Browse files

Merge "Prepare to move dexopt calls to Binder." am: d7b144a5 am: 35cbe8ff

am: 41d75809

Change-Id: I0b87126b4b312ef8fc3c71479d6d5725e96e6acc
parents 0e4fc209 41d75809
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -134,13 +134,6 @@ public class InstallerConnection {
        return resRaw;
    }

    public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
            int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
            throws InstallerException {
        dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /*outputPath*/, dexFlags,
                compilerFilter, volumeUuid, sharedLibraries);
    }

    public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
            int dexoptNeeded, String outputPath, int dexFlags, String compilerFilter,
            String volumeUuid, String sharedLibraries) throws InstallerException {
+9 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.ZygoteProcess;
import android.os.storage.StorageManager;
import android.security.keystore.AndroidKeyStoreProvider;
import android.system.ErrnoException;
import android.system.Os;
@@ -522,10 +523,15 @@ public class ZygoteInit {
                }

                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                    final String packageName = "*";
                    final String outputPath = null;
                    final int dexFlags = 0;
                    final String compilerFilter = "speed";
                    final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
                    try {
                        installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
                                dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
                                sharedLibraries);
                        installer.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
                                instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
                                uuid, sharedLibraries);
                    } catch (InstallerException e) {
                        // Ignore (but log), we need this on the classpath for fallback mode.
                        Log.w(TAG, "Failed compiling classpath element for system server: "
+65 −48
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ import dalvik.system.VMRuntime;

import java.util.Arrays;

public final class Installer extends SystemService {
public class Installer extends SystemService {
    private static final String TAG = "Installer";

    /* ***************************************************************************
@@ -58,52 +58,75 @@ public final class Installer extends SystemService {
    public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
    public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;

    private final boolean mIsolated;

    // TODO: reconnect if installd restarts
    private final InstallerConnection mInstaller;
    private final IInstalld mInstalld;

    private volatile Object mWarnIfHeld;

    public Installer(Context context) {
        super(context);
        mInstaller = new InstallerConnection();
        // TODO: reconnect if installd restarts
        mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd"));
        this(context, false);
    }

    // Package-private installer that accepts a custom InstallerConnection. Used for
    // OtaDexoptService.
    Installer(Context context, InstallerConnection connection) {
    /**
     * @param isolated indicates if this object should <em>not</em> connect to
     *            the real {@code installd}. All remote calls will be ignored
     *            unless you extend this class and intercept them.
     */
    public Installer(Context context, boolean isolated) {
        super(context);
        mInstaller = connection;
        // TODO: reconnect if installd restarts
        mIsolated = isolated;
        if (isolated) {
            mInstaller = null;
            mInstalld = null;
        } else {
            mInstaller = new InstallerConnection();
            mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd"));
        }
    }

    /**
     * Yell loudly if someone tries making future calls while holding a lock on
     * the given object.
     */
    public void setWarnIfHeld(Object warnIfHeld) {
        if (mInstaller != null) {
            mInstaller.setWarnIfHeld(warnIfHeld);
        }
        mWarnIfHeld = warnIfHeld;
    }

    @Override
    public void onStart() {
        if (mInstaller != null) {
            Slog.i(TAG, "Waiting for installd to be ready.");
            mInstaller.waitForConnection();
        }
    }

    private void checkLock() {
    /**
     * Do several pre-flight checks before making a remote call.
     *
     * @return if the remote call should continue.
     */
    private boolean checkBeforeRemote() {
        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
        }
        if (mIsolated) {
            Slog.i(TAG, "Ignoring request because this installer is isolated");
            return false;
        } else {
            return true;
        }
    }

    public void createAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo, int targetSdkVersion) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                    targetSdkVersion);
@@ -114,7 +137,7 @@ public final class Installer extends SystemService {

    public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -124,7 +147,7 @@ public final class Installer extends SystemService {

    public void migrateAppData(String uuid, String packageName, int userId, int flags)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.migrateAppData(uuid, packageName, userId, flags);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -134,7 +157,7 @@ public final class Installer extends SystemService {

    public void clearAppData(String uuid, String packageName, int userId, int flags,
            long ceDataInode) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -144,7 +167,7 @@ public final class Installer extends SystemService {

    public void destroyAppData(String uuid, String packageName, int userId, int flags,
            long ceDataInode) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -155,7 +178,7 @@ public final class Installer extends SystemService {
    public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
            String dataAppName, int appId, String seInfo, int targetSdkVersion)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo,
                    targetSdkVersion);
@@ -166,6 +189,7 @@ public final class Installer extends SystemService {

    public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode,
            String codePath, PackageStats stats) throws InstallerException {
        if (!checkBeforeRemote()) return;
        final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags,
                ceDataInode, codePath);
        try {
@@ -179,7 +203,7 @@ public final class Installer extends SystemService {

    public long getAppDataInode(String uuid, String packageName, int userId, int flags)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return -1;
        try {
            return mInstalld.getAppDataInode(uuid, packageName, userId, flags);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -187,25 +211,18 @@ public final class Installer extends SystemService {
        }
    }

    public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
            int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
            throws InstallerException {
        assertValidInstructionSet(instructionSet);
        mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
                compilerFilter, volumeUuid, sharedLibraries);
    }

    public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
    public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
            int dexoptNeeded, @Nullable String outputPath, int dexFlags,
            String compilerFilter, String volumeUuid, String sharedLibraries)
            String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries)
            throws InstallerException {
        assertValidInstructionSet(instructionSet);
        if (!checkBeforeRemote()) return;
        mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
                outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries);
    }

    public boolean mergeProfiles(int uid, String packageName) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return false;
        try {
            return mInstalld.mergeProfiles(uid, packageName);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -215,7 +232,7 @@ public final class Installer extends SystemService {

    public boolean dumpProfiles(int uid, String packageName, String codePaths)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return false;
        try {
            return mInstalld.dumpProfiles(uid, packageName, codePaths);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -225,7 +242,7 @@ public final class Installer extends SystemService {

    public void idmap(String targetApkPath, String overlayApkPath, int uid)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.idmap(targetApkPath, overlayApkPath, uid);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -235,7 +252,7 @@ public final class Installer extends SystemService {

    public void rmdex(String codePath, String instructionSet) throws InstallerException {
        assertValidInstructionSet(instructionSet);
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.rmdex(codePath, instructionSet);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -244,7 +261,7 @@ public final class Installer extends SystemService {
    }

    public void rmPackageDir(String packageDir) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.rmPackageDir(packageDir);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -253,7 +270,7 @@ public final class Installer extends SystemService {
    }

    public void clearAppProfiles(String packageName) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.clearAppProfiles(packageName);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -262,7 +279,7 @@ public final class Installer extends SystemService {
    }

    public void destroyAppProfiles(String packageName) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.destroyAppProfiles(packageName);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -272,7 +289,7 @@ public final class Installer extends SystemService {

    public void createUserData(String uuid, int userId, int userSerial, int flags)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.createUserData(uuid, userId, userSerial, flags);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -281,7 +298,7 @@ public final class Installer extends SystemService {
    }

    public void destroyUserData(String uuid, int userId, int flags) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.destroyUserData(uuid, userId, flags);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -291,7 +308,7 @@ public final class Installer extends SystemService {

    public void markBootComplete(String instructionSet) throws InstallerException {
        assertValidInstructionSet(instructionSet);
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.markBootComplete(instructionSet);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -300,7 +317,7 @@ public final class Installer extends SystemService {
    }

    public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.freeCache(uuid, freeStorageSize);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -315,7 +332,7 @@ public final class Installer extends SystemService {
     */
    public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32,
            int userId) throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -325,7 +342,7 @@ public final class Installer extends SystemService {

    public void createOatDir(String oatDir, String dexInstructionSet)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.createOatDir(oatDir, dexInstructionSet);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -335,7 +352,7 @@ public final class Installer extends SystemService {

    public void linkFile(String relativePath, String fromBase, String toBase)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.linkFile(relativePath, fromBase, toBase);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -345,7 +362,7 @@ public final class Installer extends SystemService {

    public void moveAb(String apkPath, String instructionSet, String outputPath)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.moveAb(apkPath, instructionSet, outputPath);
        } catch (RemoteException | ServiceSpecificException e) {
@@ -355,7 +372,7 @@ public final class Installer extends SystemService {

    public void deleteOdex(String apkPath, String instructionSet, String outputPath)
            throws InstallerException {
        checkLock();
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
        } catch (RemoteException | ServiceSpecificException e) {
+47 −38
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
@@ -29,15 +30,17 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.InstallerConnection;
import com.android.internal.os.InstallerConnection.InstallerException;

import java.io.File;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -276,9 +279,27 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
     */
    private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg,
            int compilationReason) {
        // Use our custom connection that just collects the commands.
        RecordingInstallerConnection collectingConnection = new RecordingInstallerConnection();
        Installer collectingInstaller = new Installer(mContext, collectingConnection);
        // Intercept and collect dexopt requests
        final List<String> commands = new ArrayList<String>();
        final Installer collectingInstaller = new Installer(mContext, true) {
            @Override
            public void dexopt(String apkPath, int uid, @Nullable String pkgName,
                    String instructionSet, int dexoptNeeded, @Nullable String outputPath,
                    int dexFlags, String compilerFilter, @Nullable String volumeUuid,
                    @Nullable String sharedLibraries) throws InstallerException {
                commands.add(buildCommand("dexopt",
                        apkPath,
                        uid,
                        pkgName,
                        instructionSet,
                        dexoptNeeded,
                        outputPath,
                        dexFlags,
                        compilerFilter,
                        volumeUuid,
                        sharedLibraries));
            }
        };

        // Use the package manager install and install lock here for the OTA dex optimizer.
        PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
@@ -295,7 +316,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
                getCompilerFilterForReason(compilationReason),
                null /* CompilerStats.PackageStats */);

        return collectingConnection.commands;
        return commands;
    }

    @Override
@@ -414,39 +435,27 @@ public class OtaDexoptService extends IOtaDexopt.Stub {

    }

    private static class RecordingInstallerConnection extends InstallerConnection {
        public List<String> commands = new ArrayList<String>(1);

        @Override
        public void setWarnIfHeld(Object warnIfHeld) {
            throw new IllegalStateException("Should not reach here");
        }

        @Override
        public synchronized String transact(String cmd) {
            commands.add(cmd);
            return "0";
        }

        @Override
        public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
            throw new IllegalStateException("Should not reach here");
    /**
     * Cook up argument list in the format that {@code installd} expects.
     */
    private static String buildCommand(Object... args) {
        final StringBuilder builder = new StringBuilder();
        for (Object arg : args) {
            String escaped;
            if (arg == null) {
                escaped = "";
            } else {
                escaped = String.valueOf(arg);
            }

        @Override
        public boolean dumpProfiles(String gid, String packageName, String codePaths)
                throws InstallerException {
            throw new IllegalStateException("Should not reach here");
            if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
                throw new IllegalArgumentException(
                        "Invalid argument while executing " + Arrays.toString(args));
            }

        @Override
        public void disconnect() {
            throw new IllegalStateException("Should not reach here");
            if (TextUtils.isEmpty(escaped)) {
                escaped = "!";
            }

        @Override
        public void waitForConnection() {
            throw new IllegalStateException("Should not reach here");
            builder.append(' ').append(escaped);
        }
        return builder.toString();
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -2240,8 +2240,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    getCompilerFilterForReason(REASON_SHARED_APK),
                                    false /* newProfile */);
                            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                                mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                        dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                mInstaller.dexopt(lib, Process.SYSTEM_UID, "*",
                                        dexCodeInstructionSet, dexoptNeeded, null,
                                        DEXOPT_PUBLIC,
                                        getCompilerFilterForReason(REASON_SHARED_APK),
                                        StorageManager.UUID_PRIVATE_INTERNAL,
                                        SKIP_SHARED_LIBRARY_CHECK);