diff options
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 3 | ||||
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 3 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 25 | ||||
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 33 | ||||
-rw-r--r-- | core/java/android/os/ShellCallback.java | 23 | ||||
-rw-r--r-- | core/java/android/os/ShellCommand.java | 6 | ||||
-rw-r--r-- | core/java/com/android/internal/os/IShellCallback.aidl | 2 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 31 | ||||
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 87 | ||||
-rw-r--r-- | libs/androidfw/ZipFileRO.cpp | 24 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AssetManager.h | 27 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ZipFileRO.h | 6 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerShellCommand.java | 8 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerShellCommand.java | 78 | ||||
-rw-r--r-- | services/coverage/java/com/android/server/coverage/CoverageService.java | 2 |
15 files changed, 284 insertions, 74 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index ab075ee0e9f2..79e7fac11bb1 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -98,7 +98,8 @@ public class Am extends BaseCommand { static final class MyShellCallback extends ShellCallback { boolean mActive = true; - @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { + @Override public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, + String mode) { if (!mActive) { System.err.println("Open attempt after active for: " + path); return null; diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 29433f3fc14f..9490880afe0f 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -157,7 +157,8 @@ public final class Pm { } static final class MyShellCallback extends ShellCallback { - @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { + @Override public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, + String mode) { File file = new File(path); final ParcelFileDescriptor fd; try { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index b48829cfc87d..1c5cf15da062 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -102,6 +102,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.File; +import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -1708,13 +1709,33 @@ public class PackageParser { */ public static ApkLite parseApkLite(File apkFile, int flags) throws PackageParserException { - final String apkPath = apkFile.getAbsolutePath(); + return parseApkLiteInner(apkFile, null, null, flags); + } + + /** + * Utility method that retrieves lightweight details about a single APK + * file, including package name, split name, and install location. + * + * @param fd already open file descriptor of an apk file + * @param debugPathName arbitrary text name for this file, for debug output + * @param flags optional parse flags, such as + * {@link #PARSE_COLLECT_CERTIFICATES} + */ + public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags) + throws PackageParserException { + return parseApkLiteInner(null, fd, debugPathName, flags); + } + + private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, + int flags) throws PackageParserException { + final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath(); AssetManager assets = null; XmlResourceParser parser = null; try { assets = newConfiguredAssetManager(); - int cookie = assets.addAssetPath(apkPath); + int cookie = fd != null + ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath); if (cookie == 0) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse " + apkPath); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index f0adcd6cfb3e..78665609bdd4 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -28,8 +28,7 @@ import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; -import dalvik.annotation.optimization.FastNative; - +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -694,7 +693,35 @@ public final class AssetManager implements AutoCloseable { private native final int addAssetPathNative(String path, boolean appAsLib); - /** + /** + * Add an additional set of assets to the asset manager from an already open + * FileDescriptor. Not for use by applications. + * This does not give full AssetManager functionality for these assets, + * since the origin of the file is not known for purposes of sharing, + * overlay resolution, and other features. However it does allow you + * to do simple access to the contents of the given fd as an apk file. + * Performs a dup of the underlying fd, so you must take care of still closing + * the FileDescriptor yourself (and can do that whenever you want). + * Returns the cookie of the added asset, or 0 on failure. + * {@hide} + */ + public int addAssetFd(FileDescriptor fd, String debugPathName) { + return addAssetFdInternal(fd, debugPathName, false); + } + + private int addAssetFdInternal(FileDescriptor fd, String debugPathName, + boolean appAsLib) { + synchronized (this) { + int res = addAssetFdNative(fd, debugPathName, appAsLib); + makeStringBlocks(mStringBlocks); + return res; + } + } + + private native int addAssetFdNative(FileDescriptor fd, String debugPathName, + boolean appAsLib); + + /** * Add a set of assets to overlay an already added set of assets. * * This is only intended for application resources. System wide resources diff --git a/core/java/android/os/ShellCallback.java b/core/java/android/os/ShellCallback.java index e7fe697f9c54..ad9fbfbfae40 100644 --- a/core/java/android/os/ShellCallback.java +++ b/core/java/android/os/ShellCallback.java @@ -35,8 +35,9 @@ public class ShellCallback implements Parcelable { IShellCallback mShellCallback; class MyShellCallback extends IShellCallback.Stub { - public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) { - return onOpenOutputFile(path, seLinuxContext); + public ParcelFileDescriptor openFile(String path, String seLinuxContext, + String mode) { + return onOpenFile(path, seLinuxContext, mode); } } @@ -48,23 +49,27 @@ public class ShellCallback implements Parcelable { } /** - * Ask the shell to open a file for writing. This will truncate the file if it - * already exists. It will create the file if it doesn't exist. + * Ask the shell to open a file. If opening for writing, will truncate the file if it + * already exists and will create the file if it doesn't exist. * @param path Path of the file to be opened/created. * @param seLinuxContext Optional SELinux context that must be allowed to have * access to the file; if null, nothing is required. + * @param mode Mode to open file in: "r" for input/reading an existing file, + * "r+" for reading/writing an existing file, "w" for output/writing a new file (either + * creating or truncating an existing one), "w+" for reading/writing a new file (either + * creating or truncating an existing one). */ - public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) { - if (DEBUG) Log.d(TAG, "openOutputFile " + this + ": mLocal=" + mLocal + public ParcelFileDescriptor openFile(String path, String seLinuxContext, String mode) { + if (DEBUG) Log.d(TAG, "openFile " + this + " mode=" + mode + ": mLocal=" + mLocal + " mShellCallback=" + mShellCallback); if (mLocal) { - return onOpenOutputFile(path, seLinuxContext); + return onOpenFile(path, seLinuxContext, mode); } if (mShellCallback != null) { try { - return mShellCallback.openOutputFile(path, seLinuxContext); + return mShellCallback.openFile(path, seLinuxContext, mode); } catch (RemoteException e) { Log.w(TAG, "Failure opening " + path, e); } @@ -72,7 +77,7 @@ public class ShellCallback implements Parcelable { return null; } - public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { + public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, String mode) { return null; } diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java index 6223235e628f..d75219fdfd11 100644 --- a/core/java/android/os/ShellCommand.java +++ b/core/java/android/os/ShellCommand.java @@ -226,10 +226,10 @@ public abstract class ShellCommand { * Helper for just system services to ask the shell to open an output file. * @hide */ - public ParcelFileDescriptor openOutputFileForSystem(String path) { + public ParcelFileDescriptor openFileForSystem(String path, String mode) { try { - ParcelFileDescriptor pfd = getShellCallback().openOutputFile(path, - "u:r:system_server:s0"); + ParcelFileDescriptor pfd = getShellCallback().openFile(path, + "u:r:system_server:s0", mode); if (pfd != null) { return pfd; } diff --git a/core/java/com/android/internal/os/IShellCallback.aidl b/core/java/com/android/internal/os/IShellCallback.aidl index 57d67890d840..57043424fc47 100644 --- a/core/java/com/android/internal/os/IShellCallback.aidl +++ b/core/java/com/android/internal/os/IShellCallback.aidl @@ -20,5 +20,5 @@ import android.os.ParcelFileDescriptor; /** @hide */ interface IShellCallback { - ParcelFileDescriptor openOutputFile(String path, String seLinuxContext); + ParcelFileDescriptor openFile(String path, String seLinuxContext, String mode); } diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index b137da3ef792..c6828c4f60de 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -568,6 +568,35 @@ static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject cla return (res) ? (jint)cookie : 0; } +static jint android_content_AssetManager_addAssetFd(JNIEnv* env, jobject clazz, + jobject fileDescriptor, jstring debugPathName, + jboolean appAsLib) +{ + ScopedUtfChars debugPathName8(env, debugPathName); + + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); + if (fd < 0) { + jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor"); + return 0; + } + + AssetManager* am = assetManagerForJavaObject(env, clazz); + if (am == NULL) { + return 0; + } + + int dupfd = ::dup(fd); + if (dupfd < 0) { + jniThrowIOException(env, errno); + return 0; + } + + int32_t cookie; + bool res = am->addAssetFd(dupfd, String8(debugPathName8.c_str()), &cookie, appAsLib); + + return (res) ? static_cast<jint>(cookie) : 0; +} + static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz) { AssetManager* am = assetManagerForJavaObject(env, clazz); @@ -1673,6 +1702,8 @@ static const JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_getAssetRemainingLength }, { "addAssetPathNative", "(Ljava/lang/String;Z)I", (void*) android_content_AssetManager_addAssetPath }, + { "addAssetFdNative", "(Ljava/io/FileDescriptor;Ljava/lang/String;Z)I", + (void*) android_content_AssetManager_addAssetFd }, { "addOverlayPathNative", "(Ljava/lang/String;)I", (void*) android_content_AssetManager_addOverlayPath }, { "isUpToDate", "()Z", diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 5603508eaf09..3c8736ea0c4c 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -150,6 +150,14 @@ AssetManager::~AssetManager() { ALOGI("Destroying AssetManager in %p #%d\n", this, count); } + // Manually close any fd paths for which we have not yet opened their zip (which + // will take ownership of the fd and close it when done). + for (size_t i=0; i<mAssetPaths.size(); i++) { + if (mAssetPaths[i].rawFd >= 0 && mAssetPaths[i].zip == NULL) { + close(mAssetPaths[i].rawFd); + } + } + delete mConfig; delete mResources; @@ -280,7 +288,35 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie) } return true; - } +} + +bool AssetManager::addAssetFd( + int fd, const String8& debugPathName, int32_t* cookie, bool appAsLib, + bool assume_ownership) { + AutoMutex _l(mLock); + + asset_path ap; + + ap.path = debugPathName; + ap.rawFd = fd; + ap.type = kFileTypeRegular; + ap.assumeOwnership = assume_ownership; + + ALOGV("In %p Asset fd %d name: %s", this, fd, ap.path.string()); + + mAssetPaths.add(ap); + + // new paths are always added at the end + if (cookie) { + *cookie = static_cast<int32_t>(mAssetPaths.size()); + } + + if (mResources != NULL) { + appendPathToResTable(ap, appAsLib); + } + + return true; +} bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath, uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize) @@ -505,7 +541,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) con Asset* idmap = openIdmapLocked(ap); size_t nextEntryIdx = mResources->getTableCount(); ALOGV("Looking for resource asset in '%s'\n", ap.path.string()); - if (ap.type != kFileTypeDirectory) { + if (ap.type != kFileTypeDirectory && ap.rawFd < 0) { if (nextEntryIdx == 0) { // The first item is typically the framework resources, // which we want to avoid parsing every time. @@ -738,6 +774,8 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m { Asset* pAsset = NULL; + ALOGV("openNonAssetInPath: name=%s type=%d fd=%d", fileName, ap.type, ap.rawFd); + /* look at the filesystem on disk */ if (ap.type == kFileTypeDirectory) { String8 path(ap.path); @@ -752,7 +790,7 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m } if (pAsset != NULL) { - //printf("FOUND NA '%s' on disk\n", fileName); + ALOGV("FOUND NA '%s' on disk", fileName); pAsset->setAssetSource(path); } @@ -763,10 +801,10 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m /* check the appropriate Zip file */ ZipFileRO* pZip = getZipFileLocked(ap); if (pZip != NULL) { - //printf("GOT zip, checking NA '%s'\n", (const char*) path); + ALOGV("GOT zip, checking NA '%s'", (const char*) path); ZipEntryRO entry = pZip->findEntryByName(path.string()); if (entry != NULL) { - //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon); + ALOGV("FOUND NA in Zip file for %s", (const char*) path); pAsset = openAssetFromZipLocked(pZip, entry, mode, path); pZip->releaseEntry(entry); } @@ -817,7 +855,17 @@ ZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap) { ALOGV("getZipFileLocked() in %p\n", this); - return mZipSet.getZip(ap.path); + if (ap.zip != NULL) { + return ap.zip->getZip(); + } + + if (ap.rawFd < 0) { + ap.zip = mZipSet.getSharedZip(ap.path); + } else { + ap.zip = SharedZip::create(ap.rawFd, ap.path); + + } + return ap.zip != NULL ? ap.zip->getZip() : NULL; } /* @@ -1374,6 +1422,21 @@ AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) } } +AssetManager::SharedZip::SharedZip(int fd, const String8& path) + : mPath(path), mZipFile(NULL), mModWhen(0), + mResourceTableAsset(NULL), mResourceTable(NULL) +{ + if (kIsDebug) { + ALOGI("Creating SharedZip %p fd=%d %s\n", this, fd, (const char*)mPath); + } + ALOGV("+++ opening zip fd=%d '%s'\n", fd, mPath.string()); + mZipFile = ZipFileRO::openFd(fd, mPath.string()); + if (mZipFile == NULL) { + ::close(fd); + ALOGD("failed to open Zip archive fd=%d '%s'\n", fd, mPath.string()); + } +} + sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path, bool createIfNotPresent) { @@ -1389,7 +1452,11 @@ sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path, zip = new SharedZip(path, modWhen); gOpen.add(path, zip); return zip; +} +sp<AssetManager::SharedZip> AssetManager::SharedZip::create(int fd, const String8& path) +{ + return new SharedZip(fd, path); } ZipFileRO* AssetManager::SharedZip::getZip() @@ -1500,19 +1567,23 @@ void AssetManager::ZipSet::closeZip(int idx) mZipFile.editItemAt(idx) = NULL; } - /* * Retrieve the appropriate Zip file from the set. */ ZipFileRO* AssetManager::ZipSet::getZip(const String8& path) { + return getSharedZip(path)->getZip(); +} + +const sp<AssetManager::SharedZip> AssetManager::ZipSet::getSharedZip(const String8& path) +{ int idx = getIndex(path); sp<SharedZip> zip = mZipFile[idx]; if (zip == NULL) { zip = SharedZip::get(path); mZipFile.editItemAt(idx) = zip; } - return zip->getZip(); + return zip; } Asset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path) diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp index 49fe8a261178..6e2ca60cc3d3 100644 --- a/libs/androidfw/ZipFileRO.cpp +++ b/libs/androidfw/ZipFileRO.cpp @@ -55,7 +55,9 @@ private: ZipFileRO::~ZipFileRO() { CloseArchive(mHandle); - free(mFileName); + if (mFileName != NULL) { + free(mFileName); + } } /* @@ -76,6 +78,20 @@ ZipFileRO::~ZipFileRO() { } +/* static */ ZipFileRO* ZipFileRO::openFd(int fd, const char* debugFileName, + bool assume_ownership) +{ + ZipArchiveHandle handle; + const int32_t error = OpenArchiveFd(fd, debugFileName, &handle, assume_ownership); + if (error) { + ALOGW("Error opening archive fd %d %s: %s", fd, debugFileName, ErrorCodeString(error)); + CloseArchive(handle); + return NULL; + } + + return new ZipFileRO(handle, strdup(debugFileName)); +} + ZipEntryRO ZipFileRO::findEntryByName(const char* entryName) const { _ZipEntryRO* data = new _ZipEntryRO; @@ -139,7 +155,8 @@ bool ZipFileRO::startIteration(void** cookie, const char* prefix, const char* su prefix ? &pe : NULL, suffix ? &se : NULL); if (error) { - ALOGW("Could not start iteration over %s: %s", mFileName, ErrorCodeString(error)); + ALOGW("Could not start iteration over %s: %s", mFileName != NULL ? mFileName : "<null>", + ErrorCodeString(error)); delete ze; return false; } @@ -154,7 +171,8 @@ ZipEntryRO ZipFileRO::nextEntry(void* cookie) int32_t error = Next(ze->cookie, &(ze->entry), &(ze->name)); if (error) { if (error != -1) { - ALOGW("Error iteration over %s: %s", mFileName, ErrorCodeString(error)); + ALOGW("Error iteration over %s: %s", mFileName != NULL ? mFileName : "<null>", + ErrorCodeString(error)); } return NULL; } diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h index 0441b9d789e2..4254614c8448 100644 --- a/libs/androidfw/include/androidfw/AssetManager.h +++ b/libs/androidfw/include/androidfw/AssetManager.h @@ -92,6 +92,20 @@ public: bool addOverlayPath(const String8& path, int32_t* cookie); /* + * Add a new source for assets from an already open file descriptor. + * This does not give full AssetManager functionality for these assets, + * since the origin of the file is not known for purposes of sharing, + * overlay resolution, and other features. However it does allow you + * to do simple access to the contents of the given fd as an apk file. + * + * Returns "true" on success, "false" on failure. If 'cookie' is non-NULL, + * then on success, *cookie is set to the value corresponding to the + * newly-added asset source. + */ + bool addAssetFd(int fd, const String8& debugPathName, int32_t* cookie, + bool appAsLib=false, bool assume_ownership=true); + + /* * Convenience for adding the standard system assets. Uses the * ANDROID_ROOT environment variable to find them. */ @@ -195,15 +209,20 @@ public: uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize); private: + class SharedZip; + struct asset_path { - asset_path() : path(""), type(kFileTypeRegular), idmap(""), - isSystemOverlay(false), isSystemAsset(false) {} + asset_path() : path(""), rawFd(-1), type(kFileTypeRegular), idmap(""), + isSystemOverlay(false), isSystemAsset(false), assumeOwnership(false) {} String8 path; + int rawFd; FileType type; String8 idmap; bool isSystemOverlay; bool isSystemAsset; + bool assumeOwnership; + mutable sp<SharedZip> zip; }; Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode, @@ -238,6 +257,7 @@ private: class SharedZip : public RefBase { public: static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true); + static sp<SharedZip> create(int fd, const String8& path); ZipFileRO* getZip(); @@ -257,6 +277,7 @@ private: private: SharedZip(const String8& path, time_t modWhen); + SharedZip(int fd, const String8& path); SharedZip(); // <-- not implemented String8 mPath; @@ -290,6 +311,8 @@ private: */ ZipFileRO* getZip(const String8& path); + const sp<SharedZip> getSharedZip(const String8& path); + Asset* getZipResourceTableAsset(const String8& path); Asset* setZipResourceTableAsset(const String8& path, Asset* asset); diff --git a/libs/androidfw/include/androidfw/ZipFileRO.h b/libs/androidfw/include/androidfw/ZipFileRO.h index 768034287afa..03154d04def1 100644 --- a/libs/androidfw/include/androidfw/ZipFileRO.h +++ b/libs/androidfw/include/androidfw/ZipFileRO.h @@ -80,6 +80,12 @@ public: static ZipFileRO* open(const char* zipFileName); /* + * Open an archive from an already open file descriptor. + */ + static ZipFileRO* openFd(int fd, const char* debugFileName, + bool assume_ownership = true); + + /* * Find an entry, by name. Returns the entry identifier, or NULL if * not found. */ diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index f9422656c7db..d6bd2b317a97 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -373,7 +373,7 @@ final class ActivityManagerShellCommand extends ShellCommand { if (mProfileFile != null || mAgent != null) { ParcelFileDescriptor fd = null; if (mProfileFile != null) { - fd = openOutputFileForSystem(mProfileFile); + fd = openFileForSystem(mProfileFile, "w"); if (fd == null) { return 1; } @@ -668,7 +668,7 @@ final class ActivityManagerShellCommand extends ShellCommand { File file = new File(filename); file.delete(); - ParcelFileDescriptor fd = openOutputFileForSystem(filename); + ParcelFileDescriptor fd = openFileForSystem(filename, "w"); if (fd == null) { return -1; } @@ -756,7 +756,7 @@ final class ActivityManagerShellCommand extends ShellCommand { if (start) { profileFile = getNextArgRequired(); - fd = openOutputFileForSystem(profileFile); + fd = openFileForSystem(profileFile, "w"); if (fd == null) { return -1; } @@ -820,7 +820,7 @@ final class ActivityManagerShellCommand extends ShellCommand { File file = new File(heapFile); file.delete(); - ParcelFileDescriptor fd = openOutputFileForSystem(heapFile); + ParcelFileDescriptor fd = openFileForSystem(heapFile, "w"); if (fd == null) { return -1; } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index a2099e6080e5..807eb1a8aac4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -54,6 +54,7 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.IUserManager; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -78,7 +79,6 @@ import dalvik.system.DexFile; import libcore.io.IoUtils; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -102,8 +102,6 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO class PackageManagerShellCommand extends ShellCommand { /** Path for streaming APK content */ private static final String STDIN_PATH = "-"; - /** Whether or not APK content must be streamed from stdin */ - private static final boolean FORCE_STREAM_INSTALL = true; final IPackageManager mInterface; final private WeakHashMap<String, Resources> mResourceCache = @@ -255,30 +253,27 @@ class PackageManagerShellCommand extends ShellCommand { } private void setParamsSize(InstallParams params, String inPath) { - // If we're forced to stream the package, the params size - // must be set via command-line argument. There's nothing - // to do here. - if (FORCE_STREAM_INSTALL) { - return; - } - final PrintWriter pw = getOutPrintWriter(); if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) { - File file = new File(inPath); - if (file.isFile()) { + final ParcelFileDescriptor fd = openFileForSystem(inPath, "r"); + if (fd == null) { + getErrPrintWriter().println("Error: Can't open file: " + inPath); + throw new IllegalArgumentException("Error: Can't open file: " + inPath); + } + try { + ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0); + PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, + null, null); + params.sessionParams.setSize(PackageHelper.calculateInstalledSize( + pkgLite, params.sessionParams.abiOverride)); + } catch (PackageParserException | IOException e) { + getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath); + throw new IllegalArgumentException( + "Error: Failed to parse APK file: " + inPath, e); + } finally { try { - ApkLite baseApk = PackageParser.parseApkLite(file, 0); - PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, - null, null); - params.sessionParams.setSize(PackageHelper.calculateInstalledSize( - pkgLite, params.sessionParams.abiOverride)); - } catch (PackageParserException | IOException e) { - pw.println("Error: Failed to parse APK file: " + file); - throw new IllegalArgumentException( - "Error: Failed to parse APK file: " + file, e); + fd.close(); + } catch (IOException e) { } - } else { - pw.println("Error: Can't open non-file: " + inPath); - throw new IllegalArgumentException("Error: Can't open non-file: " + inPath); } } } @@ -1914,6 +1909,12 @@ class PackageManagerShellCommand extends ShellCommand { throw new IllegalArgumentException("Missing inherit package name"); } break; + case "--pkg": + sessionParams.appPackageName = getNextArg(); + if (sessionParams.appPackageName == null) { + throw new IllegalArgumentException("Missing package name"); + } + break; case "-S": final long sizeBytes = Long.parseLong(getNextArg()); if (sizeBytes <= 0) { @@ -1925,6 +1926,7 @@ class PackageManagerShellCommand extends ShellCommand { sessionParams.abiOverride = checkAbiArgument(getNextArg()); break; case "--ephemeral": + case "--instant": case "--instantapp": sessionParams.setInstallAsInstantApp(true /*isInstantApp*/); break; @@ -2092,20 +2094,24 @@ class PackageManagerShellCommand extends ShellCommand { private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); - if (FORCE_STREAM_INSTALL && inPath != null && !STDIN_PATH.equals(inPath)) { - pw.println("Error: APK content must be streamed"); - return 1; - } + final ParcelFileDescriptor fd; if (STDIN_PATH.equals(inPath)) { - inPath = null; + fd = null; } else if (inPath != null) { - final File file = new File(inPath); - if (file.isFile()) { - sizeBytes = file.length(); + fd = openFileForSystem(inPath, "r"); + if (fd == null) { + return -1; + } + sizeBytes = fd.getStatSize(); + if (sizeBytes < 0) { + getErrPrintWriter().println("Unable to get size of: " + inPath); + return -1; } + } else { + fd = null; } if (sizeBytes <= 0) { - pw.println("Error: must specify a APK size"); + getErrPrintWriter().println("Error: must specify a APK size"); return 1; } @@ -2118,8 +2124,8 @@ class PackageManagerShellCommand extends ShellCommand { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); - if (inPath != null) { - in = new FileInputStream(inPath); + if (fd != null) { + in = new ParcelFileDescriptor.AutoCloseInputStream(fd); } else { in = new SizedInputStream(getRawInputStream(), sizeBytes); } @@ -2144,7 +2150,7 @@ class PackageManagerShellCommand extends ShellCommand { } return 0; } catch (IOException e) { - pw.println("Error: failed to write; " + e.getMessage()); + getErrPrintWriter().println("Error: failed to write; " + e.getMessage()); return 1; } finally { IoUtils.closeQuietly(out); diff --git a/services/coverage/java/com/android/server/coverage/CoverageService.java b/services/coverage/java/com/android/server/coverage/CoverageService.java index d600aa8c4276..ed8d24aa3b8f 100644 --- a/services/coverage/java/com/android/server/coverage/CoverageService.java +++ b/services/coverage/java/com/android/server/coverage/CoverageService.java @@ -112,7 +112,7 @@ public class CoverageService extends Binder { } // Try to open the destination file - ParcelFileDescriptor fd = openOutputFileForSystem(dest); + ParcelFileDescriptor fd = openFileForSystem(dest, "w"); if (fd == null) { return -1; } |