Search in sources :

Example 1 with PackageParserException

use of android.content.pm.PackageParser.PackageParserException in project android_frameworks_base by ResurrectionRemix.

the class PackageInstallerSession method validateInstallLocked.

/**
     * Validate install by confirming that all application packages are have
     * consistent package name, version code, and signing certificates.
     * <p>
     * Clears and populates {@link #mResolvedBaseFile},
     * {@link #mResolvedStagedFiles}, and {@link #mResolvedInheritedFiles}.
     * <p>
     * Renames package files in stage to match split names defined inside.
     * <p>
     * Note that upgrade compatibility is still performed by
     * {@link PackageManagerService}.
     */
private void validateInstallLocked(PackageInfo pkgInfo, ApplicationInfo appInfo) throws PackageManagerException {
    mPackageName = null;
    mVersionCode = -1;
    mSignatures = null;
    mResolvedBaseFile = null;
    mResolvedStagedFiles.clear();
    mResolvedInheritedFiles.clear();
    final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
    final List<String> removeSplitList = new ArrayList<>();
    if (!ArrayUtils.isEmpty(removedFiles)) {
        for (File removedFile : removedFiles) {
            final String fileName = removedFile.getName();
            final String splitName = fileName.substring(0, fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length());
            removeSplitList.add(splitName);
        }
    }
    final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
    if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
        throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
    }
    // Verify that all staged packages are internally consistent
    final ArraySet<String> stagedSplits = new ArraySet<>();
    for (File addedFile : addedFiles) {
        final ApkLite apk;
        try {
            apk = PackageParser.parseApkLite(addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
        } catch (PackageParserException e) {
            throw PackageManagerException.from(e);
        }
        if (!stagedSplits.add(apk.splitName)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Split " + apk.splitName + " was defined multiple times");
        }
        // Use first package to define unknown values
        if (mPackageName == null) {
            mPackageName = apk.packageName;
            mVersionCode = apk.versionCode;
        }
        if (mSignatures == null) {
            mSignatures = apk.signatures;
            mCertificates = apk.certificates;
        }
        assertApkConsistent(String.valueOf(addedFile), apk);
        // Take this opportunity to enforce uniform naming
        final String targetName;
        if (apk.splitName == null) {
            targetName = "base.apk";
        } else {
            targetName = "split_" + apk.splitName + ".apk";
        }
        if (!FileUtils.isValidExtFilename(targetName)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Invalid filename: " + targetName);
        }
        final File targetFile = new File(mResolvedStageDir, targetName);
        if (!addedFile.equals(targetFile)) {
            addedFile.renameTo(targetFile);
        }
        // Base is coming from session
        if (apk.splitName == null) {
            mResolvedBaseFile = targetFile;
        }
        mResolvedStagedFiles.add(targetFile);
    }
    if (removeSplitList.size() > 0) {
        // validate split names marked for removal
        for (String splitName : removeSplitList) {
            if (!ArrayUtils.contains(pkgInfo.splitNames, splitName)) {
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Split not found: " + splitName);
            }
        }
        // ensure we've got appropriate package name, version code and signatures
        if (mPackageName == null) {
            mPackageName = pkgInfo.packageName;
            mVersionCode = pkgInfo.versionCode;
        }
        if (mSignatures == null) {
            mSignatures = pkgInfo.signatures;
        }
    }
    if (params.mode == SessionParams.MODE_FULL_INSTALL) {
        // Full installs must include a base package
        if (!stagedSplits.contains(null)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Full install must include a base package");
        }
    } else {
        // Partial installs must be consistent with existing install
        if (appInfo == null) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Missing existing base package for " + mPackageName);
        }
        final PackageLite existing;
        final ApkLite existingBase;
        try {
            existing = PackageParser.parsePackageLite(new File(appInfo.getCodePath()), 0);
            existingBase = PackageParser.parseApkLite(new File(appInfo.getBaseCodePath()), PackageParser.PARSE_COLLECT_CERTIFICATES);
        } catch (PackageParserException e) {
            throw PackageManagerException.from(e);
        }
        assertApkConsistent("Existing base", existingBase);
        // Inherit base if not overridden
        if (mResolvedBaseFile == null) {
            mResolvedBaseFile = new File(appInfo.getBaseCodePath());
            mResolvedInheritedFiles.add(mResolvedBaseFile);
        }
        // Inherit splits if not overridden
        if (!ArrayUtils.isEmpty(existing.splitNames)) {
            for (int i = 0; i < existing.splitNames.length; i++) {
                final String splitName = existing.splitNames[i];
                final File splitFile = new File(existing.splitCodePaths[i]);
                final boolean splitRemoved = removeSplitList.contains(splitName);
                if (!stagedSplits.contains(splitName) && !splitRemoved) {
                    mResolvedInheritedFiles.add(splitFile);
                }
            }
        }
        // Inherit compiled oat directory.
        final File packageInstallDir = (new File(appInfo.getBaseCodePath())).getParentFile();
        mInheritedFilesBase = packageInstallDir;
        final File oatDir = new File(packageInstallDir, "oat");
        if (oatDir.exists()) {
            final File[] archSubdirs = oatDir.listFiles();
            // instruction set hierarchy and link compiled output.
            if (archSubdirs != null && archSubdirs.length > 0) {
                final String[] instructionSets = InstructionSets.getAllDexCodeInstructionSets();
                for (File archSubDir : archSubdirs) {
                    // Skip any directory that isn't an ISA subdir.
                    if (!ArrayUtils.contains(instructionSets, archSubDir.getName())) {
                        continue;
                    }
                    mResolvedInstructionSets.add(archSubDir.getName());
                    List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
                    if (!oatFiles.isEmpty()) {
                        mResolvedInheritedFiles.addAll(oatFiles);
                    }
                }
            }
        }
    }
}
Also used : ArraySet(android.util.ArraySet) PackageParserException(android.content.pm.PackageParser.PackageParserException) PackageLite(android.content.pm.PackageParser.PackageLite) ArrayList(java.util.ArrayList) ApkLite(android.content.pm.PackageParser.ApkLite) File(java.io.File)

Example 2 with PackageParserException

use of android.content.pm.PackageParser.PackageParserException in project android_frameworks_base by ResurrectionRemix.

the class PackageManagerShellCommand method runInstall.

private int runInstall() throws RemoteException {
    final PrintWriter pw = getOutPrintWriter();
    final InstallParams params = makeInstallParams();
    final String inPath = getNextArg();
    boolean installExternal = (params.sessionParams.installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
    if (params.sessionParams.sizeBytes < 0 && inPath != null) {
        File file = new File(inPath);
        if (file.isFile()) {
            if (installExternal) {
                try {
                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
                    params.sessionParams.setSize(PackageHelper.calculateInstalledSize(pkgLite, false, params.sessionParams.abiOverride));
                } catch (PackageParserException | IOException e) {
                    pw.println("Error: Failed to parse APK file : " + e);
                    return 1;
                }
            } else {
                params.sessionParams.setSize(file.length());
            }
        }
    }
    final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId);
    boolean abandonSession = true;
    try {
        if (inPath == null && params.sessionParams.sizeBytes == 0) {
            pw.println("Error: must either specify a package size or an APK file");
            return 1;
        }
        if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        if (doCommitSession(sessionId, false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        abandonSession = false;
        pw.println("Success");
        return 0;
    } finally {
        if (abandonSession) {
            try {
                doAbandonSession(sessionId, false);
            } catch (Exception ignore) {
            }
        }
    }
}
Also used : ApkLite(android.content.pm.PackageParser.ApkLite) PackageParserException(android.content.pm.PackageParser.PackageParserException) PackageLite(android.content.pm.PackageParser.PackageLite) IOException(java.io.IOException) DexFile(dalvik.system.DexFile) File(java.io.File) URISyntaxException(java.net.URISyntaxException) RemoteException(android.os.RemoteException) IOException(java.io.IOException) PackageParserException(android.content.pm.PackageParser.PackageParserException) PrintWriter(java.io.PrintWriter)

Example 3 with PackageParserException

use of android.content.pm.PackageParser.PackageParserException in project android_frameworks_base by ResurrectionRemix.

the class Pm method runInstall.

/*
     * Keep this around to support existing users of the "pm install" command that may not be
     * able to be updated [or, at least informed the API has changed] such as ddmlib.
     *
     * Moving the implementation of "pm install" to "cmd package install" changes the executing
     * context. Instead of being a stand alone process, "cmd package install" runs in the
     * system_server process. Due to SELinux rules, system_server cannot access many directories;
     * one of which being the package install staging directory [/data/local/tmp].
     *
     * The use of "adb install" or "cmd package install" over "pm install" is highly encouraged.
     */
private int runInstall() throws RemoteException {
    final InstallParams params = makeInstallParams();
    final String inPath = nextArg();
    boolean installExternal = (params.sessionParams.installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
    if (params.sessionParams.sizeBytes < 0 && inPath != null) {
        File file = new File(inPath);
        if (file.isFile()) {
            if (installExternal) {
                try {
                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
                    params.sessionParams.setSize(PackageHelper.calculateInstalledSize(pkgLite, false, params.sessionParams.abiOverride));
                } catch (PackageParserException | IOException e) {
                    System.err.println("Error: Failed to parse APK file : " + e);
                    return 1;
                }
            } else {
                params.sessionParams.setSize(file.length());
            }
        }
    }
    final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId);
    try {
        if (inPath == null && params.sessionParams.sizeBytes == 0) {
            System.err.println("Error: must either specify a package size or an APK file");
            return 1;
        }
        if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        if (doCommitSession(sessionId, false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        System.out.println("Success");
        return 0;
    } finally {
        try {
            mInstaller.abandonSession(sessionId);
        } catch (Exception ignore) {
        }
    }
}
Also used : ApkLite(android.content.pm.PackageParser.ApkLite) PackageParserException(android.content.pm.PackageParser.PackageParserException) PackageLite(android.content.pm.PackageParser.PackageLite) IOException(java.io.IOException) File(java.io.File) RemoteException(android.os.RemoteException) IOException(java.io.IOException) PackageParserException(android.content.pm.PackageParser.PackageParserException)

Example 4 with PackageParserException

use of android.content.pm.PackageParser.PackageParserException in project android_frameworks_base by DirtyUnicorns.

the class PackageManager method getPackageArchiveInfo.

/**
     * Retrieve overall information about an application package defined
     * in a package archive file
     *
     * @param archiveFilePath The path to the archive file
     * @param flags Additional option flags. Use any combination of
     *         {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
     *         {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
     *         {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
     *         {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
     *         {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
     *         {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
     *         {@link #MATCH_UNINSTALLED_PACKAGES}
     *         to modify the data returned.
     *
     * @return A PackageInfo object containing information about the
     *         package archive. If the package could not be parsed,
     *         returns null.
     *
     * @see #GET_ACTIVITIES
     * @see #GET_CONFIGURATIONS
     * @see #GET_GIDS
     * @see #GET_INSTRUMENTATION
     * @see #GET_INTENT_FILTERS
     * @see #GET_META_DATA
     * @see #GET_PERMISSIONS
     * @see #GET_PROVIDERS
     * @see #GET_RECEIVERS
     * @see #GET_SERVICES
     * @see #GET_SHARED_LIBRARY_FILES
     * @see #GET_SIGNATURES
     * @see #GET_URI_PERMISSION_PATTERNS
     * @see #MATCH_DISABLED_COMPONENTS
     * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
     * @see #MATCH_UNINSTALLED_PACKAGES
     *
     */
public PackageInfo getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags) {
    final PackageParser parser = new PackageParser();
    final File apkFile = new File(archiveFilePath);
    try {
        if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
        // Caller expressed an explicit opinion about what encryption
        // aware/unaware components they want to see, so fall through and
        // give them what they want
        } else {
            // Caller expressed no opinion, so match everything
            flags |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
        }
        PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
        if ((flags & GET_SIGNATURES) != 0) {
            PackageParser.collectCertificates(pkg, 0);
        }
        PackageUserState state = new PackageUserState();
        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
    } catch (PackageParserException e) {
        return null;
    }
}
Also used : PackageParserException(android.content.pm.PackageParser.PackageParserException) File(java.io.File)

Example 5 with PackageParserException

use of android.content.pm.PackageParser.PackageParserException in project android_frameworks_base by AOSPA.

the class Pm method runInstall.

/*
     * Keep this around to support existing users of the "pm install" command that may not be
     * able to be updated [or, at least informed the API has changed] such as ddmlib.
     *
     * Moving the implementation of "pm install" to "cmd package install" changes the executing
     * context. Instead of being a stand alone process, "cmd package install" runs in the
     * system_server process. Due to SELinux rules, system_server cannot access many directories;
     * one of which being the package install staging directory [/data/local/tmp].
     *
     * The use of "adb install" or "cmd package install" over "pm install" is highly encouraged.
     */
private int runInstall() throws RemoteException {
    final InstallParams params = makeInstallParams();
    final String inPath = nextArg();
    boolean installExternal = (params.sessionParams.installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
    if (params.sessionParams.sizeBytes < 0 && inPath != null) {
        File file = new File(inPath);
        if (file.isFile()) {
            if (installExternal) {
                try {
                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
                    params.sessionParams.setSize(PackageHelper.calculateInstalledSize(pkgLite, false, params.sessionParams.abiOverride));
                } catch (PackageParserException | IOException e) {
                    System.err.println("Error: Failed to parse APK file : " + e);
                    return 1;
                }
            } else {
                params.sessionParams.setSize(file.length());
            }
        }
    }
    final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId);
    try {
        if (inPath == null && params.sessionParams.sizeBytes == 0) {
            System.err.println("Error: must either specify a package size or an APK file");
            return 1;
        }
        if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        if (doCommitSession(sessionId, false) != PackageInstaller.STATUS_SUCCESS) {
            return 1;
        }
        System.out.println("Success");
        return 0;
    } finally {
        try {
            mInstaller.abandonSession(sessionId);
        } catch (Exception ignore) {
        }
    }
}
Also used : ApkLite(android.content.pm.PackageParser.ApkLite) PackageParserException(android.content.pm.PackageParser.PackageParserException) PackageLite(android.content.pm.PackageParser.PackageLite) IOException(java.io.IOException) File(java.io.File) RemoteException(android.os.RemoteException) IOException(java.io.IOException) PackageParserException(android.content.pm.PackageParser.PackageParserException)

Aggregations

PackageParserException (android.content.pm.PackageParser.PackageParserException)30 File (java.io.File)28 PackageLite (android.content.pm.PackageParser.PackageLite)21 ApkLite (android.content.pm.PackageParser.ApkLite)19 IOException (java.io.IOException)14 ArrayList (java.util.ArrayList)10 RemoteException (android.os.RemoteException)9 DexFile (dalvik.system.DexFile)8 ArraySet (android.util.ArraySet)5 PackageParser (android.content.pm.PackageParser)4 PackageParser.isApkFile (android.content.pm.PackageParser.isApkFile)4 StrictJarFile (android.util.jar.StrictJarFile)4 PrintWriter (java.io.PrintWriter)4 URISyntaxException (java.net.URISyntaxException)4