summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2015-06-09 11:31:01 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-09 11:31:08 +0000
commit3eb63dc35e7ac0335defe4f8e7b42f5dcc390b42 (patch)
treefebba7a4381b878a4cea29d0bc0d610369030349 /services
parent3c300f0d77ad83b325bac342d997af3c17bbf8f2 (diff)
parente845a1ef646aff12978da59dcc3b74836be0875b (diff)
downloadframeworks_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
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/pm/Installer.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java110
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);
}