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

Commit f3f2f4cc authored by Peter Li's avatar Peter Li Committed by Android (Google) Code Review
Browse files

Merge "New public API to get the information of AndroidManifest.xml" into main

parents ac4089a9 76c2c47c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12781,6 +12781,7 @@ package android.content.pm {
    method public boolean isPackageSuspended();
    method @CheckResult public abstract boolean isPermissionRevokedByPolicy(@NonNull String, @NonNull String);
    method public abstract boolean isSafeMode();
    method @FlaggedApi("android.content.pm.get_package_info") @WorkerThread public <T> T parseAndroidManifest(@NonNull String, @NonNull java.util.function.Function<android.content.res.XmlResourceParser,T>) throws java.io.IOException;
    method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
    method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
+33 −0
Original line number Diff line number Diff line
@@ -80,6 +80,8 @@ import android.content.pm.SuspendDialogInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
import android.content.pm.dex.ArtManager;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.res.ApkAssets;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -144,6 +146,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;

/** @hide */
public class ApplicationPackageManager extends PackageManager {
@@ -4024,4 +4027,34 @@ public class ApplicationPackageManager extends PackageManager {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public <T> T parseAndroidManifest(@NonNull String apkFilePath,
            @NonNull Function<XmlResourceParser, T> parserFunction) throws IOException {
        Objects.requireNonNull(apkFilePath, "apkFilePath cannot be null");
        Objects.requireNonNull(parserFunction, "parserFunction cannot be null");
        try (XmlResourceParser xmlResourceParser = getAndroidManifestParser(apkFilePath)) {
            return parserFunction.apply(xmlResourceParser);
        } catch (IOException e) {
            Log.w(TAG, "Failed to get the android manifest parser", e);
            throw e;
        }
    }

    private static XmlResourceParser getAndroidManifestParser(@NonNull String apkFilePath)
            throws IOException {
        ApkAssets apkAssets = null;
        try {
            apkAssets = ApkAssets.loadFromPath(apkFilePath);
            return apkAssets.openXml(ApkLiteParseUtils.ANDROID_MANIFEST_FILENAME);
        } finally {
            if (apkAssets != null) {
                try {
                    apkAssets.close();
                } catch (Throwable ignored) {
                    Log.w(TAG, "Failed to close apkAssets", ignored);
                }
            }
        }
    }
}
+59 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.annotation.XmlRes;
import android.app.ActivityManager;
import android.app.ActivityThread;
@@ -96,6 +97,7 @@ import com.android.internal.util.DataClass;
import dalvik.system.VMRuntime;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.cert.Certificate;
@@ -108,6 +110,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Class for retrieving various kinds of information related to the application
@@ -11426,4 +11429,60 @@ public abstract class PackageManager {
        throw new UnsupportedOperationException(
                "unregisterPackageMonitorCallback not implemented in subclass");
    }

    /**
     * Retrieve AndroidManifest.xml information for the given application apk path.
     *
     * <p>Example:
     *
     * <pre><code>
     * Bundle result;
     * try {
     *     result = getContext().getPackageManager().parseAndroidManifest(apkFilePath,
     *             xmlResourceParser -> {
     *                 Bundle bundle = new Bundle();
     *                 // Search the start tag
     *                 int type;
     *                 while ((type = xmlResourceParser.next()) != XmlPullParser.START_TAG
     *                         &amp;&amp; type != XmlPullParser.END_DOCUMENT) {
     *                 }
     *                 if (type != XmlPullParser.START_TAG) {
     *                     return bundle;
     *                 }
     *
     *                 // Start to read the tags and attributes from the xmlResourceParser
     *                 if (!xmlResourceParser.getName().equals("manifest")) {
     *                     return bundle;
     *                 }
     *                 String packageName = xmlResourceParser.getAttributeValue(null, "package");
     *                 bundle.putString("package", packageName);
     *
     *                 // Continue to read the tags and attributes from the xmlResourceParser
     *
     *                 return bundle;
     *             });
     * } catch (IOException e) {
     * }
     * </code></pre>
     *
     * Note: When the parserFunction is invoked, the client can read the AndroidManifest.xml
     * information by the XmlResourceParser object. After leaving the parserFunction, the
     * XmlResourceParser object will be closed.
     *
     * @param apkFilePath The path of an application apk file.
     * @param parserFunction The parserFunction will be invoked with the XmlResourceParser object
     *        after getting the AndroidManifest.xml of an application package.
     *
     * @return Returns the result of the {@link Function#apply(Object)}.
     *
     * @throws IOException if the AndroidManifest.xml of an application package cannot be
     *             read or accessed.
     */
    @FlaggedApi(android.content.pm.Flags.FLAG_GET_PACKAGE_INFO)
    @WorkerThread
    public <T> T parseAndroidManifest(@NonNull String apkFilePath,
            @NonNull Function<XmlResourceParser, T> parserFunction) throws IOException {
        throw new UnsupportedOperationException(
                "parseAndroidManifest not implemented in subclass");
    }
}