Define an OEM directory, scan features and APKs.
To support OEM customizations, define a new top-level directory
that roughly mirrors the layout of the system partition. Scan this
location for (non-privileged) apps, and for additional features.
Bug: 13340779
Change-Id: Idb6d6626655061ee31ad952cab734d30ea6130b9
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 54e2c0b..e96398a 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -41,6 +41,7 @@
private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE";
private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE";
private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
+ private static final String ENV_OEM_ROOT = "OEM_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -55,6 +56,7 @@
public static final String DIRECTORY_ANDROID = DIR_ANDROID;
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_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");
private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
@@ -205,13 +207,24 @@
}
/**
- * Gets the Android root directory.
+ * Return root of the "system" partition holding the core Android OS.
+ * Always present and mounted read-only.
*/
public static File getRootDirectory() {
return DIR_ANDROID_ROOT;
}
/**
+ * Return root directory of the "oem" partition holding OEM customizations,
+ * if any. If present, the partition is mounted read-only.
+ *
+ * @hide
+ */
+ public static File getOemDirectory() {
+ return DIR_OEM_ROOT;
+ }
+
+ /**
* Gets the system directory available for secure storage.
* If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
* Otherwise, it returns the unencrypted /data/system directory.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cbcf408..32de6cd 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -302,12 +302,15 @@
// This is the object monitoring the privileged system app dir.
final FileObserver mPrivilegedInstallObserver;
- // This is the object monitoring the system app dir.
+ // This is the object monitoring the vendor app dir.
final FileObserver mVendorInstallObserver;
// This is the object monitoring the vendor overlay package dir.
final FileObserver mVendorOverlayInstallObserver;
+ // This is the object monitoring the OEM app dir.
+ final FileObserver mOemInstallObserver;
+
// This is the object monitoring mAppInstallDir.
final FileObserver mAppInstallObserver;
@@ -1157,7 +1160,12 @@
sUserManager = new UserManagerService(context, this,
mInstallLock, mPackages);
- readPermissions();
+ // Read permissions and features from system
+ readPermissions(Environment.buildPath(
+ Environment.getRootDirectory(), "etc", "permissions"), false);
+ // Only read features from OEM
+ readPermissions(Environment.buildPath(
+ Environment.getOemDirectory(), "etc", "permissions"), true);
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
@@ -1343,6 +1351,14 @@
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
+ // Collect all OEM packages.
+ File oemAppDir = new File(Environment.getOemDirectory(), "app");
+ mOemInstallObserver = new AppDirObserver(
+ oemAppDir.getPath(), OBSERVER_EVENTS, true, false);
+ mOemInstallObserver.startWatching();
+ scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
+
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
@@ -1581,9 +1597,8 @@
mSettings.removePackageLPw(ps.name);
}
- void readPermissions() {
+ void readPermissions(File libraryDir, boolean onlyFeatures) {
// Read permissions from .../etc/permission directory.
- File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Slog.w(TAG, "No directory " + libraryDir + ", skipping");
return;
@@ -1609,16 +1624,16 @@
continue;
}
- readPermissionsFromXml(f);
+ readPermissionsFromXml(f, onlyFeatures);
}
// Read permissions from .../etc/permissions/platform.xml last so it will take precedence
final File permFile = new File(Environment.getRootDirectory(),
"etc/permissions/platform.xml");
- readPermissionsFromXml(permFile);
+ readPermissionsFromXml(permFile, onlyFeatures);
}
- private void readPermissionsFromXml(File permFile) {
+ private void readPermissionsFromXml(File permFile, boolean onlyFeatures) {
FileReader permReader = null;
try {
permReader = new FileReader(permFile);
@@ -1640,7 +1655,7 @@
}
String name = parser.getName();
- if ("group".equals(name)) {
+ if ("group".equals(name) && !onlyFeatures) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = Process.getGidForName(gidStr);
@@ -1652,7 +1667,7 @@
XmlUtils.skipCurrentTag(parser);
continue;
- } else if ("permission".equals(name)) {
+ } else if ("permission".equals(name) && !onlyFeatures) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<permission> without name at "
@@ -1663,7 +1678,7 @@
perm = perm.intern();
readPermission(parser, perm);
- } else if ("assign-permission".equals(name)) {
+ } else if ("assign-permission".equals(name) && !onlyFeatures) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<assign-permission> without name at "
@@ -1695,7 +1710,7 @@
perms.add(perm);
XmlUtils.skipCurrentTag(parser);
- } else if ("library".equals(name)) {
+ } else if ("library".equals(name) && !onlyFeatures) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");
if (lname == null) {