summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Freni <dariofreni@google.com>2018-06-01 14:02:08 +0100
committerDario Freni <dariofreni@google.com>2018-08-17 16:34:03 +0000
commit2bef1768a8bc63d21740fdbb2ff59c0bf15a3275 (patch)
tree6fed8f7234dfffcbc16102cccd600c5c591ef3ed
parent804574644849ef39d63d6515497469ee3b33b1d8 (diff)
Support /product-services partition
This CL is largely an adaptation of Change-Id I16175933cebd9ec665d190cc5d564b5414a91827 . I also used the same way for testing the change. This CL will support the followings. - installing a RRO package for framework from /product-services/overlay - installing apps from /product-services/app - installing priv-apps from /product-services/priv-app - installing permissions from /product-services/etc/[default-permissions|permissions|sysconfig] Bug: 80741439 Test: `mm` under frameworks/base/tests/[libs|privapp]-permissions adb sync && adb reboot adb shell cmd package list libraries => confirmed com.android.test.libs.product_services library adb shell cmd package dump \ com.android.framework.permission.privapp.tests.product_services => confirmed that the package is a priv-app And I moved vendor/overlay/framework-res__auto_generated_rro.apk into system/product-services/overlay/ on taimen, and I confirmed that the RRO was installed properly. Change-Id: I7a6a30bf8e8db9f2738594d187bb9148f138b8da (cherry picked from commit a4af41736894bd3bf5bdc2a279acbeed2a24dd3d)
-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.java13
-rw-r--r--core/java/com/android/server/SystemConfig.java42
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java149
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java30
-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.java6
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java7
-rw-r--r--tests/libs-permissions/Android.mk14
-rw-r--r--tests/libs-permissions/product_services/com.android.test.libs.product_services.xml20
-rw-r--r--tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java29
-rw-r--r--tests/privapp-permissions/Android.mk16
-rw-r--r--tests/privapp-permissions/product_services/AndroidManifest.xml23
-rw-r--r--tests/privapp-permissions/product_services/privapp-permissions-test.xml6
17 files changed, 340 insertions, 48 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 83e287aecb41..b7a53520f060 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -615,6 +615,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
/**
+ * Value for {@link #privateFlags}: whether this app is pre-installed on the
+ * google partition of the system image.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
+
+ /**
* Value for {@link #privateFlags}: whether this app is signed with the
* platform key.
* @hide
@@ -639,6 +646,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
PRIVATE_FLAG_PRIVILEGED,
PRIVATE_FLAG_PRODUCT,
+ PRIVATE_FLAG_PRODUCT_SERVICES,
PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY,
PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
@@ -1888,6 +1896,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
}
+ /** @hide */
+ public boolean isProductServices() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 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 876cf2bda6fd..83757c4b523d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6785,6 +6785,11 @@ public class PackageParser {
}
/** @hide */
+ public boolean isProductServices() {
+ return applicationInfo.isProductServices();
+ }
+
+ /** @hide */
public boolean isPrivileged() {
return applicationInfo.isPrivilegedApp();
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index e32ed9deb270..347f60f6b9be 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -45,6 +45,7 @@ public class Environment {
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";
+ private static final String ENV_PRODUCT_SERVICES_ROOT = "PRODUCT_SERVICES_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -67,6 +68,8 @@ public class Environment {
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 final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT,
+ "/product_services");
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -196,6 +199,16 @@ public class Environment {
}
/**
+ * Return root directory of the "product_services" partition holding middleware
+ * services if any. If present, the partition is mounted read-only.
+ *
+ * @hide
+ */
+ public static File getProductServicesDirectory() {
+ return DIR_PRODUCT_SERVICES_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 c5be8e4a3aba..0a787b99c0ac 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -169,6 +169,10 @@ public class SystemConfig {
final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions =
+ new ArrayMap<>();
+
final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
public static SystemConfig getInstance() {
@@ -276,6 +280,14 @@ public class SystemConfig {
return mProductPrivAppDenyPermissions.get(packageName);
}
+ public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) {
+ return mProductServicesPrivAppPermissions.get(packageName);
+ }
+
+ public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) {
+ return mProductServicesPrivAppDenyPermissions.get(packageName);
+ }
+
public Map<String, Boolean> getOemPermissions(String packageName) {
final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
if (oemPermissions != null) {
@@ -326,6 +338,17 @@ public class SystemConfig {
Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+
+ // Allow /product_services to customize system configs around libs, features, permissions
+ // and apps.
+ int productServicesPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+ ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ readPermissions(Environment.buildPath(
+ Environment.getProductServicesDirectory(), "etc", "sysconfig"),
+ productServicesPermissionFlag);
+ readPermissions(Environment.buildPath(
+ Environment.getProductServicesDirectory(), "etc", "permissions"),
+ productServicesPermissionFlag);
}
void readPermissions(File libraryDir, int permissionFlag) {
@@ -659,22 +682,27 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
- // 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.
+ // privapp permissions from system, vendor, product and product_services
+ // 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())
+ Environment.getVendorDirectory().toPath() + "/")
|| permFile.toPath().startsWith(
- Environment.getOdmDirectory().toPath());
+ Environment.getOdmDirectory().toPath() + "/");
boolean product = permFile.toPath().startsWith(
- Environment.getProductDirectory().toPath());
+ Environment.getProductDirectory().toPath() + "/");
+ boolean productServices = permFile.toPath().startsWith(
+ Environment.getProductServicesDirectory().toPath() + "/");
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
} else if (product) {
readPrivAppPermissions(parser, mProductPrivAppPermissions,
mProductPrivAppDenyPermissions);
+ } else if (productServices) {
+ readPrivAppPermissions(parser, mProductServicesPrivAppPermissions,
+ mProductServicesPrivAppDenyPermissions);
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 320affb1eee2..cf47d4e6af87 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -365,10 +365,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
continue;
}
- // 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")) {
+ // If the path is in /system, /vendor, /product or /product_services, 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")
+ || pkg.codePath.startsWith("/product_services")) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f3d333b751c0..3c62b7575ad0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -449,26 +449,27 @@ public class PackageManagerService extends IPackageManager.Stub
private static final int SHELL_UID = Process.SHELL_UID;
private static final int SE_UID = Process.SE_UID;
- static final int SCAN_NO_DEX = 1<<0;
- static final int SCAN_UPDATE_SIGNATURE = 1<<1;
- static final int SCAN_NEW_INSTALL = 1<<2;
- static final int SCAN_UPDATE_TIME = 1<<3;
- static final int SCAN_BOOTING = 1<<4;
- static final int SCAN_REQUIRE_KNOWN = 1<<7;
- static final int SCAN_MOVE = 1<<8;
- static final int SCAN_INITIAL = 1<<9;
- static final int SCAN_CHECK_ONLY = 1<<10;
- static final int SCAN_DONT_KILL_APP = 1<<11;
- static final int SCAN_IGNORE_FROZEN = 1<<12;
- static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<13;
- static final int SCAN_AS_INSTANT_APP = 1<<14;
- static final int SCAN_AS_FULL_APP = 1<<15;
- static final int SCAN_AS_VIRTUAL_PRELOAD = 1<<16;
- static final int SCAN_AS_SYSTEM = 1<<17;
- 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;
+ static final int SCAN_NO_DEX = 1 << 0;
+ static final int SCAN_UPDATE_SIGNATURE = 1 << 1;
+ static final int SCAN_NEW_INSTALL = 1 << 2;
+ static final int SCAN_UPDATE_TIME = 1 << 3;
+ static final int SCAN_BOOTING = 1 << 4;
+ static final int SCAN_REQUIRE_KNOWN = 1 << 7;
+ static final int SCAN_MOVE = 1 << 8;
+ static final int SCAN_INITIAL = 1 << 9;
+ static final int SCAN_CHECK_ONLY = 1 << 10;
+ static final int SCAN_DONT_KILL_APP = 1 << 11;
+ static final int SCAN_IGNORE_FROZEN = 1 << 12;
+ static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 13;
+ static final int SCAN_AS_INSTANT_APP = 1 << 14;
+ static final int SCAN_AS_FULL_APP = 1 << 15;
+ static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 16;
+ static final int SCAN_AS_SYSTEM = 1 << 17;
+ 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;
+ static final int SCAN_AS_PRODUCT_SERVICES = 1 << 22;
@IntDef(flag = true, prefix = { "SCAN_" }, value = {
SCAN_NO_DEX,
@@ -574,6 +575,8 @@ public class PackageManagerService extends IPackageManager.Stub
private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
+ private static final String PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
+
/** Canonical intent used to identify what counts as a "web browser" app */
private static final Intent sBrowserIntent;
static {
@@ -2589,9 +2592,10 @@ public class PackageManagerService extends IPackageManager.Stub
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
- // 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.
+ // Collect vendor/product/product_services 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),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
@@ -2606,6 +2610,13 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
+ scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT_SERVICES,
+ 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
@@ -2717,7 +2728,7 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_OEM,
0);
- // Collected privileged product packages.
+ // Collected privileged /product packages.
File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
try {
privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
@@ -2733,7 +2744,7 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_PRIVILEGED,
0);
- // Collect ordinary product packages.
+ // Collect ordinary /product packages.
File productAppDir = new File(Environment.getProductDirectory(), "app");
try {
productAppDir = productAppDir.getCanonicalFile();
@@ -2748,6 +2759,39 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_PRODUCT,
0);
+ // Collected privileged /product_services packages.
+ File privilegedProductServicesAppDir =
+ new File(Environment.getProductServicesDirectory(), "priv-app");
+ try {
+ privilegedProductServicesAppDir =
+ privilegedProductServicesAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(privilegedProductServicesAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT_SERVICES
+ | SCAN_AS_PRIVILEGED,
+ 0);
+
+ // Collect ordinary /product_services packages.
+ File productServicesAppDir = new File(Environment.getProductServicesDirectory(), "app");
+ try {
+ productServicesAppDir = productServicesAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(productServicesAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT_SERVICES,
+ 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
@@ -2952,6 +2996,23 @@ public class PackageManagerService extends IPackageManager.Stub
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT;
+ } else if (FileUtils.contains(privilegedProductServicesAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT_SERVICES
+ | SCAN_AS_PRIVILEGED;
+ } else if (FileUtils.contains(productServicesAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT_SERVICES;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
@@ -10166,6 +10227,7 @@ public class PackageManagerService extends IPackageManager.Stub
* <li>{@link #SCAN_AS_OEM}</li>
* <li>{@link #SCAN_AS_VENDOR}</li>
* <li>{@link #SCAN_AS_PRODUCT}</li>
+ * <li>{@link #SCAN_AS_PRODUCT_SERVICES}</li>
* <li>{@link #SCAN_AS_INSTANT_APP}</li>
* <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
* </ul>
@@ -10192,6 +10254,10 @@ public class PackageManagerService extends IPackageManager.Stub
& ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
scanFlags |= SCAN_AS_PRODUCT;
}
+ if ((disabledPkgSetting.pkgPrivateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) {
+ scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+ }
}
if (pkgSetting != null) {
final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -11034,6 +11100,10 @@ public class PackageManagerService extends IPackageManager.Stub
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
}
+ if ((scanFlags & SCAN_AS_PRODUCT_SERVICES) != 0) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
+ }
+
// Check if the package is signed with the same key as the platform package.
if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) ||
(platformPkg != null && compareSignatures(
@@ -12127,6 +12197,8 @@ public class PackageManagerService extends IPackageManager.Stub
codeRoot = Environment.getOdmDirectory();
} else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
codeRoot = Environment.getProductDirectory();
+ } else if (FileUtils.contains(Environment.getProductServicesDirectory(), codePath)) {
+ codeRoot = Environment.getProductServicesDirectory();
} else {
// Unrecognized code path; take its top real segment as the apk root:
// e.g. /something/app/blah.apk => /something
@@ -16667,13 +16739,16 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean oem = isOemApp(oldPackage);
final boolean vendor = isVendorApp(oldPackage);
final boolean product = isProductApp(oldPackage);
+ final boolean productServices = isProductServicesApp(oldPackage);
+
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)
- | (product ? SCAN_AS_PRODUCT : 0);
+ | (product ? SCAN_AS_PRODUCT : 0)
+ | (productServices ? SCAN_AS_PRODUCT_SERVICES : 0);
replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
user, allUsers, installerPackageName, res, installReason);
@@ -17982,6 +18057,11 @@ public class PackageManagerService extends IPackageManager.Stub
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
}
+ private static boolean isProductServicesApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+ }
+
private static boolean hasDomainURLs(PackageParser.Package pkg) {
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
@@ -18721,10 +18801,13 @@ public class PackageManagerService extends IPackageManager.Stub
final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
+ final File privilegedProductServicesAppDir =
+ new File(Environment.getProductServicesDirectory(), "priv-app");
return path.startsWith(privilegedAppDir.getCanonicalPath())
|| path.startsWith(privilegedVendorAppDir.getCanonicalPath())
|| path.startsWith(privilegedOdmAppDir.getCanonicalPath())
- || path.startsWith(privilegedProductAppDir.getCanonicalPath());
+ || path.startsWith(privilegedProductAppDir.getCanonicalPath())
+ || path.startsWith(privilegedProductServicesAppDir.getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
}
@@ -18759,6 +18842,15 @@ public class PackageManagerService extends IPackageManager.Stub
return false;
}
+ static boolean locationIsProductServices(String path) {
+ try {
+ return path.startsWith(Environment.getProductServicesDirectory().getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to access code path " + path);
+ }
+ return false;
+ }
+
/*
* Tries to delete system package.
*/
@@ -18886,6 +18978,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (locationIsProduct(codePathString)) {
scanFlags |= SCAN_AS_PRODUCT;
}
+ if (locationIsProductServices(codePathString)) {
+ scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+ }
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 3834a88d1c0c..f2c0395f9f0e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -25,7 +25,6 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO
import android.accounts.IAccountManager;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -67,7 +66,6 @@ import android.os.IBinder;
import android.os.IUserManager;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
-import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -84,11 +82,17 @@ import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.PrintWriterPrinter;
+
import com.android.internal.content.PackageHelper;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
+
import dalvik.system.DexFile;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -96,10 +100,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.FileAttribute;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -110,10 +110,7 @@ import java.util.Objects;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
class PackageManagerShellCommand extends ShellCommand {
/** Path for streaming APK content */
@@ -1777,6 +1774,15 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
+ private boolean isProductServicesApp(String pkg) {
+ try {
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+ return info != null && info.applicationInfo.isProductServices();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private int runGetPrivappPermissions() {
final String pkg = getNextArg();
if (pkg == null) {
@@ -1789,6 +1795,9 @@ class PackageManagerShellCommand extends ShellCommand {
privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
} else if (isProductApp(pkg)) {
privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+ } else if (isProductServicesApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance()
+ .getProductServicesPrivAppPermissions(pkg);
} else {
privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
}
@@ -1810,6 +1819,9 @@ class PackageManagerShellCommand extends ShellCommand {
privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
} else if (isProductApp(pkg)) {
privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+ } else if (isProductServicesApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance()
+ .getProductServicesPrivAppDenyPermissions(pkg);
} else {
privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index ea05b74d7443..727fb15e616a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -148,6 +148,10 @@ public final class PackageSetting extends PackageSettingBase {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
}
+ public boolean isProductServices() {
+ return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 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 7c92045c7c5e..239dc995532a 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -63,6 +63,7 @@ abstract class SettingBase {
| ApplicationInfo.PRIVATE_FLAG_OEM
| ApplicationInfo.PRIVATE_FLAG_VENDOR
| ApplicationInfo.PRIVATE_FLAG_PRODUCT
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES
| 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 e9cd7075d8e0..ed56a32eb570 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -850,7 +850,8 @@ public final class Settings {
pkgSetting.pkgPrivateFlags &= ~(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_OEM
| ApplicationInfo.PRIVATE_FLAG_VENDOR
- | ApplicationInfo.PRIVATE_FLAG_PRODUCT);
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES);
pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -860,6 +861,8 @@ public final class Settings {
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+ pkgSetting.pkgPrivateFlags |=
+ pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
pkgSetting.primaryCpuAbiString = primaryCpuAbi;
pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
if (childPkgNames != null) {
@@ -4445,6 +4448,7 @@ public final class Settings {
ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
+ ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES, "PRODUCT_SERVICES",
ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
};
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 9dc0b296f97e..c4f90a125c71 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1097,6 +1097,10 @@ public class PermissionManagerService {
} else if (pkg.isProduct()) {
wlPermissions =
SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+ } else if (pkg.isProductServices()) {
+ wlPermissions =
+ SystemConfig.getInstance().getProductServicesPrivAppPermissions(
+ pkg.packageName);
} else {
wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
}
@@ -1129,6 +1133,9 @@ public class PermissionManagerService {
} else if (pkg.isProduct()) {
deniedPermissions = SystemConfig.getInstance()
.getProductPrivAppDenyPermissions(pkg.packageName);
+ } else if (pkg.isProductServices()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductServicesPrivAppDenyPermissions(pkg.packageName);
} else {
deniedPermissions = SystemConfig.getInstance()
.getPrivAppDenyPermissions(pkg.packageName);
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
index eb3862390338..f4250c8b4e97 100644
--- a/tests/libs-permissions/Android.mk
+++ b/tests/libs-permissions/Android.mk
@@ -13,3 +13,17 @@ 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)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product_services/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product_services.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/com.android.test.libs.product_services.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml b/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml
new file mode 100644
index 000000000000..082a9be80779
--- /dev/null
+++ b/tests/libs-permissions/product_services/com.android.test.libs.product_services.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_services"
+ file="/product_services/framework/com.android.test.libs.product_services.jar" />
+</permissions>
diff --git a/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java
new file mode 100644
index 000000000000..dcbdae809889
--- /dev/null
+++ b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.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_services;
+
+/**
+ * Test class for product_services libs.
+ */
+public class LibsProductServicesTest {
+
+ /**
+ * Dummy method for testing.
+ */
+ public static void test() {
+ }
+}
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index 9795188559c4..1149b8a8fe40 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -46,3 +46,19 @@ LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductServicesPrivAppPermissionTest
+LOCAL_SDK_VERSION := current
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product_services/AndroidManifest.xml
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_REQUIRED_MODULES := product_servicesprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := product_servicesprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product_services/AndroidManifest.xml b/tests/privapp-permissions/product_services/AndroidManifest.xml
new file mode 100644
index 000000000000..511ddee729ca
--- /dev/null
+++ b/tests/privapp-permissions/product_services/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_services">
+
+ <!-- MANAGE_USB is signature|privileged -->
+ <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product_services/privapp-permissions-test.xml b/tests/privapp-permissions/product_services/privapp-permissions-test.xml
new file mode 100644
index 000000000000..43baebbb0aad
--- /dev/null
+++ b/tests/privapp-permissions/product_services/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_services">
+ <permission name="android.permission.MANAGE_USB"/>
+ </privapp-permissions>
+</permissions>