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

Commit 7ce75047 authored by emancebo's avatar emancebo
Browse files

Revert "Revert "PackageManagerService: Create means of installing prebundled applications""

This reverts commit b06c364f.
parent b06c364f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -820,6 +820,14 @@ public abstract class PackageManager {
    @SystemApi
    public static final int INSTALL_FAILED_THEME_UNKNOWN_ERROR = -402;

    /**
     * Used for prebundles
     * Installation failed for a prebundled app because the user previously uninstalled it
     * and we don't want to bring it back
     * @hide
     */
    public static final int INSTALL_FAILED_UNINSTALLED_PREBUNDLE = -403;

    /**
     * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
     * package's data directory.
+1 −0
Original line number Diff line number Diff line
@@ -634,6 +634,7 @@ public class PackageParser {
    public final static int PARSE_IS_PRIVILEGED = 1<<7;
    public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
    public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
    public final static int PARSE_IS_PREBUNDLED_DIR = 1<<10;

    private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();

+11 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ public class Environment {
    private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
    private static final String ENV_OEM_ROOT = "OEM_ROOT";
    private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
    private static final String ENV_PREBUNDLED_ROOT = "PREBUNDLED_ROOT";

    /** {@hide} */
    public static final String DIR_ANDROID = "Android";
@@ -61,6 +62,7 @@ public class Environment {
    private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
    private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
    private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
    private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/vendor/bundled-app");
    private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");

    private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
@@ -274,6 +276,15 @@ public class Environment {
        return DIR_VENDOR_ROOT;
    }

    /**
     * Return the root directory for "prebundled" apps.  These apps will be installed directly
     * from this partition but will not be marked as system apps and will hence be uninstallable.
     * @hide
     */
    public static File getPrebundledDirectory() {
        return DIR_PREBUNDLED_ROOT;
    }

    /**
     * Gets the system directory available for secure storage.
     * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
+53 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIB
import static android.content.pm.PackageManager.INSTALL_FAILED_USER_RESTRICTED;
import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_FAILED_UNINSTALLED_PREBUNDLE;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
@@ -60,6 +61,7 @@ import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
import android.app.PackageInstallObserver;
import android.util.ArrayMap;
import com.android.internal.R;
@@ -1692,6 +1694,10 @@ public class PackageManagerService extends IPackageManager.Stub {
            scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            // Collect all prebundled packages.
            scanDirLI(Environment.getPrebundledDirectory(),
                    PackageParser.PARSE_IS_PREBUNDLED_DIR, scanFlags, 0);
            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
            mInstaller.moveFiles();
@@ -4350,6 +4356,13 @@ public class PackageManagerService extends IPackageManager.Stub {
                    + " flags=0x" + Integer.toHexString(parseFlags));
        }
        boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0;
        if (isPrebundled) {
            synchronized (mPackages) {
                mSettings.readPrebundledPackagesLPr();
            }
        }
        for (File file : files) {
            final boolean isPackage = (isApkFile(file) || file.isDirectory())
                    && !PackageInstallerService.isStageName(file.getName());
@@ -4360,6 +4373,17 @@ public class PackageManagerService extends IPackageManager.Stub {
            try {
                scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
                        scanFlags, currentTime, null);
                if (isPrebundled) {
                    final PackageParser.Package pkg;
                    try {
                        pkg = new PackageParser().parsePackage(file, parseFlags);
                    } catch (PackageParserException e) {
                        throw PackageManagerException.from(e);
                    }
                    synchronized (mPackages) {
                        mSettings.markPrebundledPackageInstalledLPr(pkg.packageName);
                    }
                }
            } catch (PackageManagerException e) {
                Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
@@ -4374,6 +4398,12 @@ public class PackageManagerService extends IPackageManager.Stub {
                }
            }
        }
        if (isPrebundled) {
            synchronized (mPackages) {
                mSettings.writePrebundledPackagesLPr();
            }
        }
    }
    private static File getSettingsProblemFile() {
@@ -4466,6 +4496,29 @@ public class PackageManagerService extends IPackageManager.Stub {
            throw PackageManagerException.from(e);
        }
        if ((parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0) {
            synchronized (mPackages) {
                PackageSetting existingSettings = mSettings.peekPackageLPr(pkg.packageName);
                if (mSettings.wasPrebundledPackageInstalledLPr(pkg.packageName) &&
                        existingSettings == null) {
                    // The prebundled app was installed at some point in time, but now it is
                    // gone.  Assume that the user uninstalled it intentionally: do not reinstall.
                    throw new PackageManagerException(INSTALL_FAILED_UNINSTALLED_PREBUNDLE,
                            "skip reinstall for " + pkg.packageName);
                } else if (existingSettings != null
                        && existingSettings.versionCode >= pkg.mVersionCode
                        && !existingSettings.codePathString.contains(
                                Environment.getPrebundledDirectory().getPath())) {
                    // This app is installed in a location that is not the prebundled location
                    // and has a higher (or same) version as the prebundled one.  Skip
                    // installing the prebundled version.
                    Slog.d(TAG, pkg.packageName + " already installed at " +
                            existingSettings.codePathString);
                    return null; // return null so we still mark package as installed
                }
            }
        }
        PackageSetting ps = null;
        PackageSetting updatedPkg;
        // reader
+61 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.internal.util.XmlUtils;
import com.android.server.pm.PackageManagerService.DumpState;

import java.util.Collection;
import java.util.HashSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -63,15 +64,20 @@ import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.PackageUserState;
import android.content.pm.VerifierDeviceIdentity;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -169,12 +175,15 @@ final class Settings {
    private final File mPackageListFilename;
    private final File mStoppedPackagesFilename;
    private final File mBackupStoppedPackagesFilename;
    private final File mPrebundledPackagesFilename;

    final HashMap<String, PackageSetting> mPackages =
            new HashMap<String, PackageSetting>();
    // List of replaced system applications
    private final HashMap<String, PackageSetting> mDisabledSysPackages =
        new HashMap<String, PackageSetting>();
    private final HashSet<String> mPrebundledPackages =
            new HashSet<String>();

    private static int mFirstAvailableUid = 0;

@@ -275,6 +284,7 @@ final class Settings {
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
        mPackageListFilename = new File(mSystemDir, "packages.list");
        FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
        mPrebundledPackagesFilename = new File(mSystemDir, "prebundled-packages.list");

        // Deprecated: Needed for migration
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
@@ -1775,6 +1785,57 @@ final class Settings {
        //Debug.stopMethodTracing();
    }

    void writePrebundledPackagesLPr() {
        PrintWriter writer = null;
        try {
            writer = new PrintWriter(
                    new BufferedWriter(new FileWriter(mPrebundledPackagesFilename, false)));
            for (String packageName : mPrebundledPackages) {
                writer.println(packageName);
            }
        } catch (IOException e) {
            Slog.e(PackageManagerService.TAG, "Unable to write prebundled package list", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    void readPrebundledPackagesLPr() {
        if (!mPrebundledPackagesFilename.exists()) {
            return;
        }

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(mPrebundledPackagesFilename));
            String packageName = reader.readLine();
            while (packageName != null) {
                if (!TextUtils.isEmpty(packageName)) {
                    mPrebundledPackages.add(packageName);
                }
                packageName = reader.readLine();
            }
        } catch (IOException e) {
            Slog.e(PackageManagerService.TAG, "Unable to read prebundled package list", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {}
            }
        }
    }

    void markPrebundledPackageInstalledLPr(String packageName) {
        mPrebundledPackages.add(packageName);
    }

    boolean wasPrebundledPackageInstalledLPr(String packageName) {
        return mPrebundledPackages.contains(packageName);
    }

    void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
            throws java.io.IOException {
        serializer.startTag(null, "updated-package");