diff options
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> |