Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01704e76 authored by Kenny Root's avatar Kenny Root Committed by Android (Google) Code Review
Browse files

Merge "Better error codes for missing files"

parents a841e524 1ebd74ac
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -598,7 +598,12 @@ public class PackageParser {
            assmgr = new AssetManager();
            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    Build.VERSION.RESOURCES_SDK_INT);

            int cookie = assmgr.addAssetPath(packageFilePath);
            if (cookie == 0) {
                return null;
            }

            parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
        } catch (Exception e) {
            if (assmgr != null) assmgr.close();
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.content;

import android.os.Build;
@@ -17,6 +33,12 @@ public class NativeLibraryHelper {

    private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);

    /**
     * Sums the size of native binaries in an APK.
     *
     * @param apkFile APK file to scan for native libraries
     * @return size of all native binary files in bytes
     */
    public static long sumNativeBinariesLI(File apkFile) {
        final String cpuAbi = Build.CPU_ABI;
        final String cpuAbi2 = Build.CPU_ABI2;
@@ -26,6 +48,14 @@ public class NativeLibraryHelper {
    private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
            String cpuAbi, String cpuAbi2);

    /**
     * Copies native binaries to a shared library directory.
     *
     * @param apkFile APK file to scan for native libraries
     * @param sharedLibraryDir directory for libraries to be copied to
     * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
     *         error code from that class if not
     */
    public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
        final String cpuAbi = Build.CPU_ABI;
        final String cpuAbi2 = Build.CPU_ABI2;
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ public class PackageHelper {
    public static final int RECOMMEND_FAILED_INVALID_LOCATION = -3;
    public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4;
    public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
    public static final int RECOMMEND_FAILED_INVALID_URI = -6;

    private static final boolean localLOGV = true;
    private static final String TAG = "PackageHelper";
    // App installation location settings values
+42 −33
Original line number Diff line number Diff line
@@ -51,15 +51,17 @@

namespace android {

typedef void (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);

// These match PackageManager.java install codes
typedef enum {
    INSTALL_SUCCEEDED = 0,
    INSTALL_SUCCEEDED = 1,
    INSTALL_FAILED_INVALID_APK = -2,
    INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
    INSTALL_FAILED_CONTAINER_ERROR = -18,
    INSTALL_FAILED_INTERNAL_ERROR = -110,
} install_status_t;

typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);

// Equivalent to isFilenameSafe
static bool
isFilenameSafe(const char* filename)
@@ -140,17 +142,19 @@ isFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime,
    return false;
}

static void
static install_status_t
sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
{
    size_t* total = (size_t*) arg;
    size_t uncompLen;

    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) {
        return;
        return INSTALL_FAILED_INVALID_APK;
    }

    *total += uncompLen;

    return INSTALL_SUCCEEDED;
}

/*
@@ -158,7 +162,7 @@ sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const
 *
 * This function assumes the library and path names passed in are considered safe.
 */
static void
static install_status_t
copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
{
    jstring* javaNativeLibPath = (jstring*) arg;
@@ -170,7 +174,8 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
    time_t modTime;

    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) {
        return;
        LOGD("Couldn't read zip entry info\n");
        return INSTALL_FAILED_INVALID_APK;
    } else {
        struct tm t;
        ZipFileRO::zipTimeToTimespec(when, &t);
@@ -182,50 +187,50 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
    char localFileName[nativeLibPath.size() + fileNameLen + 2];

    if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) {
        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
        return;
        LOGD("Couldn't allocate local file name for library");
        return INSTALL_FAILED_INTERNAL_ERROR;
    }

    *(localFileName + nativeLibPath.size()) = '/';

    if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName)
                    - nativeLibPath.size() - 1) != fileNameLen) {
        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
        return;
        LOGD("Couldn't allocate local file name for library");
        return INSTALL_FAILED_INTERNAL_ERROR;
    }

    // Only copy out the native file if it's different.
    struct stat st;
    if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
        return;
        return INSTALL_SUCCEEDED;
    }

    char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2];
    if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
            != nativeLibPath.size()) {
        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
        return;
        LOGD("Couldn't allocate local file name for library");
        return INSTALL_FAILED_INTERNAL_ERROR;
    }

    *(localFileName + nativeLibPath.size()) = '/';

    if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
                    TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) {
        LOGI("Couldn't allocate temporary file name for library: %s", strerror(errno));
        return;
        LOGI("Couldn't allocate temporary file name for library");
        return INSTALL_FAILED_INTERNAL_ERROR;
    }

    int fd = mkstemp(localTmpFileName);
    if (fd < 0) {
        LOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
        return;
        return INSTALL_FAILED_CONTAINER_ERROR;
    }

    if (!zipFile->uncompressEntry(zipEntry, fd)) {
        LOGI("Failed uncompressing %s to %s: %s", fileName, localTmpFileName, strerror(errno));
        LOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
        close(fd);
        unlink(localTmpFileName);
        return;
        return INSTALL_FAILED_CONTAINER_ERROR;
    }

    close(fd);
@@ -238,7 +243,7 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
    if (utimes(localTmpFileName, times) < 0) {
        LOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
        unlink(localTmpFileName);
        return;
        return INSTALL_FAILED_CONTAINER_ERROR;
    }

    // Set the mode to 755
@@ -246,17 +251,19 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
    if (chmod(localTmpFileName, mode) < 0) {
        LOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
        unlink(localTmpFileName);
        return;
        return INSTALL_FAILED_CONTAINER_ERROR;
    }

    // Finally, rename it to the final name.
    if (rename(localTmpFileName, localFileName) < 0) {
        LOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
        unlink(localTmpFileName);
        return;
        return INSTALL_FAILED_CONTAINER_ERROR;
    }

    LOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);

    return INSTALL_SUCCEEDED;
}

static install_status_t
@@ -301,10 +308,7 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js
        }

        const char* lastSlash = strrchr(fileName, '/');
        if (lastSlash == NULL) {
            LOG_ASSERT("last slash was null somehow for %s\n", fileName);
            continue;
        }
        LOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);

        // Check to make sure the CPU ABI of this file is one we support.
        const char* cpuAbiOffset = fileName + APK_LIB_LEN;
@@ -325,12 +329,17 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js
        }

        // If this is a .so file, check to see if we need to copy it.
        if (!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
        if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
                    && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
                && isFilenameSafe(lastSlash + 1)) {
            callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
        } else if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
            callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
                    && isFilenameSafe(lastSlash + 1))
                || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {

            install_status_t ret = callFunc(env, callArg, &zipFile, entry, lastSlash + 1);

            if (ret != INSTALL_SUCCEEDED) {
                LOGV("Failure for entry %s", lastSlash + 1);
                return ret;
            }
        }
    }

@@ -341,7 +350,7 @@ static jint
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
        jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
{
    return iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
    return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
            copyFileIfChanged, &javaNativeLibPath);
}

+7 −0
Original line number Diff line number Diff line
@@ -3114,6 +3114,13 @@ public class PackageManagerTests extends AndroidTestCase {
                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
    }

    @LargeTest
    public void testInstallNonexistentFile() {
        int retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
        File invalidFile = new File("/nonexistent-file.apk");
        invokeInstallPackageFail(Uri.fromFile(invalidFile), 0, retCode);
    }

    /*---------- Recommended install location tests ----*/
    /*
     * TODO's
Loading