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

Commit 8af7e4bb authored by William Loh's avatar William Loh Committed by Android (Google) Code Review
Browse files

Merge "Extract ASL-in-APK as a raw resource" into main

parents ba22693e 29e4bbf0
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -270,11 +270,20 @@ public abstract class PackageManager {
    /**
     * Application level {@link android.content.pm.PackageManager.Property PackageManager
     * .Property} for a app to inform the installer that a file containing the app's android
     * safety label data is bundled into the APK at the given path.
     * safety label data is bundled into the APK as a raw resource.
     *
     * <p>For example:
     * <pre>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.content.PROPERTY_ANDROID_SAFETY_LABEL"
     *     android:resource="@raw/app-metadata"/&gt;
     * &lt;/application&gt;
     * </pre>
     * @hide
     */
    public static final String PROPERTY_ANDROID_SAFETY_LABEL_PATH =
            "android.content.SAFETY_LABEL_PATH";
    public static final String PROPERTY_ANDROID_SAFETY_LABEL =
            "android.content.PROPERTY_ANDROID_SAFETY_LABEL";

    /**
     * A property value set within the manifest.
+3 −2
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_UID_CHANGED;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL_PATH;
import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
@@ -505,6 +505,7 @@ final class InstallPackageHelper {
        // metadata file path for the new package.
        if (oldPkgSetting != null) {
            pkgSetting.setAppMetadataFilePath(null);
            pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
        }
        // If the app metadata file path is not null then this is a system app with a preloaded app
        // metadata file on the system image. Do not reset the path and source if this is the
@@ -523,7 +524,7 @@ final class InstallPackageHelper {
                }
            } else if (Flags.aslInApkAppMetadataSource()) {
                Map<String, PackageManager.Property> properties = pkg.getProperties();
                if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
                if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL)) {
                    // ASL file extraction is done in post-install
                    pkgSetting.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
                    pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_APK);
+43 −21
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL_PATH;
import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL;
import static android.content.pm.SigningDetails.CertCapabilities.SHARED_USER_ID;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
@@ -71,8 +71,12 @@ import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.ApkAssets;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.Debug;
import android.os.Environment;
import android.os.FileUtils;
@@ -93,6 +97,7 @@ import android.system.Os;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LogPrinter;
import android.util.Printer;
@@ -147,11 +152,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Class containing helper methods for the PackageManagerService.
@@ -1668,11 +1672,11 @@ public class PackageManagerServiceUtils {
            return true;
        }
        Map<String, Property> properties = pkg.getProperties();
        if (!properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
        if (!properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL)) {
            return false;
        }
        Property fileInAPkPathProperty = properties.get(PROPERTY_ANDROID_SAFETY_LABEL_PATH);
        if (!fileInAPkPathProperty.isString()) {
        Property fileInApkProperty = properties.get(PROPERTY_ANDROID_SAFETY_LABEL);
        if (!fileInApkProperty.isResourceId()) {
            return false;
        }
        if (isSystem && !appMetadataFile.getParentFile().exists()) {
@@ -1684,28 +1688,46 @@ public class PackageManagerServiceUtils {
                return false;
            }
        }
        String fileInApkPath = fileInAPkPathProperty.getString();
        List<AndroidPackageSplit> splits = pkg.getSplits();
        AssetManager.Builder builder = new AssetManager.Builder();
        for (int i = 0; i < splits.size(); i++) {
            try (ZipFile zipFile = new ZipFile(splits.get(i).getPath())) {
                ZipEntry zipEntry = zipFile.getEntry(fileInApkPath);
                if (zipEntry != null
                        && (isSystem || zipEntry.getSize() <= getAppMetadataSizeLimit())) {
                    try (InputStream in = zipFile.getInputStream(zipEntry)) {
            try {
                builder.addApkAssets(ApkAssets.loadFromPath(splits.get(i).getPath()));
            } catch (IOException e) {
                Slog.e(TAG, "Failed to load resources from APK " + splits.get(i).getPath());
            }
        }
        AssetManager assetManager = builder.build();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        displayMetrics.setToDefaults();
        Resources res = new Resources(assetManager, displayMetrics, null);
        AtomicBoolean copyFailed = new AtomicBoolean(false);
        try (InputStream in = res.openRawResource(fileInApkProperty.getResourceId())) {
            try (FileOutputStream out = new FileOutputStream(appMetadataFile)) {
                if (isSystem) {
                    FileUtils.copy(in, out);
                            Os.chmod(appMetadataFile.getAbsolutePath(),
                                    APP_METADATA_FILE_ACCESS_MODE);
                            return true;
                } else {
                    long sizeLimit = getAppMetadataSizeLimit();
                    CancellationSignal signal = new CancellationSignal();
                    FileUtils.copy(in, out, signal, Runnable::run, (long progress) -> {
                        if (progress > sizeLimit) {
                            copyFailed.set(true);
                            signal.cancel();
                        }
                    });
                }
                Os.chmod(appMetadataFile.getAbsolutePath(),
                        APP_METADATA_FILE_ACCESS_MODE);
            }
        } catch (Exception e) {
            Slog.e(TAG, e.getMessage());
            copyFailed.set(true);
        } finally {
            if (copyFailed.get()) {
                appMetadataFile.delete();
            }
        }
        return false;
        return !copyFailed.get();
    }

    public static void linkFilesToOldDirs(@NonNull Installer installer,