summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java13
-rw-r--r--core/java/android/content/pm/PackageParser.java5
-rw-r--r--core/java/android/os/Environment.java12
-rw-r--r--core/java/com/android/server/SystemConfig.java26
-rw-r--r--core/jni/android_util_AssetManager.cpp4
-rw-r--r--core/jni/fd_utils.cpp6
-rw-r--r--libs/androidfw/AssetManager.cpp1
-rw-r--r--libs/androidfw/include/androidfw/AssetManager.h1
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java102
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java31
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java4
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java1
-rw-r--r--services/core/java/com/android/server/pm/Settings.java3
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java4
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java29
-rw-r--r--tests/libs-permissions/Android.mk15
-rw-r--r--tests/libs-permissions/product/com.android.test.libs.product.xml20
-rw-r--r--tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java29
-rw-r--r--tests/privapp-permissions/Android.mk14
-rw-r--r--tests/privapp-permissions/product/AndroidManifest.xml23
-rw-r--r--tests/privapp-permissions/product/privapp-permissions-test.xml6
22 files changed, 331 insertions, 25 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 746a090264c2..f6697e8148a0 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -602,6 +602,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public static final int PRIVATE_FLAG_VENDOR = 1 << 18;
+ /**
+ * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * product partition of the system image.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -619,6 +626,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
PRIVATE_FLAG_OEM,
PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
PRIVATE_FLAG_PRIVILEGED,
+ PRIVATE_FLAG_PRODUCT,
PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
PRIVATE_FLAG_VENDOR,
@@ -1699,6 +1707,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ /** @hide */
+ public boolean isProduct() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
/**
* Returns whether or not this application was installed as a virtual preload.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c705ef52f6b5..d1ce72ed1011 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6379,6 +6379,11 @@ public class PackageParser {
}
/** @hide */
+ public boolean isProduct() {
+ return applicationInfo.isProduct();
+ }
+
+ /** @hide */
public boolean isPrivileged() {
return applicationInfo.isPrivilegedApp();
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 62731e84a401..d543a0222d46 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -41,6 +41,7 @@ public class Environment {
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_ODM_ROOT = "ODM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
+ private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -62,6 +63,7 @@ public class Environment {
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
+ private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -180,6 +182,16 @@ public class Environment {
}
/**
+ * Return root directory of the "product" partition holding product-specific
+ * customizations if any. If present, the partition is mounted read-only.
+ *
+ * @hide
+ */
+ public static File getProductDirectory() {
+ return DIR_PRODUCT_ROOT;
+ }
+
+ /**
* Return the system directory for a user. This is for use by system
* services to store files relating to the user. This directory will be
* automatically deleted when the user is removed.
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c5af89727575..111934f9d005 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -149,6 +149,9 @@ public class SystemConfig {
final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
+
final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
public static SystemConfig getInstance() {
@@ -240,6 +243,14 @@ public class SystemConfig {
return mVendorPrivAppDenyPermissions.get(packageName);
}
+ public ArraySet<String> getProductPrivAppPermissions(String packageName) {
+ return mProductPrivAppPermissions.get(packageName);
+ }
+
+ public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
+ return mProductPrivAppDenyPermissions.get(packageName);
+ }
+
public Map<String, Boolean> getOemPermissions(String packageName) {
final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
if (oemPermissions != null) {
@@ -278,6 +289,14 @@ public class SystemConfig {
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
+
+ // Allow Product to customize system configs around libs, features, permissions and apps
+ int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+ ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}
void readPermissions(File libraryDir, int permissionFlag) {
@@ -598,15 +617,20 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
- // privapp permissions from system and vendor partitions are stored
+ // privapp permissions from system, vendor and product partitions are stored
// separately. This is to prevent xml files in the vendor partition from
// granting permissions to priv apps in the system partition and vice
// versa.
boolean vendor = permFile.toPath().startsWith(
Environment.getVendorDirectory().toPath());
+ boolean product = permFile.toPath().startsWith(
+ Environment.getProductDirectory().toPath());
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
+ } else if (product) {
+ readPrivAppPermissions(parser, mProductPrivAppPermissions,
+ mProductPrivAppDenyPermissions);
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 403937be7088..7e17a4909cee 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -174,6 +174,10 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
argv[argc++] = AssetManager::OVERLAY_DIR;
}
+ if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
+ }
+
// Finally, invoke idmap (if any overlay directory exists)
if (argc > 5) {
execv(AssetManager::IDMAP_BIN, (char* const*)argv);
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 956b7249660f..3b7b14c58d0a 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -85,11 +85,15 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
static const char* kOverlayDir = "/system/vendor/overlay/";
static const char* kVendorOverlayDir = "/vendor/overlay";
static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kSystemProductOverlayDir = "/system/product/overlay/";
+ static const char* kProductOverlayDir = "/product/overlay";
static const char* kApkSuffix = ".apk";
if ((android::base::StartsWith(path, kOverlayDir)
|| android::base::StartsWith(path, kOverlaySubdir)
- || android::base::StartsWith(path, kVendorOverlayDir))
+ || android::base::StartsWith(path, kVendorOverlayDir)
+ || android::base::StartsWith(path, kSystemProductOverlayDir)
+ || android::base::StartsWith(path, kProductOverlayDir))
&& android::base::EndsWith(path, kApkSuffix)
&& path.find("/../") == std::string::npos) {
return true;
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 0485625e81e8..a5698af18f6b 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -73,6 +73,7 @@ static volatile int32_t gCount = 0;
const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
const char* AssetManager::TARGET_PACKAGE_NAME = "android";
const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index ecc5dc1ad331..08da7319de85 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -60,6 +60,7 @@ public:
static const char* RESOURCES_FILENAME;
static const char* IDMAP_BIN;
static const char* OVERLAY_DIR;
+ static const char* PRODUCT_OVERLAY_DIR;
/*
* If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
* APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 03950119ea13..4fddec9c133e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -361,9 +361,10 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
continue;
}
- // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
- // /data/ota and moved into the dalvik-cache already.
- if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+ // If the path is in /system, /vendor or /product, ignore. It will have been
+ // ota-dexopted into /data/ota and moved into the dalvik-cache already.
+ if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
+ || pkg.codePath.startsWith("/product")) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5dfd3ae4b8e8..704646571f06 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -464,6 +464,7 @@ public class PackageManagerService extends IPackageManager.Stub
static final int SCAN_AS_PRIVILEGED = 1<<18;
static final int SCAN_AS_OEM = 1<<19;
static final int SCAN_AS_VENDOR = 1<<20;
+ static final int SCAN_AS_PRODUCT = 1<<21;
@IntDef(flag = true, prefix = { "SCAN_" }, value = {
SCAN_NO_DEX,
@@ -568,6 +569,8 @@ public class PackageManagerService extends IPackageManager.Stub
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
+ private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
+
private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob";
/** Canonical intent used to identify what counts as a "web browser" app */
@@ -2550,7 +2553,7 @@ public class PackageManagerService extends IPackageManager.Stub
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
- // Collect vendor overlay packages. (Do this before scanning any apps.)
+ // Collect vendor/product overlay packages. (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in the right directory.
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
@@ -2560,6 +2563,13 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
+ scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
@@ -2593,8 +2603,7 @@ public class PackageManagerService extends IPackageManager.Stub
0);
// Collected privileged vendor packages.
- File privilegedVendorAppDir = new File(Environment.getVendorDirectory(),
- "priv-app");
+ File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
@@ -2634,6 +2643,37 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_OEM,
0);
+ // Collected privileged product packages.
+ File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
+ try {
+ privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(privilegedProductAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED,
+ 0);
+
+ // Collect ordinary product packages.
+ File productAppDir = new File(Environment.getProductDirectory(), "app");
+ try {
+ productAppDir = productAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(productAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
+
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
// Stub packages must either be replaced with full versions in the /data
@@ -2840,6 +2880,23 @@ Slog.e("TODD",
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM;
+ } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED;
+ } else if (FileUtils.contains(productAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
@@ -9826,6 +9883,7 @@ Slog.e("TODD",
* <li>{@link #SCAN_AS_PRIVILEGED}</li>
* <li>{@link #SCAN_AS_OEM}</li>
* <li>{@link #SCAN_AS_VENDOR}</li>
+ * <li>{@link #SCAN_AS_PRODUCT}</li>
* <li>{@link #SCAN_AS_INSTANT_APP}</li>
* <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
* </ul>
@@ -9848,6 +9906,10 @@ Slog.e("TODD",
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if ((disabledPkgSetting.pkgPrivateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
}
if (pkgSetting != null) {
final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -10626,6 +10688,10 @@ Slog.e("TODD",
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR;
}
+ if ((scanFlags & SCAN_AS_PRODUCT) != 0) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+ }
+
if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
@@ -11672,6 +11738,8 @@ Slog.e("TODD",
codeRoot = Environment.getOemDirectory();
} else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
codeRoot = Environment.getVendorDirectory();
+ } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
+ codeRoot = Environment.getProductDirectory();
} else {
// Unrecognized code path; take its top real segment as the apk root:
// e.g. /something/app/blah.apk => /something
@@ -16074,7 +16142,7 @@ Slog.e("TODD",
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
- // Set the system/privileged/oem/vendor flags as needed
+ // Set the system/privileged/oem/vendor/product flags as needed
final boolean privileged =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
@@ -16084,12 +16152,16 @@ Slog.e("TODD",
final boolean vendor =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+ final boolean product =
+ (oldPackage.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
final @ParseFlags int systemParseFlags = parseFlags;
final @ScanFlags int systemScanFlags = scanFlags
| SCAN_AS_SYSTEM
| (privileged ? SCAN_AS_PRIVILEGED : 0)
| (oem ? SCAN_AS_OEM : 0)
- | (vendor ? SCAN_AS_VENDOR : 0);
+ | (vendor ? SCAN_AS_VENDOR : 0)
+ | (product ? SCAN_AS_PRODUCT : 0);
replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
user, allUsers, installerPackageName, res, installReason);
@@ -17339,6 +17411,10 @@ Slog.e("TODD",
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ private static boolean isProductApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
private static boolean hasDomainURLs(PackageParser.Package pkg) {
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
@@ -18078,8 +18154,10 @@ Slog.e("TODD",
try {
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+ final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
return path.startsWith(privilegedAppDir.getCanonicalPath())
- || path.startsWith(privilegedVendorAppDir.getCanonicalPath());
+ || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
+ || path.startsWith(privilegedProductAppDir.getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
}
@@ -18104,6 +18182,15 @@ Slog.e("TODD",
return false;
}
+ static boolean locationIsProduct(String path) {
+ try {
+ return path.startsWith(Environment.getProductDirectory().getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to access code path " + path);
+ }
+ return false;
+ }
+
/*
* Tries to delete system package.
*/
@@ -18228,6 +18315,9 @@ Slog.e("TODD",
if (locationIsVendor(codePathString)) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if (locationIsProduct(codePathString)) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
final File codePath = new File(codePathString);
final PackageParser.Package pkg =
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 47cd81326932..686c4a5eb321 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1555,6 +1555,15 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
+ private boolean isProductApp(String pkg) {
+ try {
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+ return info != null && info.applicationInfo.isProduct();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private int runGetPrivappPermissions() {
final String pkg = getNextArg();
if (pkg == null) {
@@ -1562,9 +1571,14 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
@@ -1578,9 +1592,14 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2a2430c07980..3e2bd4a1b3ba 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -173,6 +173,10 @@ public final class PackageSetting extends PackageSettingBase {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ public boolean isProduct() {
+ return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
public boolean isForwardLocked() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 46ba0060d93e..7c92045c7c5e 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -62,6 +62,7 @@ abstract class SettingBase {
& (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_OEM
| ApplicationInfo.PRIVATE_FLAG_VENDOR
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT
| ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
| ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8ce412e5783a..5e9019dfea04 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -851,6 +851,8 @@ public final class Settings {
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
+ pkgSetting.pkgPrivateFlags |=
+ pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
pkgSetting.primaryCpuAbiString = primaryCpuAbi;
pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
if (childPkgNames != null) {
@@ -4397,6 +4399,7 @@ public final class Settings {
ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
+ ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
};
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6e07eaac9c44..e2123c25dd81 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1215,6 +1215,10 @@ public final class DefaultPermissionGrantPolicy {
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
+ dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
+ if (dir.isDirectory() && dir.canRead()) {
+ Collections.addAll(ret, dir.listFiles());
+ }
return ret.isEmpty() ? null : ret.toArray(new File[0]);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 786b998862de..cb3b1073a593 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -954,9 +954,16 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));
* <p>This handles parent/child apps.
*/
private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
- ArraySet<String> wlPermissions = pkg.isVendor() ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ ArraySet<String> wlPermissions = null;
+ if (pkg.isVendor()) {
+ wlPermissions =
+ SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ wlPermissions =
+ SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+ } else {
+ wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ }
// Let's check if this package is whitelisted...
boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);
// If it's not, we'll also tail-recurse to the parent.
@@ -979,11 +986,17 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));
// Only report violations for apps on system image
if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
// it's only a reportable violation if the permission isn't explicitly denied
- final ArraySet<String> deniedPermissions = pkg.isVendor() ?
- SystemConfig.getInstance()
- .getVendorPrivAppDenyPermissions(pkg.packageName)
- : SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.packageName);
+ ArraySet<String> deniedPermissions = null;
+ if (pkg.isVendor()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getVendorPrivAppDenyPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductPrivAppDenyPermissions(pkg.packageName);
+ } else {
+ deniedPermissions = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.packageName);
+ }
final boolean permissionViolation =
deniedPermissions == null || !deniedPermissions.contains(perm);
if (permissionViolation) {
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
new file mode 100644
index 000000000000..eb3862390338
--- /dev/null
+++ b/tests/libs-permissions/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product
+LOCAL_PRODUCT_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/libs-permissions/product/com.android.test.libs.product.xml b/tests/libs-permissions/product/com.android.test.libs.product.xml
new file mode 100644
index 000000000000..0a955e9df7fd
--- /dev/null
+++ b/tests/libs-permissions/product/com.android.test.libs.product.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<permissions>
+ <library name="com.android.test.libs.product"
+ file="/product/framework/com.android.test.libs.product.jar" />
+</permissions>
diff --git a/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
new file mode 100644
index 000000000000..f49b46e72c25
--- /dev/null
+++ b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.libs.product;
+
+/**
+ * Test class for product libs.
+ */
+public class LibsProductTest {
+
+ /**
+ * Dummpy method for testing.
+ */
+ public static void test() {
+ }
+}
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index b001c8c466a9..3c80ad8587af 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -29,3 +29,17 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions
LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product/AndroidManifest.xml
+LOCAL_PRODUCT_MODULE := true
+LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := productprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product/AndroidManifest.xml b/tests/privapp-permissions/product/AndroidManifest.xml
new file mode 100644
index 000000000000..3d9415c3df41
--- /dev/null
+++ b/tests/privapp-permissions/product/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.framework.permission.privapp.tests.product">
+
+ <!-- MANAGE_USB is signature|privileged -->
+ <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product/privapp-permissions-test.xml b/tests/privapp-permissions/product/privapp-permissions-test.xml
new file mode 100644
index 000000000000..f298f9da41b7
--- /dev/null
+++ b/tests/privapp-permissions/product/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+ <privapp-permissions package="com.android.framework.permission.privapp.tests.product">
+ <permission name="android.permission.MANAGE_USB"/>
+ </privapp-permissions>
+</permissions>