summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2012-04-20 16:10:45 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-20 16:10:45 -0700
commit8b0af627997277978240525d87ef7a7f0661554b (patch)
tree50dc28a1e6602c7c408eb35076f8c73db6f05bbc
parent8d3696eca2fb26b33c71494eaf93a0a6588b946a (diff)
parent2782a478d0214cf71a32d4537fc9fb191d1072fb (diff)
downloadframeworks_base-8b0af627997277978240525d87ef7a7f0661554b.zip
frameworks_base-8b0af627997277978240525d87ef7a7f0661554b.tar.gz
frameworks_base-8b0af627997277978240525d87ef7a7f0661554b.tar.bz2
Merge "Move forward lock utilities to PackageHelper"
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java73
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java136
2 files changed, 122 insertions, 87 deletions
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 266728b..61866e5 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -16,15 +16,24 @@
package com.android.internal.content;
-import android.os.storage.IMountService;
-
+import android.os.FileUtils;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.storage.IMountService;
import android.os.storage.StorageResultCode;
import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import libcore.io.IoUtils;
/**
* Constants used internally between the PackageManager
@@ -196,4 +205,64 @@ public class PackageHelper {
}
return false;
}
+
+ public static void extractPublicFiles(String packagePath, File publicZipFile)
+ throws IOException {
+ final FileOutputStream fstr = new FileOutputStream(publicZipFile);
+ final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
+ try {
+ final ZipFile privateZip = new ZipFile(packagePath);
+ try {
+ // Copy manifest, resources.arsc and res directory to public zip
+ for (final ZipEntry zipEntry : Collections.list(privateZip.entries())) {
+ final String zipEntryName = zipEntry.getName();
+ if ("AndroidManifest.xml".equals(zipEntryName)
+ || "resources.arsc".equals(zipEntryName)
+ || zipEntryName.startsWith("res/")) {
+ copyZipEntry(zipEntry, privateZip, publicZipOutStream);
+ }
+ }
+ } finally {
+ try {
+ privateZip.close();
+ } catch (IOException e) {
+ }
+ }
+
+ publicZipOutStream.finish();
+ publicZipOutStream.flush();
+ FileUtils.sync(fstr);
+ publicZipOutStream.close();
+ FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
+ | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
+ } finally {
+ IoUtils.closeQuietly(publicZipOutStream);
+ }
+ }
+
+ private static void copyZipEntry(ZipEntry zipEntry, ZipFile inZipFile,
+ ZipOutputStream outZipStream) throws IOException {
+ byte[] buffer = new byte[4096];
+ int num;
+
+ ZipEntry newEntry;
+ if (zipEntry.getMethod() == ZipEntry.STORED) {
+ // Preserve the STORED method of the input entry.
+ newEntry = new ZipEntry(zipEntry);
+ } else {
+ // Create a new entry so that the compressed len is recomputed.
+ newEntry = new ZipEntry(zipEntry.getName());
+ }
+ outZipStream.putNextEntry(newEntry);
+
+ final InputStream data = inZipFile.getInputStream(zipEntry);
+ try {
+ while ((num = data.read(buffer)) > 0) {
+ outZipStream.write(buffer, 0, num);
+ }
+ outZipStream.flush();
+ } finally {
+ IoUtils.closeQuietly(data);
+ }
+ }
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index b97d7fd..6891b76 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -6067,10 +6067,23 @@ public class PackageManagerService extends IPackageManager.Stub {
Intent.FLAG_GRANT_READ_URI_PERMISSION);
ret = imcs.copyResource(packageURI, out);
} finally {
- try { if (out != null) out.close(); } catch (IOException e) {}
+ IoUtils.closeQuietly(out);
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
+ if (isFwdLocked()) {
+ final File destResourceFile = new File(getResourcePath());
+
+ // Copy the public files
+ try {
+ PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
+ } catch (IOException e) {
+ Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
+ + " forward-locked app.");
+ destResourceFile.delete();
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ }
return ret;
}
@@ -6086,21 +6099,29 @@ public class PackageManagerService extends IPackageManager.Stub {
cleanUp();
return false;
} else {
- // Rename based on packageName
- File codeFile = new File(getCodePath());
- String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
- File desFile = new File(installDir, apkName + ".apk");
- if (!codeFile.renameTo(desFile)) {
+ final File oldCodeFile = new File(getCodePath());
+ final File oldResourceFile = new File(getResourcePath());
+
+ // Rename APK file based on packageName
+ final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
+ final File newCodeFile = new File(installDir, apkName + ".apk");
+ if (!oldCodeFile.renameTo(newCodeFile)) {
+ return false;
+ }
+ codeFileName = newCodeFile.getPath();
+
+ // Rename public resource file if it's forward-locked.
+ final File newResFile = new File(getResourcePathFromCodePath());
+ if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
return false;
}
- // Reset paths since the file has been renamed.
- codeFileName = desFile.getPath();
resourceFileName = getResourcePathFromCodePath();
- // Set permissions
+
+ // Attempt to set permissions
if (!setPermissions()) {
- // Failed setting permissions.
return false;
}
+
return true;
}
}
@@ -6116,11 +6137,26 @@ public class PackageManagerService extends IPackageManager.Stub {
return resourceFileName;
}
- String getResourcePathFromCodePath() {
- String codePath = getCodePath();
- if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
- String apkNameOnly = getApkName(codePath);
- return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
+ private String getResourcePathFromCodePath() {
+ final String codePath = getCodePath();
+ if (isFwdLocked()) {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(mAppInstallDir.getPath());
+ sb.append('/');
+ sb.append(getApkName(codePath));
+ sb.append(".zip");
+
+ /*
+ * If our APK is a temporary file, mark the resource as a
+ * temporary file as well so it can be cleaned up after
+ * catastrophic failure.
+ */
+ if (codePath.endsWith(".tmp")) {
+ sb.append(".tmp");
+ }
+
+ return sb.toString();
} else {
return codePath;
}
@@ -6941,15 +6977,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO Gross hack but fix later. Ideally move this to be a post installation
// check after alloting uid.
if (isForwardLocked(newPackage)) {
- File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
- try {
- extractPublicFiles(newPackage, destResourceFile);
- } catch (IOException e) {
- Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" +
- " forward-locked app.");
- destResourceFile.delete();
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
newPackage.applicationInfo.uid);
} else {
@@ -6986,67 +7013,6 @@ public class PackageManagerService extends IPackageManager.Stub {
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
- private void extractPublicFiles(PackageParser.Package newPackage,
- File publicZipFile) throws IOException {
- final FileOutputStream fstr = new FileOutputStream(publicZipFile);
- final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
- try {
- final ZipFile privateZip = new ZipFile(newPackage.mPath);
- try {
- // Copy manifest, resources.arsc and res directory to public zip
-
- final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
- while (privateZipEntries.hasMoreElements()) {
- final ZipEntry zipEntry = privateZipEntries.nextElement();
- final String zipEntryName = zipEntry.getName();
- if ("AndroidManifest.xml".equals(zipEntryName)
- || "resources.arsc".equals(zipEntryName)
- || zipEntryName.startsWith("res/")) {
- copyZipEntry(zipEntry, privateZip, publicZipOutStream);
- }
- }
- } finally {
- try { privateZip.close(); } catch (IOException e) { }
- }
-
- publicZipOutStream.finish();
- publicZipOutStream.flush();
- FileUtils.sync(fstr);
- publicZipOutStream.close();
- FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
- | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
- } finally {
- IoUtils.closeQuietly(publicZipOutStream);
- }
- }
-
- private static void copyZipEntry(ZipEntry zipEntry,
- ZipFile inZipFile,
- ZipOutputStream outZipStream) throws IOException {
- byte[] buffer = new byte[4096];
- int num;
-
- ZipEntry newEntry;
- if (zipEntry.getMethod() == ZipEntry.STORED) {
- // Preserve the STORED method of the input entry.
- newEntry = new ZipEntry(zipEntry);
- } else {
- // Create a new entry so that the compressed len is recomputed.
- newEntry = new ZipEntry(zipEntry.getName());
- }
- outZipStream.putNextEntry(newEntry);
-
- final InputStream data = inZipFile.getInputStream(zipEntry);
- try {
- while ((num = data.read(buffer)) > 0) {
- outZipStream.write(buffer, 0, num);
- }
- outZipStream.flush();
- } finally {
- IoUtils.closeQuietly(data);
- }
- }
-
private void deleteTempPackageFiles() {
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {