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

Commit 85490371 authored by TYM Tsai's avatar TYM Tsai
Browse files

Fix NullPointerException in PackageUtil.getPackageInfo

Fix issue and code refactor

Bug: 397021179
Flag: EXEMPT Bug fix
Test: atest CtsPackageInstallerCUJInstallationTestCases
Test: atest CtsPackageInstallTestCases
Change-Id: Idf6891fff632744caa0c5deb1868fca160145ac9
parent b08353eb
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -52,8 +52,11 @@ import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * This is a utility class for defining some utility methods and constants
@@ -69,7 +72,8 @@ public class PackageUtil {
    //intent attribute strings related to uninstall
    public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName";
    private static final String DOWNLOADS_AUTHORITY = "downloads";
    private static final String SPLIT_BASE_APK_END_WITH = "base.apk";
    private static final String SPLIT_BASE_APK_SUFFIX = "base.apk";
    private static final String SPLIT_APK_SUFFIX = ".apk";

    /**
     * Utility method to get package information for a given {@link File}
@@ -77,12 +81,21 @@ public class PackageUtil {
    @Nullable
    public static PackageInfo getPackageInfo(Context context, File sourceFile, int flags) {
        String filePath = sourceFile.getAbsolutePath();
        if (filePath.endsWith(SPLIT_BASE_APK_END_WITH)) {
        if (filePath.endsWith(SPLIT_BASE_APK_SUFFIX)) {
            File dir = sourceFile.getParentFile();
            if (dir.listFiles().length > 1) {
            try (Stream<Path> list = Files.list(dir.toPath())) {
                long count = list
                        .filter((name) -> name.endsWith(SPLIT_APK_SUFFIX))
                        .limit(2)
                        .count();
                if (count > 1) {
                    // split apks, use file directory to get archive info
                    filePath = dir.getPath();
                }
            } catch (Exception ignored) {
                // No access to the parent directory, proceed to read app snippet
                // from the base apk only
            }
        }
        try {
            return context.getPackageManager().getPackageArchiveInfo(filePath, flags);
@@ -240,9 +253,10 @@ public class PackageUtil {
        appInfo.publicSourceDir = archiveFilePath;

        if (appInfo.splitNames != null && appInfo.splitSourceDirs == null) {
            final File[] files = sourceFile.getParentFile().listFiles();
            final File[] files = sourceFile.getParentFile().listFiles(
                    (dir, name) -> name.endsWith(SPLIT_APK_SUFFIX));
            final String[] splits = Arrays.stream(appInfo.splitNames)
                    .map(i -> findFilePath(files, i + ".apk"))
                    .map(i -> findFilePath(files, i + SPLIT_APK_SUFFIX))
                    .filter(Objects::nonNull)
                    .toArray(String[]::new);

@@ -283,7 +297,9 @@ public class PackageUtil {
    }

    private static String findFilePath(File[] files, String postfix) {
        for (File file : files) {
        final int length = files != null ? files.length : 0;
        for (int i = 0; i < length; i++) {
            File file = files[i];
            final String path = file.getAbsolutePath();
            if (path.endsWith(postfix)) {
                return path;
+17 −3
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ import android.util.Log
import com.android.packageinstaller.v2.model.PackageUtil.getAppSnippet
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize

@@ -48,6 +50,7 @@ object PackageUtil {
    private val LOG_TAG = InstallRepository::class.java.simpleName
    private const val DOWNLOADS_AUTHORITY = "downloads"
    private const val SPLIT_BASE_APK_SUFFIX = "base.apk"
    private const val SPLIT_APK_SUFFIX = ".apk"
    const val localLogv = false

    const val ARGS_ABORT_REASON: String = "abort_reason"
@@ -440,11 +443,22 @@ object PackageUtil {
        var filePath = sourceFile.absolutePath
        if (filePath.endsWith(SPLIT_BASE_APK_SUFFIX)) {
            val dir = sourceFile.parentFile
            if ((dir?.listFiles()?.size ?: 0) > 1) {
            try {
                Files.list(dir.toPath()).use { list ->
                    val count: Long = list
                        .filter { name: Path -> name.endsWith(SPLIT_APK_SUFFIX) }
                        .limit(2)
                        .count()
                    if (count > 1) {
                        // split apks, use file directory to get archive info
                        filePath = dir.path
                    }
                }
            } catch (ignored: Exception) {
                // No access to the parent directory, proceed to read app snippet
                // from the base apk only
            }
        }
        return try {
            context.packageManager.getPackageArchiveInfo(filePath, flags)
        } catch (ignored: Exception) {