diff options
author | Narayan Kamath <narayan@google.com> | 2015-06-09 11:31:01 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-09 11:31:08 +0000 |
commit | 3eb63dc35e7ac0335defe4f8e7b42f5dcc390b42 (patch) | |
tree | febba7a4381b878a4cea29d0bc0d610369030349 | |
parent | 3c300f0d77ad83b325bac342d997af3c17bbf8f2 (diff) | |
parent | e845a1ef646aff12978da59dcc3b74836be0875b (diff) | |
download | frameworks_base-3eb63dc35e7ac0335defe4f8e7b42f5dcc390b42.zip frameworks_base-3eb63dc35e7ac0335defe4f8e7b42f5dcc390b42.tar.gz frameworks_base-3eb63dc35e7ac0335defe4f8e7b42f5dcc390b42.tar.bz2 |
Merge "Move linking and directory creation logic to installd." into mnc-dev
-rw-r--r-- | services/core/java/com/android/server/pm/Installer.java | 12 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/PackageInstallerSession.java | 110 |
2 files changed, 56 insertions, 66 deletions
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index fb98d94..ef7be30 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -454,6 +454,18 @@ public final class Installer extends SystemService { return mInstaller.execute(builder.toString()); } + + public int linkFile(String relativePath, String fromBase, String toBase) { + StringBuilder builder = new StringBuilder("linkfile"); + builder.append(' '); + builder.append(relativePath); + builder.append(' '); + builder.append(fromBase); + builder.append(' '); + builder.append(toBase); + return mInstaller.execute(builder.toString()); + } + /** * Returns true iff. {@code instructionSet} is a valid instruction set. */ diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 1cec750..b5ef3b7 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -166,6 +166,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private final List<File> mResolvedInheritedFiles = new ArrayList<>(); @GuardedBy("mLock") + private final List<String> mResolvedInstructionSets = new ArrayList<>(); + @GuardedBy("mLock") private File mInheritedFilesBase; private final Handler.Callback mHandlerCallback = new Handler.Callback() { @@ -521,7 +523,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (isLinkPossible(fromFiles, toDir)) { - createDirsAndLinkFiles(fromFiles, toDir, mInheritedFilesBase); + if (!mResolvedInstructionSets.isEmpty()) { + final File oatDir = new File(toDir, "oat"); + createOatDirs(mResolvedInstructionSets, oatDir); + } + linkFiles(fromFiles, toDir, mInheritedFilesBase); } else { // TODO: this should delegate to DCS so the system process // avoids holding open FDs into containers. @@ -706,21 +712,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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); + // Keep track of all instruction sets we've seen compiled output for. + // If we're linking (and not copying) inherited files, we can recreate the + // instruction set hierarchy and link compiled output. + if (archSubdirs != null && archSubdirs.length > 0) { + 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; + } + + mResolvedInstructionSets.add(archSubDir.getName()); + List<File> oatFiles = Arrays.asList(archSubDir.listFiles()); + if (!oatFiles.isEmpty()) { + mResolvedInheritedFiles.addAll(oatFiles); + } } } } @@ -802,71 +810,41 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return true; } - /** - * 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(); + private static String getRelativePath(File file, File base) throws IOException { final String pathStr = file.getAbsolutePath(); - + final String baseStr = base.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); + if (pathStr.startsWith(baseStr)) { + return pathStr.substring(baseStr.length()); } - throw new IOException("File: " + pathStr + " outside base: " + oldBaseStr); + throw new IOException("File: " + pathStr + " outside base: " + baseStr); } - /** - * 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) + private void createOatDirs(List<String> instructionSets, File fromDir) { + for (String instructionSet : instructionSets) { + mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet); + } + } + + private void linkFiles(List<File> fromFiles, File toDir, File fromDir) throws IOException { for (File fromFile : fromFiles) { - 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); - } + final String relativePath = getRelativePath(fromFile, fromDir); + final int ret = mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(), + toDir.getAbsolutePath()); + + if (ret < 0) { + // installd will log failure details. + throw new IOException("failed linkOrCreateDir(" + relativePath + ", " + + fromDir + ", " + toDir + ")"); } } + Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir); } |