Change new file installs to be cluster-based!
Now that all the other pieces are in place, we're ready to start
installing new file-based packages as a cluster (the new unified
directory-based layout). This greatly simplifies the renaming
process.
Also add helper methods to ApplicationInfo to give a much clearer
mapping between it and internal field names, since we can't change
the public API.
Add recursive restorecon().
Bug: 14975160
Change-Id: I72a63c5ddbc594c2fec4a91dd59f73ef253fbfd7
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index bb90fd7..514b26e 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -410,10 +410,14 @@
*/
public int largestWidthLimitDp = 0;
+ /** {@hide} */
+ public String scanSourceDir;
+ /** {@hide} */
+ public String scanPublicSourceDir;
+
/**
* Full path to the base APK for this application.
*/
- // TODO: verify that nobody is doing codePath comparisons against this
public String sourceDir;
/**
@@ -779,11 +783,25 @@
return true;
}
}
-
+
/**
* @hide
*/
@Override protected ApplicationInfo getApplicationInfo() {
return this;
}
+
+ /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; }
+ /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; }
+ /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; }
+ /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
+ /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
+ /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
+
+ /** {@hide} */ public String getCodePath() { return scanSourceDir; }
+ /** {@hide} */ public String getBaseCodePath() { return sourceDir; }
+ /** {@hide} */ public String[] getSplitCodePaths() { return splitSourceDirs; }
+ /** {@hide} */ public String getResourcePath() { return scanPublicSourceDir; }
+ /** {@hide} */ public String getBaseResourcePath() { return publicSourceDir; }
+ /** {@hide} */ public String[] getSplitResourcePaths() { return splitSourceDirs; }
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bb47124..7651aef 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -719,7 +719,12 @@
* <p>
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
+ *
+ * @deprecated external callers should move to
+ * {@link #parsePackage(File, int)}. Eventually this method will
+ * be marked private.
*/
+ @Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final Package pkg = parseBaseApk(apkFile, flags);
if (pkg == null) {
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 4c34d46..fe47f5b 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -371,6 +371,8 @@
* attacks.
*/
public static boolean contains(File dir, File file) {
+ if (file == null) return false;
+
String dirPath = dir.getAbsolutePath();
String filePath = file.getAbsolutePath();
@@ -418,16 +420,27 @@
}
public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
+ if (path == null) return null;
final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
return (result != null) ? result.getAbsolutePath() : null;
}
+ public static String[] rewriteAfterRename(File beforeDir, File afterDir, String[] paths) {
+ if (paths == null) return null;
+ final String[] result = new String[paths.length];
+ for (int i = 0; i < paths.length; i++) {
+ result[i] = rewriteAfterRename(beforeDir, afterDir, paths[i]);
+ }
+ return result;
+ }
+
/**
* Given a path under the "before" directory, rewrite it to live under the
* "after" directory. For example, {@code /before/foo/bar.txt} would become
* {@code /after/foo/bar.txt}.
*/
public static File rewriteAfterRename(File beforeDir, File afterDir, File file) {
+ if (file == null) return null;
if (contains(beforeDir, file)) {
final String splice = file.getAbsolutePath().substring(
beforeDir.getAbsolutePath().length());
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 71d12c6..84aa427 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -28,9 +28,15 @@
* {@hide}
*/
public class SELinux {
-
private static final String TAG = "SELinux";
+ /** Keep in sync with ./external/libselinux/include/selinux/android.h */
+ private static final int SELINUX_ANDROID_RESTORECON_NOCHANGE = 1;
+ private static final int SELINUX_ANDROID_RESTORECON_VERBOSE = 2;
+ private static final int SELINUX_ANDROID_RESTORECON_RECURSE = 4;
+ private static final int SELINUX_ANDROID_RESTORECON_FORCE = 8;
+ private static final int SELINUX_ANDROID_RESTORECON_DATADATA = 16;
+
/**
* Determine whether SELinux is disabled or enabled.
* @return a boolean indicating whether SELinux is enabled.
@@ -136,7 +142,7 @@
*/
public static boolean restorecon(String pathname) throws NullPointerException {
if (pathname == null) { throw new NullPointerException(); }
- return native_restorecon(pathname);
+ return native_restorecon(pathname, 0);
}
/**
@@ -149,7 +155,7 @@
* @param pathname The pathname of the file to be relabeled.
* @return a boolean indicating whether the relabeling succeeded.
*/
- private static native boolean native_restorecon(String pathname);
+ private static native boolean native_restorecon(String pathname, int flags);
/**
* Restores a file to its default SELinux security context.
@@ -164,10 +170,10 @@
*/
public static boolean restorecon(File file) throws NullPointerException {
try {
- return native_restorecon(file.getCanonicalPath());
+ return native_restorecon(file.getCanonicalPath(), 0);
} catch (IOException e) {
Slog.e(TAG, "Error getting canonical path. Restorecon failed for " +
- file.getPath(), e);
+ file.getPath(), e);
return false;
}
}
@@ -180,14 +186,13 @@
*
* @return a boolean indicating whether the relabeling succeeded.
*/
- public static boolean restoreconTree(File dir) {
- final File[] files = dir.listFiles();
- boolean success = true;
- if (files != null) {
- for (File file : files) {
- success &= restorecon(file);
- }
+ public static boolean restoreconRecursive(File file) {
+ try {
+ return native_restorecon(file.getCanonicalPath(), SELINUX_ANDROID_RESTORECON_RECURSE);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error getting canonical path. Restorecon failed for " +
+ file.getPath(), e);
+ return false;
}
- return success;
}
}
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 26405b5..ffa569e 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -404,7 +404,7 @@
* Returns: boolean: (true) file label successfully restored, (false) otherwise
* Exceptions: none
*/
-static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) {
+static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr, jint flags) {
if (isSELinuxDisabled) {
return true;
}
@@ -415,7 +415,7 @@
return false;
}
- int ret = selinux_android_restorecon(pathname.c_str(), 0);
+ int ret = selinux_android_restorecon(pathname.c_str(), flags);
ALOGV("restorecon(%s) => %d", pathname.c_str(), ret);
return (ret == 0);
}
@@ -434,7 +434,7 @@
{ "getPidContext" , "(I)Ljava/lang/String;" , (void*)getPidCon },
{ "isSELinuxEnforced" , "()Z" , (void*)isSELinuxEnforced},
{ "isSELinuxEnabled" , "()Z" , (void*)isSELinuxEnabled },
- { "native_restorecon" , "(Ljava/lang/String;)Z" , (void*)native_restorecon},
+ { "native_restorecon" , "(Ljava/lang/String;I)Z" , (void*)native_restorecon},
{ "setBooleanValue" , "(Ljava/lang/String;Z)Z" , (void*)setBooleanValue },
{ "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
{ "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },