Loading core/java/android/content/pm/PackageManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. Loading core/java/android/content/pm/PackageParser.java +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading core/java/android/os/Environment.java +11 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading @@ -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( Loading Loading @@ -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). Loading services/core/java/com/android/server/pm/PackageManagerService.java +53 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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()); Loading @@ -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()); Loading @@ -4374,6 +4398,12 @@ public class PackageManagerService extends IPackageManager.Stub { } } } if (isPrebundled) { synchronized (mPackages) { mSettings.writePrebundledPackagesLPr(); } } } private static File getSettingsProblemFile() { Loading Loading @@ -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 Loading services/core/java/com/android/server/pm/Settings.java +61 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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"); Loading Loading
core/java/android/content/pm/PackageManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
core/java/android/content/pm/PackageParser.java +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
core/java/android/os/Environment.java +11 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading @@ -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( Loading Loading @@ -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). Loading
services/core/java/com/android/server/pm/PackageManagerService.java +53 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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()); Loading @@ -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()); Loading @@ -4374,6 +4398,12 @@ public class PackageManagerService extends IPackageManager.Stub { } } } if (isPrebundled) { synchronized (mPackages) { mSettings.writePrebundledPackagesLPr(); } } } private static File getSettingsProblemFile() { Loading Loading @@ -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 Loading
services/core/java/com/android/server/pm/Settings.java +61 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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"); Loading