From 85387d7ba36e56b291cbde87acb5a5b2200fe01c Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 26 Aug 2010 10:13:11 -0700 Subject: Allow native shared libraries in ASEC containers This change moves the native library handling earlier in the package installation process so that it may be inserted into ASEC containers before they are finalized in the DefaultContainerService. Note that native libraries on SD card requires that vold mount ASEC containers without the "noexec" flag on the mount point. Change-Id: Ib34b1886bf6f94b99bb7b3781db6e9b5a58807ba --- .../defcontainer/DefaultContainerService.java | 81 ++++++++++++++++++++-- 1 file changed, 75 insertions(+), 6 deletions(-) (limited to 'packages') diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index c6e0a24..f08bd3c 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -17,7 +17,9 @@ package com.android.defcontainer; import com.android.internal.app.IMediaContainerService; +import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; + import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; @@ -37,6 +39,7 @@ import android.os.StatFs; import android.app.IntentService; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; import java.io.File; import java.io.FileInputStream; @@ -44,6 +47,11 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; import android.os.FileUtils; import android.provider.Settings; @@ -59,6 +67,8 @@ public class DefaultContainerService extends IntentService { private static final String TAG = "DefContainer"; private static final boolean localLOGV = true; + private static final String LIB_DIR_NAME = "lib"; + private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() { /* * Creates a new container and copies resource there. @@ -194,18 +204,51 @@ public class DefaultContainerService extends IntentService { Log.w(TAG, "Make sure sdcard is mounted."); return null; } - // Create new container at newCachePath + + // The .apk file String codePath = packageURI.getPath(); File codeFile = new File(codePath); - String newCachePath = null; + + // Calculate size of container needed to hold base APK. + long sizeBytes = codeFile.length(); + + // Check all the native files that need to be copied and add that to the container size. + ZipFile zipFile; + List> nativeFiles; + try { + zipFile = new ZipFile(codeFile); + + nativeFiles = new LinkedList>(); + + NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles); + + final int N = nativeFiles.size(); + for (int i = 0; i < N; i++) { + final Pair entry = nativeFiles.get(i); + + /* + * Note that PackageHelper.createSdDir adds a 1MB padding on + * our claimed size, so we don't have to worry about block + * alignment here. + */ + sizeBytes += entry.first.getSize(); + } + } catch (ZipException e) { + Log.w(TAG, "Failed to extract data from package file", e); + return null; + } catch (IOException e) { + Log.w(TAG, "Failed to cache package shared libs", e); + return null; + } + // Create new container - if ((newCachePath = PackageHelper.createSdDir(codeFile, - newCid, key, Process.myUid())) == null) { + String newCachePath = null; + if ((newCachePath = PackageHelper.createSdDir(sizeBytes, newCid, key, Process.myUid())) == null) { Log.e(TAG, "Failed to create container " + newCid); return null; } - if (localLOGV) Log.i(TAG, "Created container for " + newCid - + " at path : " + newCachePath); + if (localLOGV) + Log.i(TAG, "Created container for " + newCid + " at path : " + newCachePath); File resFile = new File(newCachePath, resFileName); if (!FileUtils.copyFile(new File(codePath), resFile)) { Log.e(TAG, "Failed to copy " + codePath + " to " + resFile); @@ -213,6 +256,32 @@ public class DefaultContainerService extends IntentService { PackageHelper.destroySdDir(newCid); return null; } + + try { + File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME); + sharedLibraryDir.mkdir(); + + final int N = nativeFiles.size(); + for (int i = 0; i < N; i++) { + final Pair entry = nativeFiles.get(i); + + InputStream is = zipFile.getInputStream(entry.first); + try { + File destFile = new File(sharedLibraryDir, entry.second); + if (!FileUtils.copyToFile(is, destFile)) { + throw new IOException("Couldn't copy native binary " + + entry.first.getName() + " to " + entry.second); + } + } finally { + is.close(); + } + } + } catch (IOException e) { + Log.e(TAG, "Couldn't copy native file to container", e); + PackageHelper.destroySdDir(newCid); + return null; + } + if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile); if (!PackageHelper.finalizeSdDir(newCid)) { Log.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath); -- cgit v1.1