diff options
author | Kenny Root <kroot@google.com> | 2012-04-20 16:10:45 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-04-20 16:10:45 -0700 |
commit | 8b0af627997277978240525d87ef7a7f0661554b (patch) | |
tree | 50dc28a1e6602c7c408eb35076f8c73db6f05bbc | |
parent | 8d3696eca2fb26b33c71494eaf93a0a6588b946a (diff) | |
parent | 2782a478d0214cf71a32d4537fc9fb191d1072fb (diff) | |
download | frameworks_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.java | 73 | ||||
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 136 |
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) { |