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

Commit 8deec64a authored by Narayan Kamath's avatar Narayan Kamath Committed by Android Git Automerger
Browse files

am cd1fc146: Don\'t compile all splits when installing one.

* commit 'cd1fc146':
  Don't compile all splits when installing one.
parents aff26dff cd1fc146
Loading
Loading
Loading
Loading
+95 −6
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
@@ -77,6 +78,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@@ -163,6 +165,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private final List<File> mResolvedStagedFiles = new ArrayList<>();
    @GuardedBy("mLock")
    private final List<File> mResolvedInheritedFiles = new ArrayList<>();
    @GuardedBy("mLock")
    private File mInheritedFilesBase;

    private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
@@ -511,8 +515,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                final List<File> fromFiles = mResolvedInheritedFiles;
                final File toDir = resolveStageDir();

                if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                    throw new IllegalStateException("mInheritedFilesBase == null");
                }

                if (isLinkPossible(fromFiles, toDir)) {
                    linkFiles(fromFiles, toDir);
                    createDirsAndLinkFiles(fromFiles, toDir, mInheritedFilesBase);
                } else {
                    // TODO: this should delegate to DCS so the system process
                    // avoids holding open FDs into containers.
@@ -690,6 +699,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    }
                }
            }

            // Inherit compiled oat directory.
            final File packageInstallDir = (new File(app.getBaseCodePath())).getParentFile();
            mInheritedFilesBase = packageInstallDir;
            final File oatDir = new File(packageInstallDir, "oat");
            if (oatDir.exists()) {
                final File[] archSubdirs = oatDir.listFiles();
                // Only add "oatDir" if it contains arch specific subdirs.
                if (archSubdirs != null && archSubdirs.length > 0) {
                    mResolvedInheritedFiles.add(oatDir);
                }
                final String[] instructionSets = InstructionSets.getAllDexCodeInstructionSets();
                for (File archSubDir : archSubdirs) {
                    // Skip any directory that isn't an ISA subdir.
                    if (!ArrayUtils.contains(instructionSets, archSubDir.getName())) {
                        continue;
                    }

                    List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
                    if (!oatFiles.isEmpty()) {
                        mResolvedInheritedFiles.add(archSubDir);
                        mResolvedInheritedFiles.addAll(oatFiles);
                    }
                }
            }
        }
    }

@@ -768,16 +802,71 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        return true;
    }

    private static void linkFiles(List<File> fromFiles, File toDir) throws IOException {
    /**
     * Reparents the path of {@code file} from {@code oldBase} to {@code newBase}. {@code file}
     * must necessarily be a subpath of {@code oldBase}. It is an error for {@code file} to have
     * relative path components such as {@code "."} or {@code ".."}. For example, for we will
     * reparent {@code /foo/bar/baz} to {@code /foo2/bar/baz} if {@code oldBase} was {@code /foo}
     * and {@code newBase} was {@code /foo2}.
     */
    private static File reparentPath(File file, File oldBase, File newBase) throws IOException {
        final String oldBaseStr = oldBase.getAbsolutePath();
        final String pathStr = file.getAbsolutePath();

        // Don't allow relative paths.
        if (pathStr.contains("/.") ) {
            throw new IOException("Invalid path (was relative) : " + pathStr);
        }

        if (pathStr.startsWith(oldBaseStr)) {
            final String relative = pathStr.substring(oldBaseStr.length());
            return new File(newBase, relative);
        }

        throw new IOException("File: " + pathStr + " outside base: " + oldBaseStr);
    }

    /**
     * Recreates a directory and file structure, specified by a list of files {@code fromFiles}
     * which are subpaths of {@code fromDir} to {@code toDir}. Directories are created with the
     * same permissions, and regular files are linked.
     *
     * TODO: Move this function to installd so that the system process doesn't have to
     * manipulate / relabel directories.
     */
    private static void createDirsAndLinkFiles(List<File> fromFiles, File toDir, File fromDir)
            throws IOException {
        for (File fromFile : fromFiles) {
            final File toFile = new File(toDir, fromFile.getName());
            final File toFile = reparentPath(fromFile, fromDir, toDir);
            final StructStat stat;
            try {
                stat = Os.stat(fromFile.getAbsolutePath());
            } catch (ErrnoException e) {
                throw new IOException("Failed to stat: " + fromFile.getAbsolutePath(), e);
            }

            if (OsConstants.S_ISDIR(stat.st_mode)) {
                if (LOGD) Slog.d(TAG, "Creating directory " + toFile.getAbsolutePath());
                try {
                    Os.mkdir(toFile.getAbsolutePath(), stat.st_mode);
                } catch (ErrnoException e) {
                    throw new IOException("Failed to create dir: " + toFile.getAbsolutePath(), e);
                }

                // We do this to ensure that the oat/ directory is created with the right
                // label (data_dalvikcache_file) instead of apk_tmpfile.
                if (!SELinux.restorecon(toFile)) {
                    throw new IOException("Failed to restorecon: " + toFile.getAbsolutePath());
                }
            } else {
                if (LOGD) Slog.d(TAG, "Linking " + fromFile + " to " + toFile);
                try {
                    Os.link(fromFile.getAbsolutePath(), toFile.getAbsolutePath());
                } catch (ErrnoException e) {
                    throw new IOException("Failed to link " + fromFile + " to " + toFile, e);
                }
            }
        }
        Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
    }

+2 −2
Original line number Diff line number Diff line
@@ -11504,7 +11504,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
                || (args.volumeUuid != null));
        boolean replace = false;
        int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
        int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
        // Result object to be returned
        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
@@ -11705,7 +11705,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Run dexopt before old package gets removed, to minimize time when app is unavailable
            int result = mPackageDexOptimizer
                    .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
                    .performDexOpt(pkg, null /* instruction sets */, false /* forceDex */,
                            false /* defer */, false /* inclDependencies */);
            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
                res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);