summaryrefslogtreecommitdiff
path: root/com/android/server/pm
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2017-10-30 17:25:37 -0400
committerJustin Klaassen <justinklaassen@google.com>2017-10-30 17:25:37 -0400
commit46c77c203439b3b37c99d09e326df4b1fe08c10b (patch)
tree70d29abbfbb1106cd0830b33bc7e69e6fb151b1e /com/android/server/pm
parent47ed54e5d312f899507d28d6e95ccc18a0de19fe (diff)
downloadandroid-28-46c77c203439b3b37c99d09e326df4b1fe08c10b.tar.gz
Import Android SDK Platform P [4423826]
/google/data/ro/projects/android/fetch_artifact \ --bid 4423826 \ --target sdk_phone_armv7-win_sdk \ sdk-repo-linux-sources-4423826.zip AndroidVersion.ApiLevel has been modified to appear as 28 Change-Id: I45f7bdc9b9c1cdcba75386623ae5f3ead6db4da8
Diffstat (limited to 'com/android/server/pm')
-rw-r--r--com/android/server/pm/BackgroundDexOptService.java3
-rw-r--r--com/android/server/pm/Installer.java2
-rw-r--r--com/android/server/pm/OtaDexoptService.java2
-rw-r--r--com/android/server/pm/PackageDexOptimizer.java6
-rw-r--r--com/android/server/pm/PackageManagerService.java970
-rw-r--r--com/android/server/pm/PackageManagerShellCommand.java1920
-rw-r--r--com/android/server/pm/PackageSetting.java16
-rw-r--r--com/android/server/pm/PackageSettingBase.java8
-rw-r--r--com/android/server/pm/Settings.java2
-rw-r--r--com/android/server/pm/UserDataPreparer.java2
-rw-r--r--com/android/server/pm/UserRestrictionsUtils.java2
-rw-r--r--com/android/server/pm/dex/DexoptOptions.java10
-rw-r--r--com/android/server/pm/permission/BasePermission.java8
-rw-r--r--com/android/server/pm/permission/DefaultPermissionGrantPolicy.java4
-rw-r--r--com/android/server/pm/permission/PermissionManagerInternal.java34
-rw-r--r--com/android/server/pm/permission/PermissionManagerService.java999
-rw-r--r--com/android/server/pm/permission/PermissionSettings.java12
17 files changed, 2497 insertions, 1503 deletions
diff --git a/com/android/server/pm/BackgroundDexOptService.java b/com/android/server/pm/BackgroundDexOptService.java
index 6d8cac0c..679250cb 100644
--- a/com/android/server/pm/BackgroundDexOptService.java
+++ b/com/android/server/pm/BackgroundDexOptService.java
@@ -340,7 +340,8 @@ public class BackgroundDexOptService extends JobService {
int dexoptFlags =
DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES |
DexoptOptions.DEXOPT_BOOT_COMPLETE |
- (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0);
+ (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0) |
+ DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB;
if (is_for_primary_dex) {
int result = pm.performDexOptWithStatus(new DexoptOptions(pkg, reason,
dexoptFlags));
diff --git a/com/android/server/pm/Installer.java b/com/android/server/pm/Installer.java
index 371b3ef5..210eb138 100644
--- a/com/android/server/pm/Installer.java
+++ b/com/android/server/pm/Installer.java
@@ -56,6 +56,8 @@ public class Installer extends SystemService {
public static final int DEXOPT_STORAGE_CE = 1 << 7;
/** Indicates that the dex file passed to dexopt in on DE storage. */
public static final int DEXOPT_STORAGE_DE = 1 << 8;
+ /** Indicates that dexopt is invoked from the background service. */
+ public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/com/android/server/pm/OtaDexoptService.java b/com/android/server/pm/OtaDexoptService.java
index 6253857d..03f662a4 100644
--- a/com/android/server/pm/OtaDexoptService.java
+++ b/com/android/server/pm/OtaDexoptService.java
@@ -310,7 +310,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
collectingInstaller, mPackageManagerService.mInstallLock, mContext);
String[] libraryDependencies = pkg.usesLibraryFiles;
- if (pkg.isSystemApp()) {
+ if (pkg.isSystem()) {
// For system apps, we want to avoid classpaths checks.
libraryDependencies = NO_LIBRARIES;
}
diff --git a/com/android/server/pm/PackageDexOptimizer.java b/com/android/server/pm/PackageDexOptimizer.java
index cf0ffbb1..86a1c03d 100644
--- a/com/android/server/pm/PackageDexOptimizer.java
+++ b/com/android/server/pm/PackageDexOptimizer.java
@@ -54,6 +54,7 @@ import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_FORCE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
+import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -110,7 +111,7 @@ public class PackageDexOptimizer {
}
// We do not dexopt a priv-app package when pm.dexopt.priv-apps is false.
- if (pkg.isPrivilegedApp()) {
+ if (pkg.isPrivileged()) {
return SystemProperties.getBoolean("pm.dexopt.priv-apps", true);
}
@@ -612,6 +613,9 @@ public class PackageDexOptimizer {
if ((flags & DEXOPT_STORAGE_DE) == DEXOPT_STORAGE_DE) {
flagsList.add("storage_de");
}
+ if ((flags & DEXOPT_IDLE_BACKGROUND_JOB) == DEXOPT_IDLE_BACKGROUND_JOB) {
+ flagsList.add("idle_background_job");
+ }
return String.join(",", flagsList);
}
diff --git a/com/android/server/pm/PackageManagerService.java b/com/android/server/pm/PackageManagerService.java
index 391deb74..7be0cde4 100644
--- a/com/android/server/pm/PackageManagerService.java
+++ b/com/android/server/pm/PackageManagerService.java
@@ -397,7 +397,7 @@ public class PackageManagerService extends IPackageManager.Stub
static final boolean DEBUG_UPGRADE = false;
static final boolean DEBUG_DOMAIN_VERIFICATION = false;
private static final boolean DEBUG_BACKUP = false;
- private static final boolean DEBUG_INSTALL = false;
+ public static final boolean DEBUG_INSTALL = false;
public static final boolean DEBUG_REMOVE = false;
private static final boolean DEBUG_BROADCASTS = false;
private static final boolean DEBUG_SHOW_INFO = false;
@@ -522,7 +522,7 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
- static final String PLATFORM_PACKAGE_NAME = "android";
+ public static final String PLATFORM_PACKAGE_NAME = "android";
static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
@@ -542,18 +542,6 @@ public class PackageManagerService extends IPackageManager.Stub
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
- /** Permission grant: not grant the permission. */
- private static final int GRANT_DENIED = 1;
-
- /** Permission grant: grant the permission as an install permission. */
- private static final int GRANT_INSTALL = 2;
-
- /** Permission grant: grant the permission as a runtime one. */
- private static final int GRANT_RUNTIME = 3;
-
- /** Permission grant: grant as runtime a permission that was granted as an install time one. */
- private static final int GRANT_UPGRADE = 4;
-
/** Canonical intent used to identify what counts as a "web browser" app */
private static final Intent sBrowserIntent;
static {
@@ -753,9 +741,6 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
- // System configuration read by SystemConfig.
- final int[] mGlobalGids;
- final SparseArray<ArraySet<String>> mSystemPermissions;
@GuardedBy("mAvailableFeatures")
final ArrayMap<String, FeatureInfo> mAvailableFeatures;
@@ -938,10 +923,6 @@ public class PackageManagerService extends IPackageManager.Stub
final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
new ArrayMap<ComponentName, PackageParser.Instrumentation>();
- // Mapping from permission names to info about them.
- final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups =
- new ArrayMap<String, PackageParser.PermissionGroup>();
-
// Packages whose data we have transfered into another package, thus
// should no longer exist.
final ArraySet<String> mTransferedPackages = new ArraySet<String>();
@@ -1016,8 +997,6 @@ public class PackageManagerService extends IPackageManager.Stub
private File mCacheDir;
- private ArraySet<String> mPrivappPermissionsViolations;
-
private Future<?> mPrepareAppDataFuture;
private static class IFVerificationParams {
@@ -1405,8 +1384,6 @@ public class PackageManagerService extends IPackageManager.Stub
final @NonNull String mServicesSystemSharedLibraryPackageName;
final @NonNull String mSharedSystemSharedLibraryPackageName;
- final boolean mPermissionReviewRequired;
-
private final PackageUsage mPackageUsage = new PackageUsage();
private final CompilerStats mCompilerStats = new CompilerStats();
@@ -1928,9 +1905,11 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
@Override
- public void onPermissionUpdated(int userId) {
+ public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
synchronized (mPackages) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+ for (int userId : updatedUserIds) {
+ mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
+ }
}
}
@Override
@@ -2363,9 +2342,6 @@ public class PackageManagerService extends IPackageManager.Stub
mContext = context;
- mPermissionReviewRequired = context.getResources().getBoolean(
- R.bool.config_permissionReviewRequired);
-
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mMetrics = new DisplayMetrics();
@@ -2434,8 +2410,6 @@ public class PackageManagerService extends IPackageManager.Stub
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
SystemConfig systemConfig = SystemConfig.getInstance();
- mGlobalGids = systemConfig.getGlobalGids();
- mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -2872,13 +2846,14 @@ public class PackageManagerService extends IPackageManager.Stub
// cases get permissions that the user didn't initially explicitly
// allow... it would be nice to have some better way to handle
// this situation.
- int updateFlags = UPDATE_PERMISSIONS_ALL;
- if (ver.sdkVersion != mSdkVersion) {
+ final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
+ if (sdkUpdated) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
- updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
+ mPermissionManager.updateAllPermissions(
+ StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
+ mPermissionCallback);
ver.sdkVersion = mSdkVersion;
// If this is the first boot or an update from pre-M, and it is a normal
@@ -3597,7 +3572,7 @@ public class PackageManagerService extends IPackageManager.Stub
for (String packageName : packages) {
PackageParser.Package pkg = mPackages.get(packageName);
if (pkg != null) {
- if (!pkg.isSystemApp()) {
+ if (!pkg.isSystem()) {
Slog.w(TAG, "Non-system app '" + packageName + "' in sysconfig <app-link>");
continue;
}
@@ -3744,19 +3719,16 @@ public class PackageManagerService extends IPackageManager.Stub
* <p>
* Currently, there are three cases in which this can occur:
* <ol>
- * <li>The calling application is a "special" process. The special
- * processes are {@link Process#SYSTEM_UID}, {@link Process#SHELL_UID}
- * and {@code 0}</li>
+ * <li>The calling application is a "special" process. Special processes
+ * are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li>
* <li>The calling application has the permission
- * {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
+ * {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li>
* <li>The calling application is the default launcher on the
* system partition.</li>
* </ol>
*/
private boolean canViewInstantApps(int callingUid, int userId) {
- if (callingUid == Process.SYSTEM_UID
- || callingUid == Process.SHELL_UID
- || callingUid == Process.ROOT_UID) {
+ if (callingUid < Process.FIRST_APPLICATION_UID) {
return true;
}
if (mContext.checkCallingOrSelfPermission(
@@ -4228,44 +4200,22 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName,
int flags) {
- // TODO Move this to PermissionManager when mPermissionGroups is moved there
- synchronized (mPackages) {
- if (groupName != null && !mPermissionGroups.containsKey(groupName)) {
- // This is thrown as NameNotFoundException
- return null;
- }
- }
- return new ParceledListSlice<>(
- mPermissionManager.getPermissionInfoByGroup(groupName, flags, getCallingUid()));
+ final List<PermissionInfo> permissionList =
+ mPermissionManager.getPermissionInfoByGroup(groupName, flags, getCallingUid());
+ return (permissionList == null) ? null : new ParceledListSlice<>(permissionList);
}
@Override
- public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return null;
- }
- // reader
- synchronized (mPackages) {
- return PackageParser.generatePermissionGroupInfo(
- mPermissionGroups.get(name), flags);
- }
+ public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) {
+ return mPermissionManager.getPermissionGroupInfo(groupName, flags, getCallingUid());
}
@Override
public @NonNull ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return ParceledListSlice.emptyList();
- }
- // reader
- synchronized (mPackages) {
- final int N = mPermissionGroups.size();
- ArrayList<PermissionGroupInfo> out
- = new ArrayList<PermissionGroupInfo>(N);
- for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
- out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
- }
- return new ParceledListSlice<>(out);
- }
+ final List<PermissionGroupInfo> permissionList =
+ mPermissionManager.getAllPermissionGroups(flags, getCallingUid());
+ return (permissionList == null)
+ ? ParceledListSlice.emptyList() : new ParceledListSlice<>(permissionList);
}
private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
@@ -5138,59 +5088,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public int checkUidPermission(String permName, int uid) {
- final int callingUid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getUserId(callingUid);
- final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
- final boolean isUidInstantApp = getInstantAppPackageName(uid) != null;
- final int userId = UserHandle.getUserId(uid);
- if (!sUserManager.exists(userId)) {
- return PackageManager.PERMISSION_DENIED;
- }
-
- synchronized (mPackages) {
- Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
- if (obj != null) {
- if (obj instanceof SharedUserSetting) {
- if (isCallerInstantApp) {
- return PackageManager.PERMISSION_DENIED;
- }
- } else if (obj instanceof PackageSetting) {
- final PackageSetting ps = (PackageSetting) obj;
- if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
- return PackageManager.PERMISSION_DENIED;
- }
- }
- final SettingBase settingBase = (SettingBase) obj;
- final PermissionsState permissionsState = settingBase.getPermissionsState();
- if (permissionsState.hasPermission(permName, userId)) {
- if (isUidInstantApp) {
- if (mSettings.mPermissions.isPermissionInstant(permName)) {
- return PackageManager.PERMISSION_GRANTED;
- }
- } else {
- return PackageManager.PERMISSION_GRANTED;
- }
- }
- // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
- if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
- .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
- return PackageManager.PERMISSION_GRANTED;
- }
- } else {
- ArraySet<String> perms = mSystemPermissions.get(uid);
- if (perms != null) {
- if (perms.contains(permName)) {
- return PackageManager.PERMISSION_GRANTED;
- }
- if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && perms
- .contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
- return PackageManager.PERMISSION_GRANTED;
- }
- }
- }
- }
-
- return PackageManager.PERMISSION_DENIED;
+ return mPermissionManager.checkUidPermission(permName, uid, getCallingUid());
}
@Override
@@ -5352,7 +5250,9 @@ public class PackageManagerService extends IPackageManager.Stub
}
synchronized (mPackages) {
- updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+ mPermissionManager.updateAllPermissions(
+ StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
+ mPermissionCallback);
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int packageCount = mPackages.size();
for (int i = 0; i < packageCount; i++) {
@@ -5369,7 +5269,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public int getPermissionFlags(String permName, String packageName, int userId) {
- return mPermissionManager.getPermissionFlags(permName, packageName, getCallingUid(), userId);
+ return mPermissionManager.getPermissionFlags(
+ permName, packageName, getCallingUid(), userId);
}
@Override
@@ -9914,7 +9815,7 @@ public class PackageManagerService extends IPackageManager.Stub
// it is better for the user to reinstall than to be in an limbo
// state. Also libs disappearing under an app should never happen
// - just in case.
- if (!pkg.isSystemApp() || pkg.isUpdatedSystemApp()) {
+ if (!pkg.isSystem() || pkg.isUpdatedSystemApp()) {
final int flags = pkg.isUpdatedSystemApp()
? PackageManager.DELETE_KEEP_DATA : 0;
deletePackageLIF(pkg.packageName, null, true, sUserManager.getUserIds(),
@@ -10063,7 +9964,7 @@ public class PackageManagerService extends IPackageManager.Stub
assertPackageIsValid(pkg, policyFlags, scanFlags);
if (Build.IS_DEBUGGABLE &&
- pkg.isPrivilegedApp() &&
+ pkg.isPrivileged() &&
!SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) {
PackageManagerServiceUtils.logPackageHasUncompressedCode(pkg);
}
@@ -11156,54 +11057,15 @@ public class PackageManagerService extends IPackageManager.Stub
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
}
- N = pkg.permissionGroups.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
- PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
- final String curPackageName = cur == null ? null : cur.info.packageName;
- // Dont allow ephemeral apps to define new permission groups.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- Slog.w(TAG, "Permission group " + pg.info.name + " from package "
- + pg.info.packageName
- + " ignored: instant apps cannot define new permission groups.");
- continue;
- }
- final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
- if (cur == null || isPackageUpdate) {
- mPermissionGroups.put(pg.info.name, pg);
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- if (isPackageUpdate) {
- r.append("UPD:");
- }
- r.append(pg.info.name);
- }
- } else {
- Slog.w(TAG, "Permission group " + pg.info.name + " from package "
- + pg.info.packageName + " ignored: original from "
- + cur.info.packageName);
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append("DUP:");
- r.append(pg.info.name);
- }
- }
- }
- if (r != null) {
- if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
+ // Don't allow ephemeral applications to define new permissions groups.
+ if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
+ Slog.w(TAG, "Permission groups from package " + pkg.packageName
+ + " ignored: instant apps cannot define new permission groups.");
+ } else {
+ mPermissionManager.addAllPermissionGroups(pkg, chatty);
}
-
- // Dont allow ephemeral apps to define new permissions.
+ // Don't allow ephemeral applications to define new permissions.
if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
Slog.w(TAG, "Permissions from package " + pkg.packageName
+ " ignored: instant apps cannot define new permissions.");
@@ -11995,611 +11857,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- public static final int UPDATE_PERMISSIONS_ALL = 1<<0;
- public static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
- public static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
-
- private void updatePermissionsLPw(PackageParser.Package pkg, int flags) {
- // Update the parent permissions
- updatePermissionsLPw(pkg.packageName, pkg, flags);
- // Update the child permissions
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- PackageParser.Package childPkg = pkg.childPackages.get(i);
- updatePermissionsLPw(childPkg.packageName, childPkg, flags);
- }
- }
-
- private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,
- int flags) {
- final String volumeUuid = (pkgInfo != null) ? getVolumeUuidForPackage(pkgInfo) : null;
- updatePermissionsLocked(changingPkg, pkgInfo, volumeUuid, flags);
- }
-
- private void updatePermissionsLocked(String changingPkg,
- PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) {
- // TODO: Most of the methods exposing BasePermission internals [source package name,
- // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
- // have package settings, we should make note of it elsewhere [map between
- // source package name and BasePermission] and cycle through that here. Then we
- // define a single method on BasePermission that takes a PackageSetting, changing
- // package name and a package.
- // NOTE: With this approach, we also don't need to tree trees differently than
- // normal permissions. Today, we need two separate loops because these BasePermission
- // objects are stored separately.
- // Make sure there are no dangling permission trees.
- flags = mPermissionManager.updatePermissionTrees(changingPkg, pkgInfo, flags);
-
- // Make sure all dynamic permissions have been assigned to a package,
- // and make sure there are no dangling permissions.
- flags = mPermissionManager.updatePermissions(changingPkg, pkgInfo, flags);
-
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
- // Now update the permissions for all packages, in particular
- // replace the granted permissions of the system packages.
- if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
- for (PackageParser.Package pkg : mPackages.values()) {
- if (pkg != pkgInfo) {
- // Only replace for packages on requested volume
- final String volumeUuid = getVolumeUuidForPackage(pkg);
- final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
- && Objects.equals(replaceVolumeUuid, volumeUuid);
- grantPermissionsLPw(pkg, replace, changingPkg);
- }
- }
- }
-
- if (pkgInfo != null) {
- // Only replace for packages on requested volume
- final String volumeUuid = getVolumeUuidForPackage(pkgInfo);
- final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
- && Objects.equals(replaceVolumeUuid, volumeUuid);
- grantPermissionsLPw(pkgInfo, replace, changingPkg);
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
-
- private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
- String packageOfInterest) {
- // IMPORTANT: There are two types of permissions: install and runtime.
- // Install time permissions are granted when the app is installed to
- // all device users and users added in the future. Runtime permissions
- // are granted at runtime explicitly to specific users. Normal and signature
- // protected permissions are install time permissions. Dangerous permissions
- // are install permissions if the app's target SDK is Lollipop MR1 or older,
- // otherwise they are runtime permissions. This function does not manage
- // runtime permissions except for the case an app targeting Lollipop MR1
- // being upgraded to target a newer SDK, in which case dangerous permissions
- // are transformed from install time to runtime ones.
-
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
- if (ps == null) {
- return;
- }
-
- PermissionsState permissionsState = ps.getPermissionsState();
- PermissionsState origPermissions = permissionsState;
-
- final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
-
- boolean runtimePermissionsRevoked = false;
- int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
-
- boolean changedInstallPermission = false;
-
- if (replace) {
- ps.installPermissionsFixed = false;
- if (!ps.isSharedUser()) {
- origPermissions = new PermissionsState(permissionsState);
- permissionsState.reset();
- } else {
- // We need to know only about runtime permission changes since the
- // calling code always writes the install permissions state but
- // the runtime ones are written only if changed. The only cases of
- // changed runtime permissions here are promotion of an install to
- // runtime and revocation of a runtime from a shared user.
- changedRuntimePermissionUserIds =
- mPermissionManager.revokeUnusedSharedUserPermissions(
- ps.sharedUser, UserManagerService.getInstance().getUserIds());
- if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) {
- runtimePermissionsRevoked = true;
- }
- }
- }
-
- permissionsState.setGlobalGids(mGlobalGids);
-
- final int N = pkg.requestedPermissions.size();
- for (int i=0; i<N; i++) {
- final String name = pkg.requestedPermissions.get(i);
- final BasePermission bp = (BasePermission) mPermissionManager.getPermissionTEMP(name);
- final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
- >= Build.VERSION_CODES.M;
-
- if (DEBUG_INSTALL) {
- Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
- }
-
- if (bp == null || bp.getSourcePackageSetting() == null) {
- if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Unknown permission " + name
- + " in package " + pkg.packageName);
- }
- }
- continue;
- }
-
-
- // Limit ephemeral apps to ephemeral allowed permissions.
- if (pkg.applicationInfo.isInstantApp() && !bp.isInstant()) {
- if (DEBUG_PERMISSIONS) {
- Log.i(TAG, "Denying non-ephemeral permission " + bp.getName() + " for package "
- + pkg.packageName);
- }
- continue;
- }
-
- if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
- if (DEBUG_PERMISSIONS) {
- Log.i(TAG, "Denying runtime-only permission " + bp.getName() + " for package "
- + pkg.packageName);
- }
- continue;
- }
-
- final String perm = bp.getName();
- boolean allowedSig = false;
- int grant = GRANT_DENIED;
-
- // Keep track of app op permissions.
- if (bp.isAppOp()) {
- mSettings.addAppOpPackage(perm, pkg.packageName);
- }
-
- if (bp.isNormal()) {
- // For all apps normal permissions are install time ones.
- grant = GRANT_INSTALL;
- } else if (bp.isRuntime()) {
- // If a permission review is required for legacy apps we represent
- // their permissions as always granted runtime ones since we need
- // to keep the review required permission flag per user while an
- // install permission's state is shared across all users.
- if (!appSupportsRuntimePermissions && !mPermissionReviewRequired) {
- // For legacy apps dangerous permissions are install time ones.
- grant = GRANT_INSTALL;
- } else if (origPermissions.hasInstallPermission(bp.getName())) {
- // For legacy apps that became modern, install becomes runtime.
- grant = GRANT_UPGRADE;
- } else if (mPromoteSystemApps
- && isSystemApp(ps)
- && mExistingSystemPackages.contains(ps.name)) {
- // For legacy system apps, install becomes runtime.
- // We cannot check hasInstallPermission() for system apps since those
- // permissions were granted implicitly and not persisted pre-M.
- grant = GRANT_UPGRADE;
- } else {
- // For modern apps keep runtime permissions unchanged.
- grant = GRANT_RUNTIME;
- }
- } else if (bp.isSignature()) {
- // For all apps signature permissions are install time ones.
- allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
- if (allowedSig) {
- grant = GRANT_INSTALL;
- }
- }
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Granting permission " + perm + " to package " + pkg.packageName);
- }
-
- if (grant != GRANT_DENIED) {
- if (!isSystemApp(ps) && ps.installPermissionsFixed) {
- // If this is an existing, non-system package, then
- // we can't add any new permissions to it.
- if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
- // Except... if this is a permission that was added
- // to the platform (note: need to only do this when
- // updating the platform).
- if (!isNewPlatformPermissionForPackage(perm, pkg)) {
- grant = GRANT_DENIED;
- }
- }
- }
-
- switch (grant) {
- case GRANT_INSTALL: {
- // Revoke this as runtime permission to handle the case of
- // a runtime permission being downgraded to an install one.
- // Also in permission review mode we keep dangerous permissions
- // for legacy apps
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- if (origPermissions.getRuntimePermissionState(
- perm, userId) != null) {
- // Revoke the runtime permission and clear the flags.
- origPermissions.revokeRuntimePermission(bp, userId);
- origPermissions.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
- // If we revoked a permission permission, we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- }
- // Grant an install permission.
- if (permissionsState.grantInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- changedInstallPermission = true;
- }
- } break;
-
- case GRANT_RUNTIME: {
- // Grant previously granted runtime permissions.
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- PermissionState permissionState = origPermissions
- .getRuntimePermissionState(perm, userId);
- int flags = permissionState != null
- ? permissionState.getFlags() : 0;
- if (origPermissions.hasRuntimePermission(perm, userId)) {
- // Don't propagate the permission in a permission review mode if
- // the former was revoked, i.e. marked to not propagate on upgrade.
- // Note that in a permission review mode install permissions are
- // represented as constantly granted runtime ones since we need to
- // keep a per user state associated with the permission. Also the
- // revoke on upgrade flag is no longer applicable and is reset.
- final boolean revokeOnUpgrade = (flags & PackageManager
- .FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0;
- if (revokeOnUpgrade) {
- flags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
- // Since we changed the flags, we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- if (!mPermissionReviewRequired || !revokeOnUpgrade) {
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // If we cannot put the permission as it was,
- // we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- }
-
- // If the app supports runtime permissions no need for a review.
- if (mPermissionReviewRequired
- && appSupportsRuntimePermissions
- && (flags & PackageManager
- .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- // Since we changed the flags, we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- } else if (mPermissionReviewRequired
- && !appSupportsRuntimePermissions) {
- // For legacy apps that need a permission review, every new
- // runtime permission is granted but it is pending a review.
- // We also need to review only platform defined runtime
- // permissions as these are the only ones the platform knows
- // how to disable the API to simulate revocation as legacy
- // apps don't expect to run with revoked permissions.
- if (PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName())) {
- if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
- flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
- // We changed the flags, hence have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- }
- if (permissionsState.grantRuntimePermission(bp, userId)
- != PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // We changed the permission, hence have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- }
- // Propagate the permission flags.
- permissionsState.updatePermissionFlags(bp, userId, flags, flags);
- }
- } break;
-
- case GRANT_UPGRADE: {
- // Grant runtime permissions for a previously held install permission.
- PermissionState permissionState = origPermissions
- .getInstallPermissionState(perm);
- final int flags = permissionState != null ? permissionState.getFlags() : 0;
-
- if (origPermissions.revokeInstallPermission(bp)
- != PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // We will be transferring the permission flags, so clear them.
- origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
- changedInstallPermission = true;
- }
-
- // If the permission is not to be promoted to runtime we ignore it and
- // also its other flags as they are not applicable to install permissions.
- if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
- for (int userId : currentUserIds) {
- if (permissionsState.grantRuntimePermission(bp, userId) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // Transfer the permission flags.
- permissionsState.updatePermissionFlags(bp, userId,
- flags, flags);
- // If we granted the permission, we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
- }
- }
- }
- } break;
-
- default: {
- if (packageOfInterest == null
- || packageOfInterest.equals(pkg.packageName)) {
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Not granting permission " + perm
- + " to package " + pkg.packageName
- + " because it was previously installed without");
- }
- }
- } break;
- }
- } else {
- if (permissionsState.revokeInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // Also drop the permission flags.
- permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
- changedInstallPermission = true;
- Slog.i(TAG, "Un-granting permission " + perm
- + " from package " + pkg.packageName
- + " (protectionLevel=" + bp.getProtectionLevel()
- + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
- + ")");
- } else if (bp.isAppOp()) {
- // Don't print warning for app op permissions, since it is fine for them
- // not to be granted, there is a UI for the user to decide.
- if (DEBUG_PERMISSIONS
- && (packageOfInterest == null
- || packageOfInterest.equals(pkg.packageName))) {
- Slog.i(TAG, "Not granting permission " + perm
- + " to package " + pkg.packageName
- + " (protectionLevel=" + bp.getProtectionLevel()
- + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
- + ")");
- }
- }
- }
- }
-
- if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&
- !isSystemApp(ps) || isUpdatedSystemApp(ps)){
- // This is the first that we have heard about this package, so the
- // permissions we have now selected are fixed until explicitly
- // changed.
- ps.installPermissionsFixed = true;
- }
-
- // Persist the runtime permissions state for users with changes. If permissions
- // were revoked because no app in the shared user declares them we have to
- // write synchronously to avoid losing runtime permissions state.
- for (int userId : changedRuntimePermissionUserIds) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);
- }
- }
-
- private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
- boolean allowed = false;
- final int NP = PackageParser.NEW_PERMISSIONS.length;
- for (int ip=0; ip<NP; ip++) {
- final PackageParser.NewPermissionInfo npi
- = PackageParser.NEW_PERMISSIONS[ip];
- if (npi.name.equals(perm)
- && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
- allowed = true;
- Log.i(TAG, "Auto-granting " + perm + " to old pkg "
- + pkg.packageName);
- break;
- }
- }
- return allowed;
- }
-
- /**
- * Determines whether a package is whitelisted for a particular privapp permission.
- *
- * <p>Does NOT check whether the package is a privapp, just whether it's whitelisted.
- *
- * <p>This handles parent/child apps.
- */
- private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
- ArraySet<String> 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.
- return whitelisted ||
- pkg.parentPackage != null && hasPrivappWhitelistEntry(perm, pkg.parentPackage);
- }
-
- private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
- BasePermission bp, PermissionsState origPermissions) {
- boolean oemPermission = bp.isOEM();
- boolean privilegedPermission = bp.isPrivileged();
- boolean privappPermissionsDisable =
- RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
- boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
- boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.packageName);
- if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivilegedApp()
- && !platformPackage && platformPermission) {
- if (!hasPrivappWhitelistEntry(perm, pkg)) {
- Slog.w(TAG, "Privileged permission " + perm + " for package "
- + pkg.packageName + " - not in privapp-permissions whitelist");
- // 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 = SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.packageName);
- final boolean permissionViolation =
- deniedPermissions == null || !deniedPermissions.contains(perm);
- if (permissionViolation
- && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
- if (mPrivappPermissionsViolations == null) {
- mPrivappPermissionsViolations = new ArraySet<>();
- }
- mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm);
- } else {
- return false;
- }
- }
- if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
- return false;
- }
- }
- }
- boolean allowed = (compareSignatures(
- bp.getSourcePackageSetting().signatures.mSignatures, pkg.mSignatures)
- == PackageManager.SIGNATURE_MATCH)
- || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
- == PackageManager.SIGNATURE_MATCH);
- if (!allowed && (privilegedPermission || oemPermission)) {
- if (isSystemApp(pkg)) {
- // For updated system applications, a privileged/oem permission
- // is granted only if it had been defined by the original application.
- if (pkg.isUpdatedSystemApp()) {
- final PackageSetting sysPs = mSettings
- .getDisabledSystemPkgLPr(pkg.packageName);
- if (sysPs != null && sysPs.getPermissionsState().hasInstallPermission(perm)) {
- // If the original was granted this permission, we take
- // that grant decision as read and propagate it to the
- // update.
- if ((privilegedPermission && sysPs.isPrivileged())
- || (oemPermission && sysPs.isOem()
- && canGrantOemPermission(sysPs, perm))) {
- allowed = true;
- }
- } else {
- // The system apk may have been updated with an older
- // version of the one on the data partition, but which
- // granted a new system permission that it didn't have
- // before. In this case we do want to allow the app to
- // now get the new permission if the ancestral apk is
- // privileged to get it.
- if (sysPs != null && sysPs.pkg != null
- && isPackageRequestingPermission(sysPs.pkg, perm)
- && ((privilegedPermission && sysPs.isPrivileged())
- || (oemPermission && sysPs.isOem()
- && canGrantOemPermission(sysPs, perm)))) {
- allowed = true;
- }
- // Also if a privileged parent package on the system image or any of
- // its children requested a privileged/oem permission, the updated child
- // packages can also get the permission.
- if (pkg.parentPackage != null) {
- final PackageSetting disabledSysParentPs = mSettings
- .getDisabledSystemPkgLPr(pkg.parentPackage.packageName);
- final PackageParser.Package disabledSysParentPkg =
- (disabledSysParentPs == null || disabledSysParentPs.pkg == null)
- ? null : disabledSysParentPs.pkg;
- if (disabledSysParentPkg != null
- && ((privilegedPermission && disabledSysParentPs.isPrivileged())
- || (oemPermission && disabledSysParentPs.isOem()))) {
- if (isPackageRequestingPermission(disabledSysParentPkg, perm)
- && canGrantOemPermission(disabledSysParentPs, perm)) {
- allowed = true;
- } else if (disabledSysParentPkg.childPackages != null) {
- final int count = disabledSysParentPkg.childPackages.size();
- for (int i = 0; i < count; i++) {
- final PackageParser.Package disabledSysChildPkg =
- disabledSysParentPkg.childPackages.get(i);
- final PackageSetting disabledSysChildPs =
- mSettings.getDisabledSystemPkgLPr(
- disabledSysChildPkg.packageName);
- if (isPackageRequestingPermission(disabledSysChildPkg, perm)
- && canGrantOemPermission(
- disabledSysChildPs, perm)) {
- allowed = true;
- break;
- }
- }
- }
- }
- }
- }
- } else {
- allowed = (privilegedPermission && isPrivilegedApp(pkg))
- || (oemPermission && isOemApp(pkg)
- && canGrantOemPermission(
- mSettings.getPackageLPr(pkg.packageName), perm));
- }
- }
- }
- if (!allowed) {
- if (!allowed
- && bp.isPre23()
- && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- // If this was a previously normal/dangerous permission that got moved
- // to a system permission as part of the runtime permission redesign, then
- // we still want to blindly grant it to old apps.
- allowed = true;
- }
- if (!allowed && bp.isInstaller()
- && pkg.packageName.equals(mRequiredInstallerPackage)) {
- // If this permission is to be granted to the system installer and
- // this app is an installer, then it gets the permission.
- allowed = true;
- }
- if (!allowed && bp.isVerifier()
- && pkg.packageName.equals(mRequiredVerifierPackage)) {
- // If this permission is to be granted to the system verifier and
- // this app is a verifier, then it gets the permission.
- allowed = true;
- }
- if (!allowed && bp.isPreInstalled()
- && isSystemApp(pkg)) {
- // Any pre-installed system app is allowed to get this permission.
- allowed = true;
- }
- if (!allowed && bp.isDevelopment()) {
- // For development permissions, a development permission
- // is granted only if it was already granted.
- allowed = origPermissions.hasInstallPermission(perm);
- }
- if (!allowed && bp.isSetup()
- && pkg.packageName.equals(mSetupWizardPackage)) {
- // If this permission is to be granted to the system setup wizard and
- // this app is a setup wizard, then it gets the permission.
- allowed = true;
- }
- }
- return allowed;
- }
-
- private static boolean canGrantOemPermission(PackageSetting ps, String permission) {
- if (!ps.isOem()) {
- return false;
- }
- // all oem permissions must explicitly be granted or denied
- final Boolean granted =
- SystemConfig.getInstance().getOemPermissions(ps.name).get(permission);
- if (granted == null) {
- throw new IllegalStateException("OEM permission" + permission + " requested by package "
- + ps.name + " must be explicitly declared granted or not");
- }
- return Boolean.TRUE == granted;
- }
-
- private boolean isPackageRequestingPermission(PackageParser.Package pkg, String permission) {
- final int permCount = pkg.requestedPermissions.size();
- for (int j = 0; j < permCount; j++) {
- String requestedPermission = pkg.requestedPermissions.get(j);
- if (permission.equals(requestedPermission)) {
- return true;
- }
- }
- return false;
- }
final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
@@ -16491,7 +15748,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
// don't allow a system upgrade unless the upgrade hash matches
- if (oldPackage.restrictUpdateHash != null && oldPackage.isSystemApp()) {
+ if (oldPackage.restrictUpdateHash != null && oldPackage.isSystem()) {
byte[] digestBytes = null;
try {
final MessageDigest digest = MessageDigest.getInstance("SHA-512");
@@ -16758,7 +16015,9 @@ public class PackageManagerService extends IPackageManager.Stub
setInstallerPackageNameLPw(deletedPackage, installerPackageName);
// Update permissions for restored package
- updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL);
+ mPermissionManager.updatePermissions(
+ deletedPackage.packageName, deletedPackage, false, mPackages.values(),
+ mPermissionCallback);
mSettings.writeLPr();
}
@@ -16900,7 +16159,9 @@ public class PackageManagerService extends IPackageManager.Stub
setInstallerPackageNameLPw(deletedPackage, installerPackageName);
// Update permissions for restored package
- updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL);
+ mPermissionManager.updatePermissions(
+ deletedPackage.packageName, deletedPackage, false, mPackages.values(),
+ mPermissionCallback);
mSettings.writeLPr();
}
@@ -17013,12 +16274,12 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private void updateSettingsInternalLI(PackageParser.Package newPackage,
+ private void updateSettingsInternalLI(PackageParser.Package pkg,
String installerPackageName, int[] allUsers, int[] installedForUsers,
PackageInstalledInfo res, UserHandle user, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
- String pkgName = newPackage.packageName;
+ String pkgName = pkg.packageName;
synchronized (mPackages) {
//write settings. the installStatus will be incomplete at this stage.
//note that the new package setting would have already been
@@ -17030,18 +16291,18 @@ public class PackageManagerService extends IPackageManager.Stub
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.codePath);
+ if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
synchronized (mPackages) {
- updatePermissionsLPw(newPackage.packageName, newPackage,
- UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
- ? UPDATE_PERMISSIONS_ALL : 0));
+// NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
+ mPermissionManager.updatePermissions(pkg.packageName, pkg, true, mPackages.values(),
+ mPermissionCallback);
// For system-bundled packages, we assume that installing an upgraded version
// of the package implies that the user actually wants to run that new code,
// so we enable the package.
PackageSetting ps = mSettings.mPackages.get(pkgName);
final int userId = user.getIdentifier();
if (ps != null) {
- if (isSystemApp(newPackage)) {
+ if (isSystemApp(pkg)) {
if (DEBUG_INSTALL) {
Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
}
@@ -17101,8 +16362,8 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.writeKernelMappingLPr(ps);
}
res.name = pkgName;
- res.uid = newPackage.applicationInfo.uid;
- res.pkg = newPackage;
+ res.uid = pkg.applicationInfo.uid;
+ res.pkg = pkg;
mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
mSettings.setInstallerPackageName(pkgName, installerPackageName);
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
@@ -17801,18 +17062,6 @@ public class PackageManagerService extends IPackageManager.Stub
return installFlags;
}
- private String getVolumeUuidForPackage(PackageParser.Package pkg) {
- if (isExternal(pkg)) {
- if (TextUtils.isEmpty(pkg.volumeUuid)) {
- return StorageManager.UUID_PRIMARY_PHYSICAL;
- } else {
- return pkg.volumeUuid;
- }
- } else {
- return StorageManager.UUID_PRIVATE_INTERNAL;
- }
- }
-
private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) {
if (isExternal(pkg)) {
if (TextUtils.isEmpty(pkg.volumeUuid)) {
@@ -18457,7 +17706,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
}
- updatePermissionsLPw(deletedPs.name, null, 0);
+ mPermissionManager.updatePermissions(
+ deletedPs.name, null, false, mPackages.values(), mPermissionCallback);
if (deletedPs.sharedUser != null) {
// Remove permissions associated with package. Since runtime
// permissions are per user we have to kill the removed package
@@ -18660,21 +17910,21 @@ public class PackageManagerService extends IPackageManager.Stub
parseFlags |= PackageParser.PARSE_IS_OEM;
}
- final PackageParser.Package newPkg =
+ final PackageParser.Package pkg =
scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, 0 /*currentTime*/, null);
try {
// update shared libraries for the newly re-installed system package
- updateSharedLibrariesLPr(newPkg, null);
+ updateSharedLibrariesLPr(pkg, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
}
- prepareAppDataAfterInstallLIF(newPkg);
+ prepareAppDataAfterInstallLIF(pkg);
// writer
synchronized (mPackages) {
- PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
+ PackageSetting ps = mSettings.mPackages.get(pkg.packageName);
// Propagate the permissions state as we do not want to drop on the floor
// runtime permissions. The update permissions method below will take
@@ -18682,8 +17932,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (origPermissionState != null) {
ps.getPermissionsState().copyFrom(origPermissionState);
}
- updatePermissionsLPw(newPkg.packageName, newPkg,
- UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
+ mPermissionManager.updatePermissions(pkg.packageName, pkg, true, mPackages.values(),
+ mPermissionCallback);
final boolean applyUserRestrictions
= (allUserHandles != null) && (origUserHandles != null);
@@ -18716,7 +17966,7 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.writeLPr();
}
}
- return newPkg;
+ return pkg;
}
private boolean deleteInstalledPackageLIF(PackageSetting ps,
@@ -19333,7 +18583,7 @@ public class PackageManagerService extends IPackageManager.Stub
// If permission review is enabled and this is a legacy app, mark the
// permission as requiring a review as this is the initial state.
int flags = 0;
- if (mPermissionReviewRequired
+ if (mSettings.mPermissions.mPermissionReviewRequired
&& ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
}
@@ -20692,7 +19942,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
// data partition and then replace the version on the system partition.
final PackageParser.Package deletedPkg = pkgSetting.pkg;
final boolean isSystemStub = deletedPkg.isStub
- && deletedPkg.isSystemApp();
+ && deletedPkg.isSystem();
if (isSystemStub
&& (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
@@ -20732,22 +19982,23 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
synchronized (mPackages) {
disableSystemPackageLPw(deletedPkg, tmpPkg);
}
- final PackageParser.Package newPkg;
+ final PackageParser.Package pkg;
try (PackageFreezer freezer =
freezePackage(deletedPkg.packageName, "setEnabledSetting")) {
final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| PackageParser.PARSE_ENFORCE_CODE;
- newPkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/,
+ pkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/,
0 /*currentTime*/, null /*user*/);
- prepareAppDataAfterInstallLIF(newPkg);
+ prepareAppDataAfterInstallLIF(pkg);
synchronized (mPackages) {
try {
- updateSharedLibrariesLPr(newPkg, null);
+ updateSharedLibrariesLPr(pkg, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
}
- updatePermissionsLPw(newPkg.packageName, newPkg,
- UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
+ mPermissionManager.updatePermissions(
+ pkg.packageName, pkg, true, mPackages.values(),
+ mPermissionCallback);
mSettings.writeLPr();
}
} catch (PackageManagerException e) {
@@ -20787,11 +20038,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
return;
}
- clearAppDataLIF(newPkg, UserHandle.USER_ALL, FLAG_STORAGE_DE
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE
| FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
- clearAppProfilesLIF(newPkg, UserHandle.USER_ALL);
- mDexManager.notifyPackageUpdated(newPkg.packageName,
- newPkg.baseCodePath, newPkg.splitCodePaths);
+ clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+ mDexManager.notifyPackageUpdated(pkg.packageName,
+ pkg.baseCodePath, pkg.splitCodePaths);
}
}
if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
@@ -21102,8 +20353,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
// permissions, ensure permissions are updated. Beware of dragons if you
// try optimizing this.
synchronized (mPackages) {
- updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL,
- UPDATE_PERMISSIONS_ALL);
+ mPermissionManager.updateAllPermissions(
+ StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
+ mPermissionCallback);
}
// Kick off any messages waiting for system ready
@@ -21152,10 +20404,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
- if (mPrivappPermissionsViolations != null) {
- throw new IllegalStateException("Signature|privileged permissions not in "
- + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
- }
+ mPermissionManager.systemReady();
}
public void waitForAppDataPrepared() {
@@ -22140,13 +21389,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
synchronized (mPackages) {
- int updateFlags = UPDATE_PERMISSIONS_ALL;
- if (ver.sdkVersion != mSdkVersion) {
+ final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
+ if (sdkUpdated) {
logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for " + volumeUuid);
- updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLocked(null, null, volumeUuid, updateFlags);
+ mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated, mPackages.values(),
+ mPermissionCallback);
// Yay, everything is now upgraded
ver.forceCurrent();
@@ -22594,7 +21843,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
* requested by the app.
*/
private boolean maybeMigrateAppDataLIF(PackageParser.Package pkg, int userId) {
- if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
+ if (pkg.isSystem() && !StorageManager.isFileEncryptedNativeOrEmulated()
&& PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
final int storageTarget = pkg.applicationInfo.isDefaultToDeviceProtectedStorage()
? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
@@ -23159,9 +22408,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
// permissions to keep per user flag state whether review is needed.
// Hence, if a new user is added we have to propagate dangerous
// permission grants for these legacy apps.
- if (mPermissionReviewRequired) {
- updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
- | UPDATE_PERMISSIONS_REPLACE_ALL);
+ if (mSettings.mPermissions.mPermissionReviewRequired) {
+// NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
+ mPermissionManager.updateAllPermissions(
+ StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(),
+ mPermissionCallback);
}
}
}
@@ -23606,13 +22857,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
@Override
- public PackageParser.PermissionGroup getPermissionGroupTEMP(String groupName) {
- synchronized (mPackages) {
- return mPermissionGroups.get(groupName);
- }
- }
-
- @Override
public boolean isInstantApp(String packageName, int userId) {
return PackageManagerService.this.isInstantApp(packageName, userId);
}
@@ -23750,24 +22994,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
@Override
public boolean isPermissionsReviewRequired(String packageName, int userId) {
synchronized (mPackages) {
- // If we do not support permission review, done.
- if (!mPermissionReviewRequired) {
- return false;
- }
-
- PackageSetting packageSetting = mSettings.mPackages.get(packageName);
- if (packageSetting == null) {
- return false;
- }
-
- // Permission review applies only to apps not supporting the new permission model.
- if (packageSetting.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
- return false;
- }
-
- // Legacy apps have the permission and get user consent on launch.
- PermissionsState permissionsState = packageSetting.getPermissionsState();
- return permissionsState.isPermissionReviewRequired(userId);
+ return mPermissionManager.isPermissionsReviewRequired(
+ mPackages.get(packageName), userId);
}
}
@@ -23921,6 +23149,16 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
@Override
+ public boolean isLegacySystemApp(Package pkg) {
+ synchronized (mPackages) {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ return mPromoteSystemApps
+ && ps.isSystem()
+ && mExistingSystemPackages.contains(ps.name);
+ }
+ }
+
+ @Override
public List<PackageInfo> getOverlayPackages(int userId) {
final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
synchronized (mPackages) {
diff --git a/com/android/server/pm/PackageManagerShellCommand.java b/com/android/server/pm/PackageManagerShellCommand.java
index 1fea003a..a2099e60 100644
--- a/com/android/server/pm/PackageManagerShellCommand.java
+++ b/com/android/server/pm/PackageManagerShellCommand.java
@@ -16,14 +16,17 @@
package com.android.server.pm;
+import android.accounts.IAccountManager;
import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
@@ -41,6 +44,7 @@ import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
import android.content.pm.VersionedPackage;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -49,15 +53,23 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.IUserManager;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.text.TextUtils;
-import android.util.ArrayMap;
+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.internal.util.SizedInputStream;
import com.android.server.SystemConfig;
@@ -81,6 +93,12 @@ import java.util.WeakHashMap;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+
class PackageManagerShellCommand extends ShellCommand {
/** Path for streaming APK content */
private static final String STDIN_PATH = "-";
@@ -107,6 +125,20 @@ class PackageManagerShellCommand extends ShellCommand {
final PrintWriter pw = getOutPrintWriter();
try {
switch(cmd) {
+ case "path":
+ return runPath();
+ case "dump":
+ return runDump();
+ case "list":
+ return runList();
+ case "resolve-activity":
+ return runResolveActivity();
+ case "query-activities":
+ return runQueryIntentActivities();
+ case "query-services":
+ return runQueryIntentServices();
+ case "query-receivers":
+ return runQueryIntentReceivers();
case "install":
return runInstall();
case "install-abandon":
@@ -122,44 +154,99 @@ class PackageManagerShellCommand extends ShellCommand {
return runInstallWrite();
case "install-existing":
return runInstallExisting();
+ case "set-install-location":
+ return runSetInstallLocation();
+ case "get-install-location":
+ return runGetInstallLocation();
+ case "move-package":
+ return runMovePackage();
+ case "move-primary-storage":
+ return runMovePrimaryStorage();
case "compile":
return runCompile();
case "reconcile-secondary-dex-files":
return runreconcileSecondaryDexFiles();
+ case "force-dex-opt":
+ return runForceDexOpt();
case "bg-dexopt-job":
return runDexoptJob();
case "dump-profiles":
return runDumpProfiles();
- case "list":
- return runList();
case "uninstall":
return runUninstall();
- case "resolve-activity":
- return runResolveActivity();
- case "query-activities":
- return runQueryIntentActivities();
- case "query-services":
- return runQueryIntentServices();
- case "query-receivers":
- return runQueryIntentReceivers();
+ case "clear":
+ return runClear();
+ case "enable":
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ case "disable":
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+ case "disable-user":
+ return runSetEnabledSetting(
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
+ case "disable-until-used":
+ return runSetEnabledSetting(
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+ case "default-state":
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
+ case "hide":
+ return runSetHiddenSetting(true);
+ case "unhide":
+ return runSetHiddenSetting(false);
case "suspend":
return runSuspend(true);
case "unsuspend":
return runSuspend(false);
- case "set-home-activity":
- return runSetHomeActivity();
+ case "grant":
+ return runGrantRevokePermission(true);
+ case "revoke":
+ return runGrantRevokePermission(false);
+ case "reset-permissions":
+ return runResetPermissions();
+ case "set-permission-enforced":
+ return runSetPermissionEnforced();
case "get-privapp-permissions":
return runGetPrivappPermissions();
case "get-privapp-deny-permissions":
return runGetPrivappDenyPermissions();
case "get-oem-permissions":
return runGetOemPermissions();
+ case "set-app-link":
+ return runSetAppLink();
+ case "get-app-link":
+ return runGetAppLink();
+ case "trim-caches":
+ return runTrimCaches();
+ case "create-user":
+ return runCreateUser();
+ case "remove-user":
+ return runRemoveUser();
+ case "set-user-restriction":
+ return runSetUserRestriction();
+ case "get-max-users":
+ return runGetMaxUsers();
+ case "set-home-activity":
+ return runSetHomeActivity();
+ case "set-installer":
+ return runSetInstaller();
case "get-instantapp-resolver":
return runGetInstantAppResolver();
case "has-feature":
return runHasFeature();
- default:
+ default: {
+ String nextArg = getNextArg();
+ if (nextArg == null) {
+ if (cmd.equalsIgnoreCase("-l")) {
+ return runListPackages(false);
+ } else if (cmd.equalsIgnoreCase("-lf")) {
+ return runListPackages(true);
+ }
+ } else if (getNextArg() == null) {
+ if (cmd.equalsIgnoreCase("-p")) {
+ return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
+ }
+ }
return handleDefaultCommands(cmd);
+ }
}
} catch (RemoteException e) {
pw.println("Remote exception: " + e);
@@ -195,346 +282,40 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
}
-
- private int runInstall() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- final InstallParams params = makeInstallParams();
- final String inPath = getNextArg();
-
- setParamsSize(params, inPath);
- final int sessionId = doCreateSession(params.sessionParams,
- params.installerPackageName, params.userId);
- boolean abandonSession = true;
- try {
- if (inPath == null && params.sessionParams.sizeBytes == -1) {
- pw.println("Error: must either specify a package size or an APK file");
- return 1;
- }
- if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
- false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
- if (doCommitSession(sessionId, false /*logSuccess*/)
- != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
- abandonSession = false;
- pw.println("Success");
- return 0;
- } finally {
- if (abandonSession) {
- try {
- doAbandonSession(sessionId, false /*logSuccess*/);
- } catch (Exception ignore) {
+ /**
+ * Displays the package file for a package.
+ * @param pckg
+ */
+ private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
+ PackageInfo info = mInterface.getPackageInfo(pckg, 0, userId);
+ if (info != null && info.applicationInfo != null) {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.print("package:");
+ pw.println(info.applicationInfo.sourceDir);
+ if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
+ for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
+ pw.print("package:");
+ pw.println(splitSourceDir);
}
}
- }
- }
-
- private int runSuspend(boolean suspendedState) {
- final PrintWriter pw = getOutPrintWriter();
- int userId = UserHandle.USER_SYSTEM;
- String opt;
- while ((opt = getNextOption()) != null) {
- switch (opt) {
- case "--user":
- userId = UserHandle.parseUserArg(getNextArgRequired());
- break;
- default:
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
-
- String packageName = getNextArg();
- if (packageName == null) {
- pw.println("Error: package name not specified");
- return 1;
- }
-
- try {
- mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
- userId);
- pw.println("Package " + packageName + " new suspended state: "
- + mInterface.isPackageSuspendedForUser(packageName, userId));
return 0;
- } catch (RemoteException | IllegalArgumentException e) {
- pw.println(e.toString());
- return 1;
}
+ return 1;
}
- private int runInstallAbandon() throws RemoteException {
- final int sessionId = Integer.parseInt(getNextArg());
- return doAbandonSession(sessionId, true /*logSuccess*/);
- }
-
- private int runInstallCommit() throws RemoteException {
- final int sessionId = Integer.parseInt(getNextArg());
- return doCommitSession(sessionId, true /*logSuccess*/);
- }
-
- private int runInstallCreate() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- final InstallParams installParams = makeInstallParams();
- final int sessionId = doCreateSession(installParams.sessionParams,
- installParams.installerPackageName, installParams.userId);
-
- // NOTE: adb depends on parsing this string
- pw.println("Success: created install session [" + sessionId + "]");
- return 0;
- }
-
- private int runInstallWrite() throws RemoteException {
- long sizeBytes = -1;
-
- String opt;
- while ((opt = getNextOption()) != null) {
- if (opt.equals("-S")) {
- sizeBytes = Long.parseLong(getNextArg());
- } else {
- throw new IllegalArgumentException("Unknown option: " + opt);
- }
- }
-
- final int sessionId = Integer.parseInt(getNextArg());
- final String splitName = getNextArg();
- final String path = getNextArg();
- return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
- }
-
- private int runInstallRemove() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
-
- final int sessionId = Integer.parseInt(getNextArg());
-
- final String splitName = getNextArg();
- if (splitName == null) {
- pw.println("Error: split name not specified");
- return 1;
- }
- return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
- }
-
- private int runInstallExisting() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
+ private int runPath() throws RemoteException {
int userId = UserHandle.USER_SYSTEM;
- int installFlags = 0;
- String opt;
- while ((opt = getNextOption()) != null) {
- switch (opt) {
- case "--user":
- userId = UserHandle.parseUserArg(getNextArgRequired());
- break;
- case "--ephemeral":
- case "--instant":
- installFlags |= PackageManager.INSTALL_INSTANT_APP;
- installFlags &= ~PackageManager.INSTALL_FULL_APP;
- break;
- case "--full":
- installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
- installFlags |= PackageManager.INSTALL_FULL_APP;
- break;
- default:
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
}
- final String packageName = getNextArg();
- if (packageName == null) {
- pw.println("Error: package name not specified");
- return 1;
- }
-
- try {
- final int res = mInterface.installExistingPackageAsUser(packageName, userId,
- installFlags, PackageManager.INSTALL_REASON_UNKNOWN);
- if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
- throw new NameNotFoundException("Package " + packageName + " doesn't exist");
- }
- pw.println("Package " + packageName + " installed for user: " + userId);
- return 0;
- } catch (RemoteException | NameNotFoundException e) {
- pw.println(e.toString());
- return 1;
- }
- }
-
- private int runCompile() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
- boolean forceCompilation = false;
- boolean allPackages = false;
- boolean clearProfileData = false;
- String compilerFilter = null;
- String compilationReason = null;
- String checkProfilesRaw = null;
- boolean secondaryDex = false;
- String split = null;
-
- String opt;
- while ((opt = getNextOption()) != null) {
- switch (opt) {
- case "-a":
- allPackages = true;
- break;
- case "-c":
- clearProfileData = true;
- break;
- case "-f":
- forceCompilation = true;
- break;
- case "-m":
- compilerFilter = getNextArgRequired();
- break;
- case "-r":
- compilationReason = getNextArgRequired();
- break;
- case "--check-prof":
- checkProfilesRaw = getNextArgRequired();
- break;
- case "--reset":
- forceCompilation = true;
- clearProfileData = true;
- compilationReason = "install";
- break;
- case "--secondary-dex":
- secondaryDex = true;
- break;
- case "--split":
- split = getNextArgRequired();
- break;
- default:
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
-
- if (checkProfilesRaw != null) {
- if ("true".equals(checkProfilesRaw)) {
- checkProfiles = true;
- } else if ("false".equals(checkProfilesRaw)) {
- checkProfiles = false;
- } else {
- pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
- return 1;
- }
- }
-
- if (compilerFilter != null && compilationReason != null) {
- pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
- "at the same time");
- return 1;
- }
- if (compilerFilter == null && compilationReason == null) {
- pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
- "reason (\"-r\") at the same time");
- return 1;
- }
-
- if (allPackages && split != null) {
- pw.println("-a cannot be specified together with --split");
- return 1;
- }
-
- if (secondaryDex && split != null) {
- pw.println("--secondary-dex cannot be specified together with --split");
- return 1;
- }
-
- String targetCompilerFilter;
- if (compilerFilter != null) {
- if (!DexFile.isValidCompilerFilter(compilerFilter)) {
- pw.println("Error: \"" + compilerFilter +
- "\" is not a valid compilation filter.");
- return 1;
- }
- targetCompilerFilter = compilerFilter;
- } else {
- int reason = -1;
- for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
- if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
- compilationReason)) {
- reason = i;
- break;
- }
- }
- if (reason == -1) {
- pw.println("Error: Unknown compilation reason: " + compilationReason);
- return 1;
- }
- targetCompilerFilter =
- PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
- }
-
-
- List<String> packageNames = null;
- if (allPackages) {
- packageNames = mInterface.getAllPackages();
- } else {
- String packageName = getNextArg();
- if (packageName == null) {
- pw.println("Error: package name not specified");
- return 1;
- }
- packageNames = Collections.singletonList(packageName);
- }
-
- List<String> failedPackages = new ArrayList<>();
- for (String packageName : packageNames) {
- if (clearProfileData) {
- mInterface.clearApplicationProfileData(packageName);
- }
-
- boolean result = secondaryDex
- ? mInterface.performDexOptSecondary(packageName,
- targetCompilerFilter, forceCompilation)
- : mInterface.performDexOptMode(packageName,
- checkProfiles, targetCompilerFilter, forceCompilation,
- true /* bootComplete */, split);
- if (!result) {
- failedPackages.add(packageName);
- }
- }
-
- if (failedPackages.isEmpty()) {
- pw.println("Success");
- return 0;
- } else if (failedPackages.size() == 1) {
- pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
- return 1;
- } else {
- pw.print("Failure: the following packages could not be compiled: ");
- boolean is_first = true;
- for (String packageName : failedPackages) {
- if (is_first) {
- is_first = false;
- } else {
- pw.print(", ");
- }
- pw.print(packageName);
- }
- pw.println();
+ String pkg = getNextArgRequired();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified");
return 1;
}
- }
-
- private int runreconcileSecondaryDexFiles() throws RemoteException {
- String packageName = getNextArg();
- mInterface.reconcileSecondaryDexFiles(packageName);
- return 0;
- }
-
- private int runDexoptJob() throws RemoteException {
- boolean result = mInterface.runBackgroundDexoptJob();
- return result ? 0 : -1;
- }
-
- private int runDumpProfiles() throws RemoteException {
- String packageName = getNextArg();
- mInterface.dumpProfiles(packageName);
- return 0;
+ return displayPackageFilePath(pkg, userId);
}
private int runList() throws RemoteException {
@@ -558,6 +339,11 @@ class PackageManagerShellCommand extends ShellCommand {
return runListPermissionGroups();
case "permissions":
return runListPermissions();
+ case "users":
+ ServiceManager.getService("user").shellCommand(
+ getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
+ new String[] { "list" }, getShellCallback(), adoptResultReceiver());
+ return 0;
}
pw.println("Error: unknown list type '" + type + "'");
return -1;
@@ -590,7 +376,7 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println();
} else {
pw.println("reqGlEsVersion=0x"
- + Integer.toHexString(fi.reqGlEsVersion));
+ + Integer.toHexString(fi.reqGlEsVersion));
}
}
return 0;
@@ -872,111 +658,6 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
- private int runUninstall() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- int flags = 0;
- int userId = UserHandle.USER_ALL;
- int versionCode = PackageManager.VERSION_CODE_HIGHEST;
-
- String opt;
- while ((opt = getNextOption()) != null) {
- switch (opt) {
- case "-k":
- flags |= PackageManager.DELETE_KEEP_DATA;
- break;
- case "--user":
- userId = UserHandle.parseUserArg(getNextArgRequired());
- break;
- case "--versionCode":
- versionCode = Integer.parseInt(getNextArgRequired());
- break;
- default:
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
-
- final String packageName = getNextArg();
- if (packageName == null) {
- pw.println("Error: package name not specified");
- return 1;
- }
-
- // if a split is specified, just remove it and not the whole package
- final String splitName = getNextArg();
- if (splitName != null) {
- return runRemoveSplit(packageName, splitName);
- }
-
- userId = translateUserId(userId, "runUninstall");
- if (userId == UserHandle.USER_ALL) {
- userId = UserHandle.USER_SYSTEM;
- flags |= PackageManager.DELETE_ALL_USERS;
- } else {
- final PackageInfo info = mInterface.getPackageInfo(packageName,
- PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
- if (info == null) {
- pw.println("Failure [not installed for " + userId + "]");
- return 1;
- }
- final boolean isSystem =
- (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- // If we are being asked to delete a system app for just one
- // user set flag so it disables rather than reverting to system
- // version of the app.
- if (isSystem) {
- flags |= PackageManager.DELETE_SYSTEM_APP;
- }
- }
-
- final LocalIntentReceiver receiver = new LocalIntentReceiver();
- mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
- versionCode), null /*callerPackageName*/, flags,
- receiver.getIntentSender(), userId);
-
- final Intent result = receiver.getResult();
- final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
- if (status == PackageInstaller.STATUS_SUCCESS) {
- pw.println("Success");
- return 0;
- } else {
- pw.println("Failure ["
- + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
- return 1;
- }
- }
-
- private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
- sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
- sessionParams.appPackageName = packageName;
- final int sessionId =
- doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
- boolean abandonSession = true;
- try {
- if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
- != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
- if (doCommitSession(sessionId, false /*logSuccess*/)
- != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
- abandonSession = false;
- pw.println("Success");
- return 0;
- } finally {
- if (abandonSession) {
- try {
- doAbandonSession(sessionId, false /*logSuccess*/);
- } catch (Exception ignore) {
- }
- }
- }
- }
-
private Intent parseIntentAndUser() throws URISyntaxException {
mTargetUser = UserHandle.USER_CURRENT;
mBrief = false;
@@ -1154,6 +835,1029 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
+ private int runInstall() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final InstallParams params = makeInstallParams();
+ final String inPath = getNextArg();
+
+ setParamsSize(params, inPath);
+ final int sessionId = doCreateSession(params.sessionParams,
+ params.installerPackageName, params.userId);
+ boolean abandonSession = true;
+ try {
+ if (inPath == null && params.sessionParams.sizeBytes == -1) {
+ pw.println("Error: must either specify a package size or an APK file");
+ return 1;
+ }
+ if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
+ false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
+ return 1;
+ }
+ if (doCommitSession(sessionId, false /*logSuccess*/)
+ != PackageInstaller.STATUS_SUCCESS) {
+ return 1;
+ }
+ abandonSession = false;
+ pw.println("Success");
+ return 0;
+ } finally {
+ if (abandonSession) {
+ try {
+ doAbandonSession(sessionId, false /*logSuccess*/);
+ } catch (Exception ignore) {
+ }
+ }
+ }
+ }
+
+ private int runInstallAbandon() throws RemoteException {
+ final int sessionId = Integer.parseInt(getNextArg());
+ return doAbandonSession(sessionId, true /*logSuccess*/);
+ }
+
+ private int runInstallCommit() throws RemoteException {
+ final int sessionId = Integer.parseInt(getNextArg());
+ return doCommitSession(sessionId, true /*logSuccess*/);
+ }
+
+ private int runInstallCreate() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final InstallParams installParams = makeInstallParams();
+ final int sessionId = doCreateSession(installParams.sessionParams,
+ installParams.installerPackageName, installParams.userId);
+
+ // NOTE: adb depends on parsing this string
+ pw.println("Success: created install session [" + sessionId + "]");
+ return 0;
+ }
+
+ private int runInstallWrite() throws RemoteException {
+ long sizeBytes = -1;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("-S")) {
+ sizeBytes = Long.parseLong(getNextArg());
+ } else {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+
+ final int sessionId = Integer.parseInt(getNextArg());
+ final String splitName = getNextArg();
+ final String path = getNextArg();
+ return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
+ }
+
+ private int runInstallRemove() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+
+ final int sessionId = Integer.parseInt(getNextArg());
+
+ final String splitName = getNextArg();
+ if (splitName == null) {
+ pw.println("Error: split name not specified");
+ return 1;
+ }
+ return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
+ }
+
+ private int runInstallExisting() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ int userId = UserHandle.USER_SYSTEM;
+ int installFlags = 0;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--user":
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ case "--ephemeral":
+ case "--instant":
+ installFlags |= PackageManager.INSTALL_INSTANT_APP;
+ installFlags &= ~PackageManager.INSTALL_FULL_APP;
+ break;
+ case "--full":
+ installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
+ installFlags |= PackageManager.INSTALL_FULL_APP;
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ final String packageName = getNextArg();
+ if (packageName == null) {
+ pw.println("Error: package name not specified");
+ return 1;
+ }
+
+ try {
+ final int res = mInterface.installExistingPackageAsUser(packageName, userId,
+ installFlags, PackageManager.INSTALL_REASON_UNKNOWN);
+ if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
+ throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+ }
+ pw.println("Package " + packageName + " installed for user: " + userId);
+ return 0;
+ } catch (RemoteException | NameNotFoundException e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
+ private int runSetInstallLocation() throws RemoteException {
+ int loc;
+
+ String arg = getNextArg();
+ if (arg == null) {
+ getErrPrintWriter().println("Error: no install location specified.");
+ return 1;
+ }
+ try {
+ loc = Integer.parseInt(arg);
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: install location has to be a number.");
+ return 1;
+ }
+ if (!mInterface.setInstallLocation(loc)) {
+ getErrPrintWriter().println("Error: install location has to be a number.");
+ return 1;
+ }
+ return 0;
+ }
+
+ private int runGetInstallLocation() throws RemoteException {
+ int loc = mInterface.getInstallLocation();
+ String locStr = "invalid";
+ if (loc == PackageHelper.APP_INSTALL_AUTO) {
+ locStr = "auto";
+ } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
+ locStr = "internal";
+ } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
+ locStr = "external";
+ }
+ getOutPrintWriter().println(loc + "[" + locStr + "]");
+ return 0;
+ }
+
+ public int runMovePackage() throws RemoteException {
+ final String packageName = getNextArg();
+ if (packageName == null) {
+ getErrPrintWriter().println("Error: package name not specified");
+ return 1;
+ }
+ String volumeUuid = getNextArg();
+ if ("internal".equals(volumeUuid)) {
+ volumeUuid = null;
+ }
+
+ final int moveId = mInterface.movePackage(packageName, volumeUuid);
+
+ int status = mInterface.getMoveStatus(moveId);
+ while (!PackageManager.isMoveStatusFinished(status)) {
+ SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
+ status = mInterface.getMoveStatus(moveId);
+ }
+
+ if (status == PackageManager.MOVE_SUCCEEDED) {
+ getOutPrintWriter().println("Success");
+ return 0;
+ } else {
+ getErrPrintWriter().println("Failure [" + status + "]");
+ return 1;
+ }
+ }
+
+ public int runMovePrimaryStorage() throws RemoteException {
+ String volumeUuid = getNextArg();
+ if ("internal".equals(volumeUuid)) {
+ volumeUuid = null;
+ }
+
+ final int moveId = mInterface.movePrimaryStorage(volumeUuid);
+
+ int status = mInterface.getMoveStatus(moveId);
+ while (!PackageManager.isMoveStatusFinished(status)) {
+ SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
+ status = mInterface.getMoveStatus(moveId);
+ }
+
+ if (status == PackageManager.MOVE_SUCCEEDED) {
+ getOutPrintWriter().println("Success");
+ return 0;
+ } else {
+ getErrPrintWriter().println("Failure [" + status + "]");
+ return 1;
+ }
+ }
+
+ private int runCompile() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
+ boolean forceCompilation = false;
+ boolean allPackages = false;
+ boolean clearProfileData = false;
+ String compilerFilter = null;
+ String compilationReason = null;
+ String checkProfilesRaw = null;
+ boolean secondaryDex = false;
+ String split = null;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-a":
+ allPackages = true;
+ break;
+ case "-c":
+ clearProfileData = true;
+ break;
+ case "-f":
+ forceCompilation = true;
+ break;
+ case "-m":
+ compilerFilter = getNextArgRequired();
+ break;
+ case "-r":
+ compilationReason = getNextArgRequired();
+ break;
+ case "--check-prof":
+ checkProfilesRaw = getNextArgRequired();
+ break;
+ case "--reset":
+ forceCompilation = true;
+ clearProfileData = true;
+ compilationReason = "install";
+ break;
+ case "--secondary-dex":
+ secondaryDex = true;
+ break;
+ case "--split":
+ split = getNextArgRequired();
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ if (checkProfilesRaw != null) {
+ if ("true".equals(checkProfilesRaw)) {
+ checkProfiles = true;
+ } else if ("false".equals(checkProfilesRaw)) {
+ checkProfiles = false;
+ } else {
+ pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
+ return 1;
+ }
+ }
+
+ if (compilerFilter != null && compilationReason != null) {
+ pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
+ "at the same time");
+ return 1;
+ }
+ if (compilerFilter == null && compilationReason == null) {
+ pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
+ "reason (\"-r\") at the same time");
+ return 1;
+ }
+
+ if (allPackages && split != null) {
+ pw.println("-a cannot be specified together with --split");
+ return 1;
+ }
+
+ if (secondaryDex && split != null) {
+ pw.println("--secondary-dex cannot be specified together with --split");
+ return 1;
+ }
+
+ String targetCompilerFilter;
+ if (compilerFilter != null) {
+ if (!DexFile.isValidCompilerFilter(compilerFilter)) {
+ pw.println("Error: \"" + compilerFilter +
+ "\" is not a valid compilation filter.");
+ return 1;
+ }
+ targetCompilerFilter = compilerFilter;
+ } else {
+ int reason = -1;
+ for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
+ if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
+ compilationReason)) {
+ reason = i;
+ break;
+ }
+ }
+ if (reason == -1) {
+ pw.println("Error: Unknown compilation reason: " + compilationReason);
+ return 1;
+ }
+ targetCompilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
+ }
+
+
+ List<String> packageNames = null;
+ if (allPackages) {
+ packageNames = mInterface.getAllPackages();
+ } else {
+ String packageName = getNextArg();
+ if (packageName == null) {
+ pw.println("Error: package name not specified");
+ return 1;
+ }
+ packageNames = Collections.singletonList(packageName);
+ }
+
+ List<String> failedPackages = new ArrayList<>();
+ for (String packageName : packageNames) {
+ if (clearProfileData) {
+ mInterface.clearApplicationProfileData(packageName);
+ }
+
+ boolean result = secondaryDex
+ ? mInterface.performDexOptSecondary(packageName,
+ targetCompilerFilter, forceCompilation)
+ : mInterface.performDexOptMode(packageName,
+ checkProfiles, targetCompilerFilter, forceCompilation,
+ true /* bootComplete */, split);
+ if (!result) {
+ failedPackages.add(packageName);
+ }
+ }
+
+ if (failedPackages.isEmpty()) {
+ pw.println("Success");
+ return 0;
+ } else if (failedPackages.size() == 1) {
+ pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
+ return 1;
+ } else {
+ pw.print("Failure: the following packages could not be compiled: ");
+ boolean is_first = true;
+ for (String packageName : failedPackages) {
+ if (is_first) {
+ is_first = false;
+ } else {
+ pw.print(", ");
+ }
+ pw.print(packageName);
+ }
+ pw.println();
+ return 1;
+ }
+ }
+
+ private int runreconcileSecondaryDexFiles() throws RemoteException {
+ String packageName = getNextArg();
+ mInterface.reconcileSecondaryDexFiles(packageName);
+ return 0;
+ }
+
+ public int runForceDexOpt() throws RemoteException {
+ mInterface.forceDexOpt(getNextArgRequired());
+ return 0;
+ }
+
+ private int runDexoptJob() throws RemoteException {
+ boolean result = mInterface.runBackgroundDexoptJob();
+ return result ? 0 : -1;
+ }
+
+ private int runDumpProfiles() throws RemoteException {
+ String packageName = getNextArg();
+ mInterface.dumpProfiles(packageName);
+ return 0;
+ }
+
+ private int runUninstall() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ int flags = 0;
+ int userId = UserHandle.USER_ALL;
+ int versionCode = PackageManager.VERSION_CODE_HIGHEST;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-k":
+ flags |= PackageManager.DELETE_KEEP_DATA;
+ break;
+ case "--user":
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ case "--versionCode":
+ versionCode = Integer.parseInt(getNextArgRequired());
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ final String packageName = getNextArg();
+ if (packageName == null) {
+ pw.println("Error: package name not specified");
+ return 1;
+ }
+
+ // if a split is specified, just remove it and not the whole package
+ final String splitName = getNextArg();
+ if (splitName != null) {
+ return runRemoveSplit(packageName, splitName);
+ }
+
+ userId = translateUserId(userId, "runUninstall");
+ if (userId == UserHandle.USER_ALL) {
+ userId = UserHandle.USER_SYSTEM;
+ flags |= PackageManager.DELETE_ALL_USERS;
+ } else {
+ final PackageInfo info = mInterface.getPackageInfo(packageName,
+ PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
+ if (info == null) {
+ pw.println("Failure [not installed for " + userId + "]");
+ return 1;
+ }
+ final boolean isSystem =
+ (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ // If we are being asked to delete a system app for just one
+ // user set flag so it disables rather than reverting to system
+ // version of the app.
+ if (isSystem) {
+ flags |= PackageManager.DELETE_SYSTEM_APP;
+ }
+ }
+
+ final LocalIntentReceiver receiver = new LocalIntentReceiver();
+ mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
+ versionCode), null /*callerPackageName*/, flags,
+ receiver.getIntentSender(), userId);
+
+ final Intent result = receiver.getResult();
+ final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ if (status == PackageInstaller.STATUS_SUCCESS) {
+ pw.println("Success");
+ return 0;
+ } else {
+ pw.println("Failure ["
+ + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
+ return 1;
+ }
+ }
+
+ private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+ sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+ sessionParams.appPackageName = packageName;
+ final int sessionId =
+ doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
+ boolean abandonSession = true;
+ try {
+ if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
+ != PackageInstaller.STATUS_SUCCESS) {
+ return 1;
+ }
+ if (doCommitSession(sessionId, false /*logSuccess*/)
+ != PackageInstaller.STATUS_SUCCESS) {
+ return 1;
+ }
+ abandonSession = false;
+ pw.println("Success");
+ return 0;
+ } finally {
+ if (abandonSession) {
+ try {
+ doAbandonSession(sessionId, false /*logSuccess*/);
+ } catch (Exception ignore) {
+ }
+ }
+ }
+ }
+
+ static class ClearDataObserver extends IPackageDataObserver.Stub {
+ boolean finished;
+ boolean result;
+
+ @Override
+ public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
+ synchronized (this) {
+ finished = true;
+ result = succeeded;
+ notifyAll();
+ }
+ }
+ }
+
+ private int runClear() throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+
+ String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified");
+ return 1;
+ }
+
+ ClearDataObserver obs = new ClearDataObserver();
+ ActivityManager.getService().clearApplicationUserData(pkg, obs, userId);
+ synchronized (obs) {
+ while (!obs.finished) {
+ try {
+ obs.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ if (obs.result) {
+ getOutPrintWriter().println("Success");
+ return 0;
+ } else {
+ getErrPrintWriter().println("Failed");
+ return 1;
+ }
+ }
+
+ private static String enabledSettingToString(int state) {
+ switch (state) {
+ case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
+ return "default";
+ case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
+ return "enabled";
+ case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
+ return "disabled";
+ case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
+ return "disabled-user";
+ case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+ return "disabled-until-used";
+ }
+ return "unknown";
+ }
+
+ private int runSetEnabledSetting(int state) throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+
+ String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package or component specified");
+ return 1;
+ }
+ ComponentName cn = ComponentName.unflattenFromString(pkg);
+ if (cn == null) {
+ mInterface.setApplicationEnabledSetting(pkg, state, 0, userId,
+ "shell:" + android.os.Process.myUid());
+ getOutPrintWriter().println("Package " + pkg + " new state: "
+ + enabledSettingToString(
+ mInterface.getApplicationEnabledSetting(pkg, userId)));
+ return 0;
+ } else {
+ mInterface.setComponentEnabledSetting(cn, state, 0, userId);
+ getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
+ + enabledSettingToString(
+ mInterface.getComponentEnabledSetting(cn, userId)));
+ return 0;
+ }
+ }
+
+ private int runSetHiddenSetting(boolean state) throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+
+ String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package or component specified");
+ return 1;
+ }
+ mInterface.setApplicationHiddenSettingAsUser(pkg, state, userId);
+ getOutPrintWriter().println("Package " + pkg + " new hidden state: "
+ + mInterface.getApplicationHiddenSettingAsUser(pkg, userId));
+ return 0;
+ }
+
+ private int runSuspend(boolean suspendedState) {
+ final PrintWriter pw = getOutPrintWriter();
+ int userId = UserHandle.USER_SYSTEM;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--user":
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ String packageName = getNextArg();
+ if (packageName == null) {
+ pw.println("Error: package name not specified");
+ return 1;
+ }
+
+ try {
+ mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
+ userId);
+ pw.println("Package " + packageName + " new suspended state: "
+ + mInterface.isPackageSuspendedForUser(packageName, userId));
+ return 0;
+ } catch (RemoteException | IllegalArgumentException e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
+ private int runGrantRevokePermission(boolean grant) throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+
+ String opt = null;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+ }
+
+ String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified");
+ return 1;
+ }
+ String perm = getNextArg();
+ if (perm == null) {
+ getErrPrintWriter().println("Error: no permission specified");
+ return 1;
+ }
+
+ if (grant) {
+ mInterface.grantRuntimePermission(pkg, perm, userId);
+ } else {
+ mInterface.revokeRuntimePermission(pkg, perm, userId);
+ }
+ return 0;
+ }
+
+ private int runResetPermissions() throws RemoteException {
+ mInterface.resetRuntimePermissions();
+ return 0;
+ }
+
+ private int runSetPermissionEnforced() throws RemoteException {
+ final String permission = getNextArg();
+ if (permission == null) {
+ getErrPrintWriter().println("Error: no permission specified");
+ return 1;
+ }
+ final String enforcedRaw = getNextArg();
+ if (enforcedRaw == null) {
+ getErrPrintWriter().println("Error: no enforcement specified");
+ return 1;
+ }
+ mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
+ return 0;
+ }
+
+ private int runGetPrivappPermissions() {
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified.");
+ return 1;
+ }
+ ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ getOutPrintWriter().println(privAppPermissions == null
+ ? "{}" : privAppPermissions.toString());
+ return 0;
+ }
+
+ private int runGetPrivappDenyPermissions() {
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified.");
+ return 1;
+ }
+ ArraySet<String> privAppDenyPermissions =
+ SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ getOutPrintWriter().println(privAppDenyPermissions == null
+ ? "{}" : privAppDenyPermissions.toString());
+ return 0;
+ }
+
+ private int runGetOemPermissions() {
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified.");
+ return 1;
+ }
+ final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
+ .getOemPermissions(pkg);
+ if (oemPermissions == null || oemPermissions.isEmpty()) {
+ getOutPrintWriter().println("{}");
+ } else {
+ oemPermissions.forEach((permission, granted) ->
+ getOutPrintWriter().println(permission + " granted:" + granted)
+ );
+ }
+ return 0;
+ }
+
+ private String linkStateToString(int state) {
+ switch (state) {
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
+ }
+ return "Unknown link state: " + state;
+ }
+
+ // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
+ private int runSetAppLink() throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ // Package name to act on; required
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified.");
+ return 1;
+ }
+
+ // State to apply; {always|ask|never|undefined}, required
+ final String modeString = getNextArg();
+ if (modeString == null) {
+ getErrPrintWriter().println("Error: no app link state specified.");
+ return 1;
+ }
+
+ final int newMode;
+ switch (modeString.toLowerCase()) {
+ case "undefined":
+ newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+ break;
+
+ case "always":
+ newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+ break;
+
+ case "ask":
+ newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+ break;
+
+ case "always-ask":
+ newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
+ break;
+
+ case "never":
+ newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+ break;
+
+ default:
+ getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
+ return 1;
+ }
+
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
+ if (info == null) {
+ getErrPrintWriter().println("Error: package " + pkg + " not found.");
+ return 1;
+ }
+
+ if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
+ getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
+ return 1;
+ }
+
+ if (!mInterface.updateIntentVerificationStatus(pkg, newMode, userId)) {
+ getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
+ return 1;
+ }
+
+ return 0;
+ }
+
+ // pm get-app-link [--user USER_ID] PACKAGE
+ private int runGetAppLink() throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ // Package name to act on; required
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified.");
+ return 1;
+ }
+
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
+ if (info == null) {
+ getErrPrintWriter().println("Error: package " + pkg + " not found.");
+ return 1;
+ }
+
+ if ((info.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
+ getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
+ return 1;
+ }
+
+ getOutPrintWriter().println(linkStateToString(
+ mInterface.getIntentVerificationStatus(pkg, userId)));
+
+ return 0;
+ }
+
+ private int runTrimCaches() throws RemoteException {
+ String size = getNextArg();
+ if (size == null) {
+ getErrPrintWriter().println("Error: no size specified");
+ return 1;
+ }
+ long multiplier = 1;
+ int len = size.length();
+ char c = size.charAt(len - 1);
+ if (c < '0' || c > '9') {
+ if (c == 'K' || c == 'k') {
+ multiplier = 1024L;
+ } else if (c == 'M' || c == 'm') {
+ multiplier = 1024L*1024L;
+ } else if (c == 'G' || c == 'g') {
+ multiplier = 1024L*1024L*1024L;
+ } else {
+ getErrPrintWriter().println("Invalid suffix: " + c);
+ return 1;
+ }
+ size = size.substring(0, len-1);
+ }
+ long sizeVal;
+ try {
+ sizeVal = Long.parseLong(size) * multiplier;
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: expected number at: " + size);
+ return 1;
+ }
+ String volumeUuid = getNextArg();
+ if ("internal".equals(volumeUuid)) {
+ volumeUuid = null;
+ }
+ ClearDataObserver obs = new ClearDataObserver();
+ mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
+ StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
+ synchronized (obs) {
+ while (!obs.finished) {
+ try {
+ obs.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ return 0;
+ }
+
+ private static boolean isNumber(String s) {
+ try {
+ Integer.parseInt(s);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ return true;
+ }
+
+ public int runCreateUser() throws RemoteException {
+ String name;
+ int userId = -1;
+ int flags = 0;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if ("--profileOf".equals(opt)) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else if ("--managed".equals(opt)) {
+ flags |= UserInfo.FLAG_MANAGED_PROFILE;
+ } else if ("--restricted".equals(opt)) {
+ flags |= UserInfo.FLAG_RESTRICTED;
+ } else if ("--ephemeral".equals(opt)) {
+ flags |= UserInfo.FLAG_EPHEMERAL;
+ } else if ("--guest".equals(opt)) {
+ flags |= UserInfo.FLAG_GUEST;
+ } else if ("--demo".equals(opt)) {
+ flags |= UserInfo.FLAG_DEMO;
+ } else {
+ getErrPrintWriter().println("Error: unknown option " + opt);
+ return 1;
+ }
+ }
+ String arg = getNextArg();
+ if (arg == null) {
+ getErrPrintWriter().println("Error: no user name specified.");
+ return 1;
+ }
+ name = arg;
+ UserInfo info;
+ IUserManager um = IUserManager.Stub.asInterface(
+ ServiceManager.getService(Context.USER_SERVICE));
+ IAccountManager accm = IAccountManager.Stub.asInterface(
+ ServiceManager.getService(Context.ACCOUNT_SERVICE));
+ if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
+ // In non-split user mode, userId can only be SYSTEM
+ int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
+ info = um.createRestrictedProfile(name, parentUserId);
+ accm.addSharedAccountsFromParentUser(parentUserId, userId,
+ (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
+ } else if (userId < 0) {
+ info = um.createUser(name, flags);
+ } else {
+ info = um.createProfileForUser(name, flags, userId, null);
+ }
+
+ if (info != null) {
+ getOutPrintWriter().println("Success: created user id " + info.id);
+ return 0;
+ } else {
+ getErrPrintWriter().println("Error: couldn't create User.");
+ return 1;
+ }
+ }
+
+ public int runRemoveUser() throws RemoteException {
+ int userId;
+ String arg = getNextArg();
+ if (arg == null) {
+ getErrPrintWriter().println("Error: no user id specified.");
+ return 1;
+ }
+ userId = UserHandle.parseUserArg(arg);
+ IUserManager um = IUserManager.Stub.asInterface(
+ ServiceManager.getService(Context.USER_SERVICE));
+ if (um.removeUser(userId)) {
+ getOutPrintWriter().println("Success: removed user");
+ return 0;
+ } else {
+ getErrPrintWriter().println("Error: couldn't remove user id " + userId);
+ return 1;
+ }
+ }
+
+ public int runSetUserRestriction() throws RemoteException {
+ int userId = UserHandle.USER_SYSTEM;
+ String opt = getNextOption();
+ if (opt != null && "--user".equals(opt)) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+
+ String restriction = getNextArg();
+ String arg = getNextArg();
+ boolean value;
+ if ("1".equals(arg)) {
+ value = true;
+ } else if ("0".equals(arg)) {
+ value = false;
+ } else {
+ getErrPrintWriter().println("Error: valid value not specified");
+ return 1;
+ }
+ IUserManager um = IUserManager.Stub.asInterface(
+ ServiceManager.getService(Context.USER_SERVICE));
+ um.setUserRestriction(restriction, value, userId);
+ return 0;
+ }
+
+ public int runGetMaxUsers() {
+ getOutPrintWriter().println("Maximum supported users: "
+ + UserManager.getMaxSupportedUsers());
+ return 0;
+ }
+
private static class InstallParams {
SessionParams sessionParams;
String installerPackageName;
@@ -1287,46 +1991,17 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
- private int runGetPrivappPermissions() {
- final String pkg = getNextArg();
- if (pkg == null) {
- System.err.println("Error: no package specified.");
- return 1;
- }
- ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
- getOutPrintWriter().println(privAppPermissions == null
- ? "{}" : privAppPermissions.toString());
- return 0;
- }
+ private int runSetInstaller() throws RemoteException {
+ final String targetPackage = getNextArg();
+ final String installerPackageName = getNextArg();
- private int runGetPrivappDenyPermissions() {
- final String pkg = getNextArg();
- if (pkg == null) {
- System.err.println("Error: no package specified.");
+ if (targetPackage == null || installerPackageName == null) {
+ getErrPrintWriter().println("Must provide both target and installer package names");
return 1;
}
- ArraySet<String> privAppDenyPermissions =
- SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
- getOutPrintWriter().println(privAppDenyPermissions == null
- ? "{}" : privAppDenyPermissions.toString());
- return 0;
- }
- private int runGetOemPermissions() {
- final String pkg = getNextArg();
- if (pkg == null) {
- System.err.println("Error: no package specified.");
- return 1;
- }
- final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
- .getOemPermissions(pkg);
- if (oemPermissions == null || oemPermissions.isEmpty()) {
- getOutPrintWriter().println("{}");
- } else {
- oemPermissions.forEach((permission, granted) ->
- getOutPrintWriter().println(permission + " granted:" + granted)
- );
- }
+ mInterface.setInstallerPackageName(targetPackage, installerPackageName);
+ getOutPrintWriter().println("Success");
return 0;
}
@@ -1367,6 +2042,16 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
+ private int runDump() {
+ String pkg = getNextArg();
+ if (pkg == null) {
+ getErrPrintWriter().println("Error: no package specified");
+ return 1;
+ }
+ ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
+ return 0;
+ }
+
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
@@ -1663,52 +2348,31 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" help");
pw.println(" Print this help text.");
pw.println("");
- pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
- pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
- pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
- pw.println(" Options:");
- pw.println(" -a: compile all packages");
- pw.println(" -c: clear profile data before compiling");
- pw.println(" -f: force compilation even if not needed");
- pw.println(" -m: select compilation mode");
- pw.println(" MODE is one of the dex2oat compiler filters:");
- pw.println(" assume-verified");
- pw.println(" extract");
- pw.println(" verify");
- pw.println(" quicken");
- pw.println(" space-profile");
- pw.println(" space");
- pw.println(" speed-profile");
- pw.println(" speed");
- pw.println(" everything");
- pw.println(" -r: select compilation reason");
- pw.println(" REASON is one of:");
- for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
- pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
- }
- pw.println(" --reset: restore package to its post-install state");
- pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
- pw.println(" --secondary-dex: compile app secondary dex files");
- pw.println(" --split SPLIT: compile only the given split name");
- pw.println(" bg-dexopt-job");
- pw.println(" Execute the background optimizations immediately.");
- pw.println(" Note that the command only runs the background optimizer logic. It may");
- pw.println(" overlap with the actual job but the job scheduler will not be able to");
- pw.println(" cancel it. It will also run even if the device is not in the idle");
- pw.println(" maintenance mode.");
+ pw.println(" path [--user USER_ID] PACKAGE");
+ pw.println(" Print the path to the .apk of the given PACKAGE.");
+ pw.println("");
+ pw.println(" dump PACKAGE");
+ pw.println(" Print various system state associated with the given PACKAGE.");
+ pw.println("");
pw.println(" list features");
pw.println(" Prints all features of the system.");
+ pw.println("");
+ pw.println(" has-feature FEATURE_NAME [version]");
+ pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
+ pw.println(" otherwise prints false and returns exit status 1");
+ pw.println("");
pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
pw.println(" Options:");
pw.println(" -f: dump the name of the .apk file containing the test package");
+ pw.println("");
pw.println(" list libraries");
pw.println(" Prints all system libraries.");
- pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] "
- + "[--uid UID] [--user USER_ID] [FILTER]");
+ pw.println("");
+ pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
+ pw.println(" [--uid UID] [--user USER_ID] [FILTER]");
pw.println(" Prints all packages; optionally only those whose name contains");
- pw.println(" the text in FILTER.");
- pw.println(" Options:");
+ pw.println(" the text in FILTER. Options are:");
pw.println(" -f: see their associated file");
pw.println(" -d: filter to only show disabled packages");
pw.println(" -e: filter to only show enabled packages");
@@ -1720,42 +2384,216 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" -u: also include uninstalled packages");
pw.println(" --uid UID: filter to only show packages with the given UID");
pw.println(" --user USER_ID: only list packages belonging to the given user");
- pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
- pw.println(" Reconciles the package secondary dex files with the generated oat files.");
+ pw.println("");
pw.println(" list permission-groups");
pw.println(" Prints all known permission groups.");
+ pw.println("");
pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
- pw.println(" Prints all known permissions; optionally only those in GROUP.");
- pw.println(" Options:");
+ pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
pw.println(" -g: organize by group");
pw.println(" -f: print all information");
pw.println(" -s: short summary");
pw.println(" -d: only list dangerous permissions");
pw.println(" -u: list only the permissions users will see");
- pw.println(" dump-profiles TARGET-PACKAGE");
- pw.println(" Dumps method/class profile files to");
- pw.println(" /data/misc/profman/TARGET-PACKAGE.txt");
+ pw.println("");
pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
- pw.println(" Prints the activity that resolves to the given Intent.");
+ pw.println(" Prints the activity that resolves to the given INTENT.");
+ pw.println("");
pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT");
- pw.println(" Prints all activities that can handle the given Intent.");
+ pw.println(" Prints all activities that can handle the given INTENT.");
+ pw.println("");
pw.println(" query-services [--brief] [--components] [--user USER_ID] INTENT");
- pw.println(" Prints all services that can handle the given Intent.");
+ pw.println(" Prints all services that can handle the given INTENT.");
+ pw.println("");
pw.println(" query-receivers [--brief] [--components] [--user USER_ID] INTENT");
- pw.println(" Prints all broadcast receivers that can handle the given Intent.");
+ pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
+ pw.println("");
+ pw.println(" install [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
+ pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
+ pw.println(" [--originating-uri URI] [---referrer URI]");
+ pw.println(" [--abi ABI_NAME] [--force-sdk]");
+ pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
+ pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [PATH|-]");
+ pw.println(" Install an application. Must provide the apk data to install, either as a");
+ pw.println(" file path or '-' to read from stdin. Options are:");
+ pw.println(" -l: forward lock application");
+ pw.println(" -r: allow replacement of existing application");
+ pw.println(" -t: allow test packages");
+ pw.println(" -i: specify package name of installer owning the app");
+ pw.println(" -s: install application on sdcard");
+ pw.println(" -f: install application on internal flash");
+ pw.println(" -d: allow version code downgrade (debuggable packages only)");
+ pw.println(" -p: partial application install (new split on top of existing pkg)");
+ pw.println(" -g: grant all runtime permissions");
+ pw.println(" -S: size in bytes of package, required for stdin");
+ pw.println(" --user: install under the given user.");
+ pw.println(" --dont-kill: installing a new feature split, don't kill running app");
+ pw.println(" --originating-uri: set URI where app was downloaded from");
+ pw.println(" --referrer: set URI that instigated the install of the app");
+ pw.println(" --pkg: specify expected package name of app being installed");
+ pw.println(" --abi: override the default ABI of the platform");
+ pw.println(" --instantapp: cause the app to be installed as an ephemeral install app");
+ pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
+ pw.println(" --install-location: force the install location:");
+ pw.println(" 0=auto, 1=internal only, 2=prefer external");
+ pw.println(" --force-uuid: force install on to disk volume with given UUID");
+ pw.println(" --force-sdk: allow install even when existing app targets platform");
+ pw.println(" codename but new one targets a final API level");
+ pw.println("");
+ pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
+ pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
+ pw.println(" [--originating-uri URI] [---referrer URI]");
+ pw.println(" [--abi ABI_NAME] [--force-sdk]");
+ pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
+ pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
+ pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
+ pw.println(" to push data into the session, and \"install-commit\" to finish.");
+ pw.println("");
+ pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
+ pw.println(" Write an apk into the given install session. If the path is '-', data");
+ pw.println(" will be read from stdin. Options are:");
+ pw.println(" -S: size in bytes of package, required for stdin");
+ pw.println("");
+ pw.println(" install-commit SESSION_ID");
+ pw.println(" Commit the given active install session, installing the app.");
+ pw.println("");
+ pw.println(" install-abandon SESSION_ID");
+ pw.println(" Delete the given active install session.");
+ pw.println("");
+ pw.println(" set-install-location LOCATION");
+ pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
+ pw.println(" using this can cause applications to break and other undersireable behavior.");
+ pw.println(" LOCATION is one of:");
+ pw.println(" 0 [auto]: Let system decide the best location");
+ pw.println(" 1 [internal]: Install on internal device storage");
+ pw.println(" 2 [external]: Install on external media");
+ pw.println("");
+ pw.println(" get-install-location");
+ pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
+ pw.println("");
+ pw.println(" move-package PACKAGE [internal|UUID]");
+ pw.println("");
+ pw.println(" move-primary-storage [internal|UUID]");
+ pw.println("");
+ pw.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]");
+ pw.println(" Remove the given package name from the system. May remove an entire app");
+ pw.println(" if no SPLIT name is specified, otherwise will remove only the split of the");
+ pw.println(" given app. Options are:");
+ pw.println(" -k: keep the data and cache directories around after package removal.");
+ pw.println(" --user: remove the app from the given user.");
+ pw.println(" --versionCode: only uninstall if the app has the given version code.");
+ pw.println("");
+ pw.println(" clear [--user USER_ID] PACKAGE");
+ pw.println(" Deletes all data associated with a package.");
+ pw.println("");
+ pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" These commands change the enabled state of a given package or");
+ pw.println(" component (written as \"package/class\").");
+ pw.println("");
+ pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
+ pw.println("");
pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
pw.println(" Suspends the specified package (as user).");
+ pw.println("");
pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
pw.println(" Unsuspends the specified package (as user).");
- pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
- pw.println(" set the default home activity (aka launcher).");
- pw.println(" has-feature FEATURE_NAME [version]");
- pw.println(" prints true and returns exit status 0 when system has a FEATURE_NAME,");
- pw.println(" otherwise prints false and returns exit status 1");
- pw.println(" get-privileged-permissions TARGET-PACKAGE");
- pw.println(" prints all privileged permissions for a package.");
+ pw.println("");
+ pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
+ pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
+ pw.println(" These commands either grant or revoke permissions to apps. The permissions");
+ pw.println(" must be declared as used in the app's manifest, be runtime permissions");
+ pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
+ pw.println("");
+ pw.println(" reset-permissions");
+ pw.println(" Revert all runtime permissions to their default state.");
+ pw.println("");
+ pw.println(" set-permission-enforced PERMISSION [true|false]");
+ pw.println("");
+ pw.println(" get-privapp-permissions TARGET-PACKAGE");
+ pw.println(" Prints all privileged permissions for a package.");
+ pw.println("");
+ pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
+ pw.println(" Prints all privileged permissions that are denied for a package.");
+ pw.println("");
pw.println(" get-oem-permissions TARGET-PACKAGE");
- pw.println(" prints all OEM permissions for a package.");
+ pw.println(" Prints all OEM permissions for a package.");
+ pw.println("");
+ pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
+ pw.println(" get-app-link [--user USER_ID] PACKAGE");
+ pw.println("");
+ pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
+ pw.println(" Trim cache files to reach the given free space.");
+ pw.println("");
+ pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
+ pw.println(" [--guest] USER_NAME");
+ pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
+ pw.println(" of the user.");
+ pw.println("");
+ pw.println(" remove-user USER_ID");
+ pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
+ pw.println(" associated with that user");
+ pw.println("");
+ pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
+ pw.println("");
+ pw.println(" get-max-users");
+ pw.println("");
+ pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
+ pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
+ pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
+ pw.println(" -a: compile all packages");
+ pw.println(" -c: clear profile data before compiling");
+ pw.println(" -f: force compilation even if not needed");
+ pw.println(" -m: select compilation mode");
+ pw.println(" MODE is one of the dex2oat compiler filters:");
+ pw.println(" assume-verified");
+ pw.println(" extract");
+ pw.println(" verify");
+ pw.println(" quicken");
+ pw.println(" space-profile");
+ pw.println(" space");
+ pw.println(" speed-profile");
+ pw.println(" speed");
+ pw.println(" everything");
+ pw.println(" -r: select compilation reason");
+ pw.println(" REASON is one of:");
+ for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
+ pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
+ }
+ pw.println(" --reset: restore package to its post-install state");
+ pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
+ pw.println(" --secondary-dex: compile app secondary dex files");
+ pw.println(" --split SPLIT: compile only the given split name");
+ pw.println("");
+ pw.println(" force-dex-opt PACKAGE");
+ pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
+ pw.println("");
+ pw.println(" bg-dexopt-job");
+ pw.println(" Execute the background optimizations immediately.");
+ pw.println(" Note that the command only runs the background optimizer logic. It may");
+ pw.println(" overlap with the actual job but the job scheduler will not be able to");
+ pw.println(" cancel it. It will also run even if the device is not in the idle");
+ pw.println(" maintenance mode.");
+ pw.println("");
+ pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
+ pw.println(" Reconciles the package secondary dex files with the generated oat files.");
+ pw.println("");
+ pw.println(" dump-profiles TARGET-PACKAGE");
+ pw.println(" Dumps method/class profile files to");
+ pw.println(" /data/misc/profman/TARGET-PACKAGE.txt");
+ pw.println("");
+ pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
+ pw.println(" Set the default home activity (aka launcher).");
+ pw.println("");
+ pw.println(" set-installer PACKAGE INSTALLER");
+ pw.println(" Set installer package name");
+ pw.println("");
+ pw.println(" get-instantapp-resolver");
+ pw.println(" Return the name of the component that is the current instant app installer.");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
diff --git a/com/android/server/pm/PackageSetting.java b/com/android/server/pm/PackageSetting.java
index 83cb2db2..3b414e9a 100644
--- a/com/android/server/pm/PackageSetting.java
+++ b/com/android/server/pm/PackageSetting.java
@@ -86,6 +86,10 @@ public final class PackageSetting extends PackageSettingBase {
return sharedUserId;
}
+ public SharedUserSetting getSharedUser() {
+ return sharedUser;
+ }
+
@Override
public String toString() {
return "PackageSetting{"
@@ -120,6 +124,14 @@ public final class PackageSetting extends PackageSettingBase {
return appId;
}
+ public void setInstallPermissionsFixed(boolean fixed) {
+ installPermissionsFixed = fixed;
+ }
+
+ public boolean areInstallPermissionsFixed() {
+ return installPermissionsFixed;
+ }
+
public boolean isPrivileged() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
}
@@ -136,6 +148,10 @@ public final class PackageSetting extends PackageSettingBase {
return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
+ public boolean isUpdatedSystem() {
+ return (pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
+ }
+
@Override
public boolean isSharedUser() {
return sharedUser != null;
diff --git a/com/android/server/pm/PackageSettingBase.java b/com/android/server/pm/PackageSettingBase.java
index e19e83fc..a8387684 100644
--- a/com/android/server/pm/PackageSettingBase.java
+++ b/com/android/server/pm/PackageSettingBase.java
@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
+import android.content.pm.Signature;
import android.service.pm.PackageProto;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -57,7 +58,7 @@ public abstract class PackageSettingBase extends SettingBase {
static final int PKG_INSTALL_COMPLETE = 1;
static final int PKG_INSTALL_INCOMPLETE = 0;
- final String name;
+ public final String name;
final String realName;
String parentPackageName;
@@ -231,6 +232,11 @@ public abstract class PackageSettingBase extends SettingBase {
public boolean isSharedUser() {
return false;
}
+
+ public Signature[] getSignatures() {
+ return signatures.mSignatures;
+ }
+
/**
* Makes a shallow copy of the given package settings.
*
diff --git a/com/android/server/pm/Settings.java b/com/android/server/pm/Settings.java
index 191b43a6..7077fd16 100644
--- a/com/android/server/pm/Settings.java
+++ b/com/android/server/pm/Settings.java
@@ -544,7 +544,7 @@ public final class Settings {
}
final PackageSetting dp = mDisabledSysPackages.get(name);
// always make sure the system package code and resource paths dont change
- if (dp == null && p.pkg != null && p.pkg.isSystemApp() && !p.pkg.isUpdatedSystemApp()) {
+ if (dp == null && p.pkg != null && p.pkg.isSystem() && !p.pkg.isUpdatedSystemApp()) {
if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
diff --git a/com/android/server/pm/UserDataPreparer.java b/com/android/server/pm/UserDataPreparer.java
index b8b00af4..bfe09b8e 100644
--- a/com/android/server/pm/UserDataPreparer.java
+++ b/com/android/server/pm/UserDataPreparer.java
@@ -132,11 +132,9 @@ class UserDataPreparer {
if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
FileUtils.deleteContentsAndDir(getUserSystemDirectory(userId));
FileUtils.deleteContentsAndDir(getDataSystemDeDirectory(userId));
- FileUtils.deleteContentsAndDir(getDataMiscDeDirectory(userId));
}
if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
FileUtils.deleteContentsAndDir(getDataSystemCeDirectory(userId));
- FileUtils.deleteContentsAndDir(getDataMiscCeDirectory(userId));
}
}
diff --git a/com/android/server/pm/UserRestrictionsUtils.java b/com/android/server/pm/UserRestrictionsUtils.java
index c18a71d3..c86122f2 100644
--- a/com/android/server/pm/UserRestrictionsUtils.java
+++ b/com/android/server/pm/UserRestrictionsUtils.java
@@ -80,6 +80,7 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
UserManager.DISALLOW_DEBUGGING_FEATURES,
UserManager.DISALLOW_CONFIG_VPN,
+ UserManager.DISALLOW_CONFIG_DATE_TIME,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
@@ -157,6 +158,7 @@ public class UserRestrictionsUtils {
private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_BLUETOOTH_SHARING,
+ UserManager.DISALLOW_CONFIG_DATE_TIME,
UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
diff --git a/com/android/server/pm/dex/DexoptOptions.java b/com/android/server/pm/dex/DexoptOptions.java
index 4fa47b5d..0966770d 100644
--- a/com/android/server/pm/dex/DexoptOptions.java
+++ b/com/android/server/pm/dex/DexoptOptions.java
@@ -56,6 +56,9 @@ public final class DexoptOptions {
// actually shared at runtime.
public static final int DEXOPT_AS_SHARED_LIBRARY = 1 << 6;
+ // When set, indicates that dexopt is invoked from the background service.
+ public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
+
// The name of package to optimize.
private final String mPackageName;
@@ -86,7 +89,8 @@ public final class DexoptOptions {
DEXOPT_ONLY_SECONDARY_DEX |
DEXOPT_ONLY_SHARED_DEX |
DEXOPT_DOWNGRADE |
- DEXOPT_AS_SHARED_LIBRARY;
+ DEXOPT_AS_SHARED_LIBRARY |
+ DEXOPT_IDLE_BACKGROUND_JOB;
if ((flags & (~validityMask)) != 0) {
throw new IllegalArgumentException("Invalid flags : " + Integer.toHexString(flags));
}
@@ -133,6 +137,10 @@ public final class DexoptOptions {
return (mFlags & DEXOPT_AS_SHARED_LIBRARY) != 0;
}
+ public boolean isDexoptIdleBackgroundJob() {
+ return (mFlags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
+ }
+
public String getSplitName() {
return mSplitName;
}
diff --git a/com/android/server/pm/permission/BasePermission.java b/com/android/server/pm/permission/BasePermission.java
index 71d3202d..8c86db64 100644
--- a/com/android/server/pm/permission/BasePermission.java
+++ b/com/android/server/pm/permission/BasePermission.java
@@ -32,6 +32,7 @@ import android.annotation.Nullable;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Permission;
import android.content.pm.PermissionInfo;
+import android.content.pm.Signature;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
@@ -129,6 +130,9 @@ public final class BasePermission {
public PackageSettingBase getSourcePackageSetting() {
return sourcePackageSetting;
}
+ public Signature[] getSourceSignatures() {
+ return sourcePackageSetting.getSignatures();
+ }
public int getType() {
return type;
}
@@ -277,8 +281,8 @@ public final class BasePermission {
// Allow system apps to redefine non-system permissions
if (bp != null && !Objects.equals(bp.sourcePackageName, p.info.packageName)) {
final boolean currentOwnerIsSystem = (bp.perm != null
- && bp.perm.owner.isSystemApp());
- if (p.owner.isSystemApp()) {
+ && bp.perm.owner.isSystem());
+ if (p.owner.isSystem()) {
if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
// It's a built-in permission and no owner, take ownership now
bp.sourcePackageSetting = pkgSetting;
diff --git a/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 161efd38..533b2619 100644
--- a/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -985,7 +985,7 @@ public final class DefaultPermissionGrantPolicy {
private PackageParser.Package getSystemPackage(String packageName) {
PackageParser.Package pkg = getPackage(packageName);
- if (pkg != null && pkg.isSystemApp()) {
+ if (pkg != null && pkg.isSystem()) {
return !isSysComponentOrPersistentPlatformSignedPrivApp(pkg) ? pkg : null;
}
return null;
@@ -1094,7 +1094,7 @@ public final class DefaultPermissionGrantPolicy {
if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
return true;
}
- if (!pkg.isPrivilegedApp()) {
+ if (!pkg.isPrivileged()) {
return false;
}
final PackageParser.Package disabledPkg =
diff --git a/com/android/server/pm/permission/PermissionManagerInternal.java b/com/android/server/pm/permission/PermissionManagerInternal.java
index 8aac52ae..60c118b5 100644
--- a/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -19,6 +19,7 @@ package com.android.server.pm.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageParser;
+import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.PermissionInfoFlags;
@@ -57,7 +58,7 @@ public abstract class PermissionManagerInternal {
}
public void onInstallPermissionRevoked() {
}
- public void onPermissionUpdated(int userId) {
+ public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
}
public void onPermissionRemoved() {
}
@@ -65,6 +66,10 @@ public abstract class PermissionManagerInternal {
}
}
+ public abstract void systemReady();
+
+ public abstract boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId);
+
public abstract void grantRuntimePermission(
@NonNull String permName, @NonNull String packageName, boolean overridePolicy,
int callingUid, int userId, @Nullable PermissionCallback callback);
@@ -78,9 +83,12 @@ public abstract class PermissionManagerInternal {
public abstract void revokeRuntimePermission(@NonNull String permName,
@NonNull String packageName, boolean overridePolicy, int callingUid, int userId,
@Nullable PermissionCallback callback);
- public abstract int[] revokeUnusedSharedUserPermissions(@NonNull SharedUserSetting suSetting,
- @NonNull int[] allUserIds);
+ public abstract void updatePermissions(@Nullable String packageName,
+ @Nullable PackageParser.Package pkg, boolean replaceGrant,
+ @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
+ public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
+ @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
/**
* Add all permissions in the given package.
@@ -89,22 +97,28 @@ public abstract class PermissionManagerInternal {
* the permission settings.
*/
public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
+ public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty);
public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
int callingUid, @Nullable PermissionCallback callback);
public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
@Nullable PermissionCallback callback);
- public abstract int updatePermissions(@Nullable String changingPkg,
- @Nullable PackageParser.Package pkgInfo, int flags);
- public abstract int updatePermissionTrees(@Nullable String changingPkg,
- @Nullable PackageParser.Package pkgInfo, int flags);
-
public abstract @Nullable String[] getAppOpPermissionPackages(@NonNull String permName);
public abstract int getPermissionFlags(@NonNull String permName,
@NonNull String packageName, int callingUid, int userId);
/**
+ * Retrieve all of the information we know about a particular group of permissions.
+ */
+ public abstract @Nullable PermissionGroupInfo getPermissionGroupInfo(
+ @NonNull String groupName, int flags, int callingUid);
+ /**
+ * Retrieve all of the known permission groups in the system.
+ */
+ public abstract @Nullable List<PermissionGroupInfo> getAllPermissionGroups(int flags,
+ int callingUid);
+ /**
* Retrieve all of the information we know about a particular permission.
*/
public abstract @Nullable PermissionInfo getPermissionInfo(@NonNull String permName,
@@ -132,6 +146,7 @@ public abstract class PermissionManagerInternal {
public abstract int checkPermission(@NonNull String permName, @NonNull String packageName,
int callingUid, int userId);
+ public abstract int checkUidPermission(String permName, int uid, int callingUid);
/**
* Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS
@@ -147,8 +162,5 @@ public abstract class PermissionManagerInternal {
public abstract @NonNull DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy();
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
- public abstract Iterator<BasePermission> getPermissionIteratorTEMP();
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
- public abstract void putPermissionTEMP(@NonNull String permName,
- @NonNull BasePermission permission);
} \ No newline at end of file
diff --git a/com/android/server/pm/permission/PermissionManagerService.java b/com/android/server/pm/permission/PermissionManagerService.java
index d2d857ca..76805ce3 100644
--- a/com/android/server/pm/permission/PermissionManagerService.java
+++ b/com/android/server/pm/permission/PermissionManagerService.java
@@ -18,6 +18,13 @@ package com.android.server.pm.permission;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
+import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
+import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
+import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import android.Manifest;
import android.annotation.NonNull;
@@ -27,7 +34,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
-import android.content.pm.ParceledListSlice;
+import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.PackageParser.Package;
import android.os.Binder;
@@ -35,18 +42,24 @@ import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
+import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.ArrayUtils;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -58,6 +71,7 @@ import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.ProcessLoggingHandler;
import com.android.server.pm.SharedUserSetting;
+import com.android.server.pm.UserManagerService;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState.PermissionState;
@@ -69,6 +83,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -107,8 +122,19 @@ public class PermissionManagerService {
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.ANSWER_PHONE_CALLS);
- /** Cap the size of permission trees that 3rd party apps can define */
- private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
+ /** Permission grant: not grant the permission. */
+ private static final int GRANT_DENIED = 1;
+ /** Permission grant: grant the permission as an install permission. */
+ private static final int GRANT_INSTALL = 2;
+ /** Permission grant: grant the permission as a runtime one. */
+ private static final int GRANT_RUNTIME = 3;
+ /** Permission grant: grant as runtime a permission that was granted as an install time one. */
+ private static final int GRANT_UPGRADE = 4;
+
+ /** Cap the size of permission trees that 3rd party apps can define; in characters of text */
+ private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;
+ /** Empty array to avoid allocations */
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
/** Lock to protect internal data access */
private final Object mLock;
@@ -122,13 +148,29 @@ public class PermissionManagerService {
/** Default permission policy to provide proper behaviour out-of-the-box */
private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
- /** Internal storage for permissions and related settings */
- private final PermissionSettings mSettings;
+ /**
+ * Built-in permissions. Read from system configuration files. Mapping is from
+ * UID to permission name.
+ */
+ private final SparseArray<ArraySet<String>> mSystemPermissions;
+
+ /** Built-in group IDs given to all packages. Read from system configuration files. */
+ private final int[] mGlobalGids;
private final HandlerThread mHandlerThread;
private final Handler mHandler;
private final Context mContext;
+ /** Internal storage for permissions and related settings */
+ @GuardedBy("mLock")
+ private final PermissionSettings mSettings;
+
+ @GuardedBy("mLock")
+ private ArraySet<String> mPrivappPermissionsViolations;
+
+ @GuardedBy("mLock")
+ private boolean mSystemReady;
+
PermissionManagerService(Context context,
@Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
@NonNull Object externalLock) {
@@ -146,6 +188,9 @@ public class PermissionManagerService {
mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
context, mHandlerThread.getLooper(), defaultGrantCallback, this);
+ SystemConfig systemConfig = SystemConfig.getInstance();
+ mSystemPermissions = systemConfig.getSystemPermissions();
+ mGlobalGids = systemConfig.getGlobalGids();
// propagate permission configuration
final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
@@ -230,14 +275,105 @@ public class PermissionManagerService {
return PackageManager.PERMISSION_DENIED;
}
- private PermissionInfo getPermissionInfo(String name, String packageName, int flags,
+ private int checkUidPermission(String permName, int uid, int callingUid) {
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final boolean isCallerInstantApp =
+ mPackageManagerInt.getInstantAppPackageName(callingUid) != null;
+ final boolean isUidInstantApp =
+ mPackageManagerInt.getInstantAppPackageName(uid) != null;
+ final int userId = UserHandle.getUserId(uid);
+ if (!mUserManagerInt.exists(userId)) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+ if (packages != null && packages.length > 0) {
+ PackageParser.Package pkg = null;
+ for (String packageName : packages) {
+ pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg != null) {
+ break;
+ }
+ }
+ if (pkg == null) {
+Slog.e(TAG, "TODD: No package not found; UID: " + uid);
+Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));
+ return PackageManager.PERMISSION_DENIED;
+ }
+ if (pkg.mSharedUserId != null) {
+ if (isCallerInstantApp) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ } else {
+ if (mPackageManagerInt.filterAppAccess(pkg, callingUid, callingUserId)) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+ final PermissionsState permissionsState =
+ ((PackageSetting) pkg.mExtras).getPermissionsState();
+ if (permissionsState.hasPermission(permName, userId)) {
+ if (isUidInstantApp) {
+ if (mSettings.isPermissionInstant(permName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ } else {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ }
+ // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
+ if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
+ .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ } else {
+ ArraySet<String> perms = mSystemPermissions.get(uid);
+ if (perms != null) {
+ if (perms.contains(permName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && perms
+ .contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ }
+ }
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ private PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
+ int callingUid) {
+ if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
+ return null;
+ }
+ synchronized (mLock) {
+ return PackageParser.generatePermissionGroupInfo(
+ mSettings.mPermissionGroups.get(groupName), flags);
+ }
+ }
+
+ private List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
+ if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
+ return null;
+ }
+ synchronized (mLock) {
+ final int N = mSettings.mPermissionGroups.size();
+ final ArrayList<PermissionGroupInfo> out
+ = new ArrayList<PermissionGroupInfo>(N);
+ for (PackageParser.PermissionGroup pg : mSettings.mPermissionGroups.values()) {
+ out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
+ }
+ return out;
+ }
+ }
+
+ private PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
int callingUid) {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
return null;
}
// reader
synchronized (mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(name);
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
if (bp == null) {
return null;
}
@@ -252,14 +388,10 @@ public class PermissionManagerService {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
return null;
}
- // reader
synchronized (mLock) {
- // TODO Uncomment when mPermissionGroups moves to this class
-// if (groupName != null && !mPermissionGroups.containsKey(groupName)) {
-// // This is thrown as NameNotFoundException
-// return null;
-// }
-
+ if (groupName != null && !mSettings.mPermissionGroups.containsKey(groupName)) {
+ return null;
+ }
final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
for (BasePermission bp : mSettings.mPermissions.values()) {
final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
@@ -314,21 +446,21 @@ public class PermissionManagerService {
// Assume by default that we did not install this permission into the system.
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
- // Now that permission groups have a special meaning, we ignore permission
- // groups for legacy apps to prevent unexpected behavior. In particular,
- // permissions for one app being granted to someone just because they happen
- // to be in a group defined by another app (before this had no implications).
- if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
- p.group = mPackageManagerInt.getPermissionGroupTEMP(p.info.group);
- // Warn for a permission in an unknown group.
- if (PackageManagerService.DEBUG_PERMISSIONS
- && p.info.group != null && p.group == null) {
- Slog.i(TAG, "Permission " + p.info.name + " from package "
- + p.info.packageName + " in an unknown group " + p.info.group);
+ synchronized (PermissionManagerService.this.mLock) {
+ // Now that permission groups have a special meaning, we ignore permission
+ // groups for legacy apps to prevent unexpected behavior. In particular,
+ // permissions for one app being granted to someone just because they happen
+ // to be in a group defined by another app (before this had no implications).
+ if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ p.group = mSettings.mPermissionGroups.get(p.info.group);
+ // Warn for a permission in an unknown group.
+ if (DEBUG_PERMISSIONS
+ && p.info.group != null && p.group == null) {
+ Slog.i(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName + " in an unknown group " + p.info.group);
+ }
}
- }
- synchronized (PermissionManagerService.this.mLock) {
if (p.tree) {
final BasePermission bp = BasePermission.createOrUpdate(
mSettings.getPermissionTreeLocked(p.info.name), p, pkg,
@@ -344,6 +476,48 @@ public class PermissionManagerService {
}
}
+ private void addAllPermissionGroups(PackageParser.Package pkg, boolean chatty) {
+ final int N = pkg.permissionGroups.size();
+ StringBuilder r = null;
+ for (int i=0; i<N; i++) {
+ final PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
+ final PackageParser.PermissionGroup cur = mSettings.mPermissionGroups.get(pg.info.name);
+ final String curPackageName = (cur == null) ? null : cur.info.packageName;
+ final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
+ if (cur == null || isPackageUpdate) {
+ mSettings.mPermissionGroups.put(pg.info.name, pg);
+ if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ if (isPackageUpdate) {
+ r.append("UPD:");
+ }
+ r.append(pg.info.name);
+ }
+ } else {
+ Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ + pg.info.packageName + " ignored: original from "
+ + cur.info.packageName);
+ if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append("DUP:");
+ r.append(pg.info.name);
+ }
+ }
+ }
+ if (r != null && DEBUG_PACKAGE_SCANNING) {
+ Log.d(TAG, " Permission Groups: " + r);
+ }
+
+ }
+
private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
synchronized (mLock) {
int N = pkg.permissions.size();
@@ -356,7 +530,7 @@ public class PermissionManagerService {
}
if (bp != null && bp.isPermission(p)) {
bp.setPermission(null);
- if (PackageManagerService.DEBUG_REMOVE && chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -374,7 +548,7 @@ public class PermissionManagerService {
}
}
if (r != null) {
- if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
}
N = pkg.requestedPermissions.size();
@@ -392,7 +566,7 @@ public class PermissionManagerService {
}
}
if (r != null) {
- if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
}
}
}
@@ -455,6 +629,581 @@ public class PermissionManagerService {
}
}
+ private void grantPermissions(PackageParser.Package pkg, boolean replace,
+ String packageOfInterest, PermissionCallback callback) {
+ // IMPORTANT: There are two types of permissions: install and runtime.
+ // Install time permissions are granted when the app is installed to
+ // all device users and users added in the future. Runtime permissions
+ // are granted at runtime explicitly to specific users. Normal and signature
+ // protected permissions are install time permissions. Dangerous permissions
+ // are install permissions if the app's target SDK is Lollipop MR1 or older,
+ // otherwise they are runtime permissions. This function does not manage
+ // runtime permissions except for the case an app targeting Lollipop MR1
+ // being upgraded to target a newer SDK, in which case dangerous permissions
+ // are transformed from install time to runtime ones.
+
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null) {
+ return;
+ }
+ final boolean isLegacySystemApp = mPackageManagerInt.isLegacySystemApp(pkg);
+
+ final PermissionsState permissionsState = ps.getPermissionsState();
+ PermissionsState origPermissions = permissionsState;
+
+ final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+
+ boolean runtimePermissionsRevoked = false;
+ int[] updatedUserIds = EMPTY_INT_ARRAY;
+
+ boolean changedInstallPermission = false;
+
+ if (replace) {
+ ps.setInstallPermissionsFixed(false);
+ if (!ps.isSharedUser()) {
+ origPermissions = new PermissionsState(permissionsState);
+ permissionsState.reset();
+ } else {
+ // We need to know only about runtime permission changes since the
+ // calling code always writes the install permissions state but
+ // the runtime ones are written only if changed. The only cases of
+ // changed runtime permissions here are promotion of an install to
+ // runtime and revocation of a runtime from a shared user.
+ synchronized (mLock) {
+ updatedUserIds = revokeUnusedSharedUserPermissionsLocked(
+ ps.getSharedUser(), UserManagerService.getInstance().getUserIds());
+ if (!ArrayUtils.isEmpty(updatedUserIds)) {
+ runtimePermissionsRevoked = true;
+ }
+ }
+ }
+ }
+
+ permissionsState.setGlobalGids(mGlobalGids);
+
+ synchronized (mLock) {
+ final int N = pkg.requestedPermissions.size();
+ for (int i = 0; i < N; i++) {
+ final String permName = pkg.requestedPermissions.get(i);
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
+ final boolean appSupportsRuntimePermissions =
+ pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;
+
+ if (DEBUG_INSTALL) {
+ Log.i(TAG, "Package " + pkg.packageName + " checking " + permName + ": " + bp);
+ }
+
+ if (bp == null || bp.getSourcePackageSetting() == null) {
+ if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Unknown permission " + permName
+ + " in package " + pkg.packageName);
+ }
+ }
+ continue;
+ }
+
+ // Limit ephemeral apps to ephemeral allowed permissions.
+ if (pkg.applicationInfo.isInstantApp() && !bp.isInstant()) {
+ if (DEBUG_PERMISSIONS) {
+ Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
+ + " for package " + pkg.packageName);
+ }
+ continue;
+ }
+
+ if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
+ if (DEBUG_PERMISSIONS) {
+ Log.i(TAG, "Denying runtime-only permission " + bp.getName()
+ + " for package " + pkg.packageName);
+ }
+ continue;
+ }
+
+ final String perm = bp.getName();
+ boolean allowedSig = false;
+ int grant = GRANT_DENIED;
+
+ // Keep track of app op permissions.
+ if (bp.isAppOp()) {
+ mSettings.addAppOpPackage(perm, pkg.packageName);
+ }
+
+ if (bp.isNormal()) {
+ // For all apps normal permissions are install time ones.
+ grant = GRANT_INSTALL;
+ } else if (bp.isRuntime()) {
+ // If a permission review is required for legacy apps we represent
+ // their permissions as always granted runtime ones since we need
+ // to keep the review required permission flag per user while an
+ // install permission's state is shared across all users.
+ if (!appSupportsRuntimePermissions && !mSettings.mPermissionReviewRequired) {
+ // For legacy apps dangerous permissions are install time ones.
+ grant = GRANT_INSTALL;
+ } else if (origPermissions.hasInstallPermission(bp.getName())) {
+ // For legacy apps that became modern, install becomes runtime.
+ grant = GRANT_UPGRADE;
+ } else if (isLegacySystemApp) {
+ // For legacy system apps, install becomes runtime.
+ // We cannot check hasInstallPermission() for system apps since those
+ // permissions were granted implicitly and not persisted pre-M.
+ grant = GRANT_UPGRADE;
+ } else {
+ // For modern apps keep runtime permissions unchanged.
+ grant = GRANT_RUNTIME;
+ }
+ } else if (bp.isSignature()) {
+ // For all apps signature permissions are install time ones.
+ allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
+ if (allowedSig) {
+ grant = GRANT_INSTALL;
+ }
+ }
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Granting permission " + perm + " to package " + pkg.packageName);
+ }
+
+ if (grant != GRANT_DENIED) {
+ if (!ps.isSystem() && ps.areInstallPermissionsFixed()) {
+ // If this is an existing, non-system package, then
+ // we can't add any new permissions to it.
+ if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
+ // Except... if this is a permission that was added
+ // to the platform (note: need to only do this when
+ // updating the platform).
+ if (!isNewPlatformPermissionForPackage(perm, pkg)) {
+ grant = GRANT_DENIED;
+ }
+ }
+ }
+
+ switch (grant) {
+ case GRANT_INSTALL: {
+ // Revoke this as runtime permission to handle the case of
+ // a runtime permission being downgraded to an install one.
+ // Also in permission review mode we keep dangerous permissions
+ // for legacy apps
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ if (origPermissions.getRuntimePermissionState(
+ perm, userId) != null) {
+ // Revoke the runtime permission and clear the flags.
+ origPermissions.revokeRuntimePermission(bp, userId);
+ origPermissions.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ // If we revoked a permission permission, we have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ }
+ // Grant an install permission.
+ if (permissionsState.grantInstallPermission(bp) !=
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ changedInstallPermission = true;
+ }
+ } break;
+
+ case GRANT_RUNTIME: {
+ // Grant previously granted runtime permissions.
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ final PermissionState permissionState = origPermissions
+ .getRuntimePermissionState(perm, userId);
+ int flags = permissionState != null
+ ? permissionState.getFlags() : 0;
+ if (origPermissions.hasRuntimePermission(perm, userId)) {
+ // Don't propagate the permission in a permission review
+ // mode if the former was revoked, i.e. marked to not
+ // propagate on upgrade. Note that in a permission review
+ // mode install permissions are represented as constantly
+ // granted runtime ones since we need to keep a per user
+ // state associated with the permission. Also the revoke
+ // on upgrade flag is no longer applicable and is reset.
+ final boolean revokeOnUpgrade = (flags & PackageManager
+ .FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0;
+ if (revokeOnUpgrade) {
+ flags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ // Since we changed the flags, we have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ if (!mSettings.mPermissionReviewRequired || !revokeOnUpgrade) {
+ if (permissionsState.grantRuntimePermission(bp, userId) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // If we cannot put the permission as it was,
+ // we have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ }
+
+ // If the app supports runtime permissions no need for a review.
+ if (mSettings.mPermissionReviewRequired
+ && appSupportsRuntimePermissions
+ && (flags & PackageManager
+ .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ // Since we changed the flags, we have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ } else if (mSettings.mPermissionReviewRequired
+ && !appSupportsRuntimePermissions) {
+ // For legacy apps that need a permission review, every new
+ // runtime permission is granted but it is pending a review.
+ // We also need to review only platform defined runtime
+ // permissions as these are the only ones the platform knows
+ // how to disable the API to simulate revocation as legacy
+ // apps don't expect to run with revoked permissions.
+ if (PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName())) {
+ if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ // We changed the flags, hence have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ }
+ if (permissionsState.grantRuntimePermission(bp, userId)
+ != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // We changed the permission, hence have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ }
+ // Propagate the permission flags.
+ permissionsState.updatePermissionFlags(bp, userId, flags, flags);
+ }
+ } break;
+
+ case GRANT_UPGRADE: {
+ // Grant runtime permissions for a previously held install permission.
+ final PermissionState permissionState = origPermissions
+ .getInstallPermissionState(perm);
+ final int flags =
+ (permissionState != null) ? permissionState.getFlags() : 0;
+
+ if (origPermissions.revokeInstallPermission(bp)
+ != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // We will be transferring the permission flags, so clear them.
+ origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ changedInstallPermission = true;
+ }
+
+ // If the permission is not to be promoted to runtime we ignore it and
+ // also its other flags as they are not applicable to install permissions.
+ if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
+ for (int userId : currentUserIds) {
+ if (permissionsState.grantRuntimePermission(bp, userId) !=
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // Transfer the permission flags.
+ permissionsState.updatePermissionFlags(bp, userId,
+ flags, flags);
+ // If we granted the permission, we have to write.
+ updatedUserIds = ArrayUtils.appendInt(
+ updatedUserIds, userId);
+ }
+ }
+ }
+ } break;
+
+ default: {
+ if (packageOfInterest == null
+ || packageOfInterest.equals(pkg.packageName)) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Not granting permission " + perm
+ + " to package " + pkg.packageName
+ + " because it was previously installed without");
+ }
+ }
+ } break;
+ }
+ } else {
+ if (permissionsState.revokeInstallPermission(bp) !=
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // Also drop the permission flags.
+ permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ changedInstallPermission = true;
+ Slog.i(TAG, "Un-granting permission " + perm
+ + " from package " + pkg.packageName
+ + " (protectionLevel=" + bp.getProtectionLevel()
+ + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ + ")");
+ } else if (bp.isAppOp()) {
+ // Don't print warning for app op permissions, since it is fine for them
+ // not to be granted, there is a UI for the user to decide.
+ if (DEBUG_PERMISSIONS
+ && (packageOfInterest == null
+ || packageOfInterest.equals(pkg.packageName))) {
+ Slog.i(TAG, "Not granting permission " + perm
+ + " to package " + pkg.packageName
+ + " (protectionLevel=" + bp.getProtectionLevel()
+ + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ + ")");
+ }
+ }
+ }
+ }
+
+ if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
+ !ps.isSystem() || ps.isUpdatedSystem()) {
+ // This is the first that we have heard about this package, so the
+ // permissions we have now selected are fixed until explicitly
+ // changed.
+ ps.setInstallPermissionsFixed(true);
+ }
+ }
+
+ // Persist the runtime permissions state for users with changes. If permissions
+ // were revoked because no app in the shared user declares them we have to
+ // write synchronously to avoid losing runtime permissions state.
+ if (callback != null) {
+ callback.onPermissionUpdated(updatedUserIds, runtimePermissionsRevoked);
+ }
+ }
+
+ private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
+ boolean allowed = false;
+ final int NP = PackageParser.NEW_PERMISSIONS.length;
+ for (int ip=0; ip<NP; ip++) {
+ final PackageParser.NewPermissionInfo npi
+ = PackageParser.NEW_PERMISSIONS[ip];
+ if (npi.name.equals(perm)
+ && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
+ allowed = true;
+ Log.i(TAG, "Auto-granting " + perm + " to old pkg "
+ + pkg.packageName);
+ break;
+ }
+ }
+ return allowed;
+ }
+
+ /**
+ * Determines whether a package is whitelisted for a particular privapp permission.
+ *
+ * <p>Does NOT check whether the package is a privapp, just whether it's whitelisted.
+ *
+ * <p>This handles parent/child apps.
+ */
+ private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
+ ArraySet<String> 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.
+ return whitelisted ||
+ pkg.parentPackage != null && hasPrivappWhitelistEntry(perm, pkg.parentPackage);
+ }
+
+ private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
+ BasePermission bp, PermissionsState origPermissions) {
+ boolean oemPermission = bp.isOEM();
+ boolean privilegedPermission = bp.isPrivileged();
+ boolean privappPermissionsDisable =
+ RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
+ boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
+ boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.packageName);
+ if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
+ && !platformPackage && platformPermission) {
+ if (!hasPrivappWhitelistEntry(perm, pkg)) {
+ // 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 = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.packageName);
+ final boolean permissionViolation =
+ deniedPermissions == null || !deniedPermissions.contains(perm);
+ if (permissionViolation) {
+ Slog.w(TAG, "Privileged permission " + perm + " for package "
+ + pkg.packageName + " - not in privapp-permissions whitelist");
+
+ if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+ if (mPrivappPermissionsViolations == null) {
+ mPrivappPermissionsViolations = new ArraySet<>();
+ }
+ mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm);
+ }
+ } else {
+ return false;
+ }
+ }
+ if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+ return false;
+ }
+ }
+ }
+ final String systemPackageName = mPackageManagerInt.getKnownPackageName(
+ PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
+ final PackageParser.Package systemPackage =
+ mPackageManagerInt.getPackage(systemPackageName);
+ boolean allowed = (PackageManagerService.compareSignatures(
+ bp.getSourceSignatures(), pkg.mSignatures)
+ == PackageManager.SIGNATURE_MATCH)
+ || (PackageManagerService.compareSignatures(
+ systemPackage.mSignatures, pkg.mSignatures)
+ == PackageManager.SIGNATURE_MATCH);
+ if (!allowed && (privilegedPermission || oemPermission)) {
+ if (pkg.isSystem()) {
+ // For updated system applications, a privileged/oem permission
+ // is granted only if it had been defined by the original application.
+ if (pkg.isUpdatedSystemApp()) {
+ final PackageParser.Package disabledPkg =
+ mPackageManagerInt.getDisabledPackage(pkg.packageName);
+ final PackageSetting disabledPs =
+ (disabledPkg != null) ? (PackageSetting) disabledPkg.mExtras : null;
+ if (disabledPs != null
+ && disabledPs.getPermissionsState().hasInstallPermission(perm)) {
+ // If the original was granted this permission, we take
+ // that grant decision as read and propagate it to the
+ // update.
+ if ((privilegedPermission && disabledPs.isPrivileged())
+ || (oemPermission && disabledPs.isOem()
+ && canGrantOemPermission(disabledPs, perm))) {
+ allowed = true;
+ }
+ } else {
+ // The system apk may have been updated with an older
+ // version of the one on the data partition, but which
+ // granted a new system permission that it didn't have
+ // before. In this case we do want to allow the app to
+ // now get the new permission if the ancestral apk is
+ // privileged to get it.
+ if (disabledPs != null && disabledPkg != null
+ && isPackageRequestingPermission(disabledPkg, perm)
+ && ((privilegedPermission && disabledPs.isPrivileged())
+ || (oemPermission && disabledPs.isOem()
+ && canGrantOemPermission(disabledPs, perm)))) {
+ allowed = true;
+ }
+ // Also if a privileged parent package on the system image or any of
+ // its children requested a privileged/oem permission, the updated child
+ // packages can also get the permission.
+ if (pkg.parentPackage != null) {
+ final PackageParser.Package disabledParentPkg = mPackageManagerInt
+ .getDisabledPackage(pkg.parentPackage.packageName);
+ final PackageSetting disabledParentPs = (disabledParentPkg != null)
+ ? (PackageSetting) disabledParentPkg.mExtras : null;
+ if (disabledParentPkg != null
+ && ((privilegedPermission && disabledParentPs.isPrivileged())
+ || (oemPermission && disabledParentPs.isOem()))) {
+ if (isPackageRequestingPermission(disabledParentPkg, perm)
+ && canGrantOemPermission(disabledParentPs, perm)) {
+ allowed = true;
+ } else if (disabledParentPkg.childPackages != null) {
+ for (PackageParser.Package disabledChildPkg
+ : disabledParentPkg.childPackages) {
+ final PackageSetting disabledChildPs =
+ (disabledChildPkg != null)
+ ? (PackageSetting) disabledChildPkg.mExtras
+ : null;
+ if (isPackageRequestingPermission(disabledChildPkg, perm)
+ && canGrantOemPermission(
+ disabledChildPs, perm)) {
+ allowed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ allowed = (privilegedPermission && pkg.isPrivileged())
+ || (oemPermission && pkg.isOem()
+ && canGrantOemPermission(ps, perm));
+ }
+ }
+ }
+ if (!allowed) {
+ if (!allowed
+ && bp.isPre23()
+ && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ // If this was a previously normal/dangerous permission that got moved
+ // to a system permission as part of the runtime permission redesign, then
+ // we still want to blindly grant it to old apps.
+ allowed = true;
+ }
+ if (!allowed && bp.isInstaller()
+ && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+ PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))) {
+ // If this permission is to be granted to the system installer and
+ // this app is an installer, then it gets the permission.
+ allowed = true;
+ }
+ if (!allowed && bp.isVerifier()
+ && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+ PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM))) {
+ // If this permission is to be granted to the system verifier and
+ // this app is a verifier, then it gets the permission.
+ allowed = true;
+ }
+ if (!allowed && bp.isPreInstalled()
+ && pkg.isSystem()) {
+ // Any pre-installed system app is allowed to get this permission.
+ allowed = true;
+ }
+ if (!allowed && bp.isDevelopment()) {
+ // For development permissions, a development permission
+ // is granted only if it was already granted.
+ allowed = origPermissions.hasInstallPermission(perm);
+ }
+ if (!allowed && bp.isSetup()
+ && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+ PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM))) {
+ // If this permission is to be granted to the system setup wizard and
+ // this app is a setup wizard, then it gets the permission.
+ allowed = true;
+ }
+ }
+ return allowed;
+ }
+
+ private static boolean canGrantOemPermission(PackageSetting ps, String permission) {
+ if (!ps.isOem()) {
+ return false;
+ }
+ // all oem permissions must explicitly be granted or denied
+ final Boolean granted =
+ SystemConfig.getInstance().getOemPermissions(ps.name).get(permission);
+ if (granted == null) {
+ throw new IllegalStateException("OEM permission" + permission + " requested by package "
+ + ps.name + " must be explicitly declared granted or not");
+ }
+ return Boolean.TRUE == granted;
+ }
+
+ private boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId) {
+ if (!mSettings.mPermissionReviewRequired) {
+ return false;
+ }
+
+ // Permission review applies only to apps not supporting the new permission model.
+ if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
+ return false;
+ }
+
+ // Legacy apps have the permission and get user consent on launch.
+ if (pkg == null || pkg.mExtras == null) {
+ return false;
+ }
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ final PermissionsState permissionsState = ps.getPermissionsState();
+ return permissionsState.isPermissionReviewRequired(userId);
+ }
+
+ private boolean isPackageRequestingPermission(PackageParser.Package pkg, String permission) {
+ final int permCount = pkg.requestedPermissions.size();
+ for (int j = 0; j < permCount; j++) {
+ String requestedPermission = pkg.requestedPermissions.get(j);
+ if (permission.equals(requestedPermission)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void grantRuntimePermissionsGrantedToDisabledPackageLocked(
PackageParser.Package pkg, int callingUid, PermissionCallback callback) {
if (pkg.parentPackage == null) {
@@ -744,7 +1493,8 @@ public class PermissionManagerService {
}
}
- private int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting, int[] allUserIds) {
+ private int[] revokeUnusedSharedUserPermissionsLocked(
+ SharedUserSetting suSetting, int[] allUserIds) {
// Collect all used permissions in the UID
final ArraySet<String> usedPermissions = new ArraySet<>();
final List<PackageParser.Package> pkgList = suSetting.getPackages();
@@ -845,7 +1595,79 @@ public class PermissionManagerService {
return permissionsState.getPermissionFlags(permName, userId);
}
- private int updatePermissions(String packageName, PackageParser.Package pkgInfo, int flags) {
+ private static final int UPDATE_PERMISSIONS_ALL = 1<<0;
+ private static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
+ private static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
+
+ private void updatePermissions(String packageName, PackageParser.Package pkg,
+ boolean replaceGrant, Collection<PackageParser.Package> allPackages,
+ PermissionCallback callback) {
+ final int flags = (pkg != null ? UPDATE_PERMISSIONS_ALL : 0) |
+ (replaceGrant ? UPDATE_PERMISSIONS_REPLACE_PKG : 0);
+ updatePermissions(
+ packageName, pkg, getVolumeUuidForPackage(pkg), flags, allPackages, callback);
+ if (pkg != null && pkg.childPackages != null) {
+ for (PackageParser.Package childPkg : pkg.childPackages) {
+ updatePermissions(childPkg.packageName, childPkg,
+ getVolumeUuidForPackage(childPkg), flags, allPackages, callback);
+ }
+ }
+ }
+
+ private void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
+ Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
+ final int flags = UPDATE_PERMISSIONS_ALL |
+ (sdkUpdated
+ ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
+ : 0);
+ updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
+ }
+
+ private void updatePermissions(String changingPkgName, PackageParser.Package changingPkg,
+ String replaceVolumeUuid, int flags, Collection<PackageParser.Package> allPackages,
+ PermissionCallback callback) {
+ // TODO: Most of the methods exposing BasePermission internals [source package name,
+ // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
+ // have package settings, we should make note of it elsewhere [map between
+ // source package name and BasePermission] and cycle through that here. Then we
+ // define a single method on BasePermission that takes a PackageSetting, changing
+ // package name and a package.
+ // NOTE: With this approach, we also don't need to tree trees differently than
+ // normal permissions. Today, we need two separate loops because these BasePermission
+ // objects are stored separately.
+ // Make sure there are no dangling permission trees.
+ flags = updatePermissionTrees(changingPkgName, changingPkg, flags);
+
+ // Make sure all dynamic permissions have been assigned to a package,
+ // and make sure there are no dangling permissions.
+ flags = updatePermissions(changingPkgName, changingPkg, flags);
+
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
+ // Now update the permissions for all packages, in particular
+ // replace the granted permissions of the system packages.
+ if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
+ for (PackageParser.Package pkg : allPackages) {
+ if (pkg != changingPkg) {
+ // Only replace for packages on requested volume
+ final String volumeUuid = getVolumeUuidForPackage(pkg);
+ final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
+ && Objects.equals(replaceVolumeUuid, volumeUuid);
+ grantPermissions(pkg, replace, changingPkgName, callback);
+ }
+ }
+ }
+
+ if (changingPkg != null) {
+ // Only replace for packages on requested volume
+ final String volumeUuid = getVolumeUuidForPackage(changingPkg);
+ final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
+ && Objects.equals(replaceVolumeUuid, volumeUuid);
+ grantPermissions(changingPkg, replace, changingPkgName, callback);
+ }
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+
+ private int updatePermissions(String packageName, PackageParser.Package pkg, int flags) {
Set<BasePermission> needsUpdate = null;
synchronized (mLock) {
final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
@@ -856,10 +1678,10 @@ public class PermissionManagerService {
}
if (bp.getSourcePackageSetting() != null) {
if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
+ && (pkg == null || !hasPermission(pkg, bp.getName()))) {
Slog.i(TAG, "Removing old permission tree: " + bp.getName()
+ " from package " + bp.getSourcePackageName());
- flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
+ flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
continue;
@@ -872,13 +1694,13 @@ public class PermissionManagerService {
}
if (needsUpdate != null) {
for (final BasePermission bp : needsUpdate) {
- final PackageParser.Package pkg =
+ final PackageParser.Package sourcePkg =
mPackageManagerInt.getPackage(bp.getSourcePackageName());
synchronized (mLock) {
- if (pkg != null && pkg.mExtras != null) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (sourcePkg != null && sourcePkg.mExtras != null) {
+ final PackageSetting sourcePs = (PackageSetting) sourcePkg.mExtras;
if (bp.getSourcePackageSetting() == null) {
- bp.setSourcePackageSetting(ps);
+ bp.setSourcePackageSetting(sourcePs);
}
continue;
}
@@ -891,7 +1713,7 @@ public class PermissionManagerService {
return flags;
}
- private int updatePermissionTrees(String packageName, PackageParser.Package pkgInfo,
+ private int updatePermissionTrees(String packageName, PackageParser.Package pkg,
int flags) {
Set<BasePermission> needsUpdate = null;
synchronized (mLock) {
@@ -900,10 +1722,10 @@ public class PermissionManagerService {
final BasePermission bp = it.next();
if (bp.getSourcePackageSetting() != null) {
if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
+ && (pkg == null || !hasPermission(pkg, bp.getName()))) {
Slog.i(TAG, "Removing old permission tree: " + bp.getName()
+ " from package " + bp.getSourcePackageName());
- flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
+ flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
continue;
@@ -916,13 +1738,13 @@ public class PermissionManagerService {
}
if (needsUpdate != null) {
for (final BasePermission bp : needsUpdate) {
- final PackageParser.Package pkg =
+ final PackageParser.Package sourcePkg =
mPackageManagerInt.getPackage(bp.getSourcePackageName());
synchronized (mLock) {
- if (pkg != null && pkg.mExtras != null) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (sourcePkg != null && sourcePkg.mExtras != null) {
+ final PackageSetting sourcePs = (PackageSetting) sourcePkg.mExtras;
if (bp.getSourcePackageSetting() == null) {
- bp.setSourcePackageSetting(ps);
+ bp.setSourcePackageSetting(sourcePs);
}
continue;
}
@@ -985,7 +1807,7 @@ public class PermissionManagerService {
callback.onInstallPermissionUpdated();
} else if (permissionsState.getRuntimePermissionState(permName, userId) != null
|| hadState) {
- callback.onPermissionUpdated(userId);
+ callback.onPermissionUpdated(new int[] { userId }, false);
}
}
}
@@ -1083,6 +1905,29 @@ public class PermissionManagerService {
}
}
+ private void systemReady() {
+ mSystemReady = true;
+ if (mPrivappPermissionsViolations != null) {
+ throw new IllegalStateException("Signature|privileged permissions not in "
+ + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+ }
+ }
+
+ private static String getVolumeUuidForPackage(PackageParser.Package pkg) {
+ if (pkg == null) {
+ return StorageManager.UUID_PRIVATE_INTERNAL;
+ }
+ if (pkg.isExternal()) {
+ if (TextUtils.isEmpty(pkg.volumeUuid)) {
+ return StorageManager.UUID_PRIMARY_PHYSICAL;
+ } else {
+ return pkg.volumeUuid;
+ }
+ } else {
+ return StorageManager.UUID_PRIVATE_INTERNAL;
+ }
+ }
+
private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) {
for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
if (pkgInfo.permissions.get(i).info.name.equals(permName)) {
@@ -1154,10 +1999,22 @@ public class PermissionManagerService {
private class PermissionManagerInternalImpl extends PermissionManagerInternal {
@Override
+ public void systemReady() {
+ PermissionManagerService.this.systemReady();
+ }
+ @Override
+ public boolean isPermissionsReviewRequired(Package pkg, int userId) {
+ return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId);
+ }
+ @Override
public void addAllPermissions(Package pkg, boolean chatty) {
PermissionManagerService.this.addAllPermissions(pkg, chatty);
}
@Override
+ public void addAllPermissionGroups(Package pkg, boolean chatty) {
+ PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
+ }
+ @Override
public void removeAllPermissions(Package pkg, boolean chatty) {
PermissionManagerService.this.removeAllPermissions(pkg, chatty);
}
@@ -1198,10 +2055,16 @@ public class PermissionManagerService {
overridePolicy, callingUid, userId, callback);
}
@Override
- public int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting,
- int[] allUserIds) {
- return PermissionManagerService.this.revokeUnusedSharedUserPermissions(
- (SharedUserSetting) suSetting, allUserIds);
+ public void updatePermissions(String packageName, Package pkg, boolean replaceGrant,
+ Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
+ PermissionManagerService.this.updatePermissions(
+ packageName, pkg, replaceGrant, allPackages, callback);
+ }
+ @Override
+ public void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
+ Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
+ PermissionManagerService.this.updateAllPermissions(
+ volumeUuid, sdkUpdated, allPackages, callback);
}
@Override
public String[] getAppOpPermissionPackages(String permName) {
@@ -1214,16 +2077,6 @@ public class PermissionManagerService {
callingUid, userId);
}
@Override
- public int updatePermissions(String packageName,
- PackageParser.Package pkgInfo, int flags) {
- return PermissionManagerService.this.updatePermissions(packageName, pkgInfo, flags);
- }
- @Override
- public int updatePermissionTrees(String packageName,
- PackageParser.Package pkgInfo, int flags) {
- return PermissionManagerService.this.updatePermissionTrees(packageName, pkgInfo, flags);
- }
- @Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
@@ -1252,6 +2105,20 @@ public class PermissionManagerService {
permName, packageName, callingUid, userId);
}
@Override
+ public int checkUidPermission(String permName, int uid, int callingUid) {
+ return PermissionManagerService.this.checkUidPermission(permName, uid, callingUid);
+ }
+ @Override
+ public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
+ int callingUid) {
+ return PermissionManagerService.this.getPermissionGroupInfo(
+ groupName, flags, callingUid);
+ }
+ @Override
+ public List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
+ return PermissionManagerService.this.getAllPermissionGroups(flags, callingUid);
+ }
+ @Override
public PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
int callingUid) {
return PermissionManagerService.this.getPermissionInfo(
@@ -1276,17 +2143,5 @@ public class PermissionManagerService {
return mSettings.getPermissionLocked(permName);
}
}
- @Override
- public void putPermissionTEMP(String permName, BasePermission permission) {
- synchronized (PermissionManagerService.this.mLock) {
- mSettings.putPermissionLocked(permName, (BasePermission) permission);
- }
- }
- @Override
- public Iterator<BasePermission> getPermissionIteratorTEMP() {
- synchronized (PermissionManagerService.this.mLock) {
- return mSettings.getAllPermissionsLocked().iterator();
- }
- }
}
}
diff --git a/com/android/server/pm/permission/PermissionSettings.java b/com/android/server/pm/permission/PermissionSettings.java
index 7d125c9e..f6c4990c 100644
--- a/com/android/server/pm/permission/PermissionSettings.java
+++ b/com/android/server/pm/permission/PermissionSettings.java
@@ -19,6 +19,7 @@ package com.android.server.pm.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.PackageParser;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -46,7 +47,8 @@ import java.util.Set;
*/
public class PermissionSettings {
- final boolean mPermissionReviewRequired;
+ public final boolean mPermissionReviewRequired;
+
/**
* All of the permissions known to the system. The mapping is from permission
* name to permission object.
@@ -64,6 +66,14 @@ public class PermissionSettings {
new ArrayMap<String, BasePermission>();
/**
+ * All permisson groups know to the system. The mapping is from permission group
+ * name to permission group object.
+ */
+ @GuardedBy("mLock")
+ final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups =
+ new ArrayMap<String, PackageParser.PermissionGroup>();
+
+ /**
* Set of packages that request a particular app op. The mapping is from permission
* name to package names.
*/