Protect instant apps from full apps
Bug: 35871369
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest
Test: Manual; install instant app and ensure it runs
Change-Id: I1835fe58256377f901db38fcc3e4c98886d799ac
(cherry picked from commit befd4bc33c)
This commit is contained in:
@@ -3593,13 +3593,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkPackageStartable(String packageName, int userId) {
|
public void checkPackageStartable(String packageName, int userId) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
throw new SecurityException("Instant applications don't have access to this method");
|
throw new SecurityException("Instant applications don't have access to this method");
|
||||||
}
|
}
|
||||||
final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
|
final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
if (ps == null) {
|
if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
throw new SecurityException("Package " + packageName + " was not found!");
|
throw new SecurityException("Package " + packageName + " was not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3868,15 +3869,26 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] currentToCanonicalPackageNames(String[] names) {
|
public String[] currentToCanonicalPackageNames(String[] names) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
String[] out = new String[names.length];
|
final String[] out = new String[names.length];
|
||||||
// reader
|
// reader
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
|
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||||
|
final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
|
||||||
for (int i=names.length-1; i>=0; i--) {
|
for (int i=names.length-1; i>=0; i--) {
|
||||||
PackageSetting ps = mSettings.mPackages.get(names[i]);
|
final PackageSetting ps = mSettings.mPackages.get(names[i]);
|
||||||
out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
|
boolean translateName = false;
|
||||||
|
if (ps != null && ps.realName != null) {
|
||||||
|
final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
|
||||||
|
translateName = !targetIsInstantApp
|
||||||
|
|| canViewInstantApps
|
||||||
|
|| mInstantAppRegistry.isInstantAccessGranted(callingUserId,
|
||||||
|
UserHandle.getAppId(callingUid), ps.appId);
|
||||||
|
}
|
||||||
|
out[i] = translateName ? ps.realName : names[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -3884,15 +3896,28 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] canonicalToCurrentPackageNames(String[] names) {
|
public String[] canonicalToCurrentPackageNames(String[] names) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
String[] out = new String[names.length];
|
final String[] out = new String[names.length];
|
||||||
// reader
|
// reader
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
|
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||||
|
final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
|
||||||
for (int i=names.length-1; i>=0; i--) {
|
for (int i=names.length-1; i>=0; i--) {
|
||||||
String cur = mSettings.getRenamedPackageLPr(names[i]);
|
final String cur = mSettings.getRenamedPackageLPr(names[i]);
|
||||||
out[i] = cur != null ? cur : names[i];
|
boolean translateName = false;
|
||||||
|
if (cur != null) {
|
||||||
|
final PackageSetting ps = mSettings.mPackages.get(names[i]);
|
||||||
|
final boolean targetIsInstantApp =
|
||||||
|
ps != null && ps.getInstantApp(callingUserId);
|
||||||
|
translateName = !targetIsInstantApp
|
||||||
|
|| canViewInstantApps
|
||||||
|
|| mInstantAppRegistry.isInstantAccessGranted(callingUserId,
|
||||||
|
UserHandle.getAppId(callingUid), ps.appId);
|
||||||
|
}
|
||||||
|
out[i] = translateName ? cur : names[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -5302,12 +5327,13 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
Log.e(TAG, "No such user:" + userId);
|
Log.e(TAG, "No such user:" + userId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
|
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
|
||||||
"grantRuntimePermission");
|
"grantRuntimePermission");
|
||||||
|
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, true /* checkShell */,
|
true /* requireFullPermission */, true /* checkShell */,
|
||||||
"grantRuntimePermission");
|
"grantRuntimePermission");
|
||||||
|
|
||||||
@@ -5319,11 +5345,18 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
if (pkg == null) {
|
if (pkg == null) {
|
||||||
throw new IllegalArgumentException("Unknown package: " + packageName);
|
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BasePermission bp = mSettings.mPermissions.get(name);
|
final BasePermission bp = mSettings.mPermissions.get(name);
|
||||||
if (bp == null) {
|
if (bp == null) {
|
||||||
throw new IllegalArgumentException("Unknown permission: " + name);
|
throw new IllegalArgumentException("Unknown permission: " + name);
|
||||||
}
|
}
|
||||||
|
sb = (SettingBase) pkg.mExtras;
|
||||||
|
if (sb == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||||
|
}
|
||||||
|
if (sb instanceof PackageSetting
|
||||||
|
&& filterAppAccessLPr((PackageSetting) sb, callingUid, userId)) {
|
||||||
|
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||||
|
}
|
||||||
|
|
||||||
enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
|
enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
|
||||||
|
|
||||||
@@ -5338,10 +5371,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
|
uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
|
||||||
sb = (SettingBase) pkg.mExtras;
|
|
||||||
if (sb == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown package: " + packageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
final PermissionsState permissionsState = sb.getPermissionsState();
|
final PermissionsState permissionsState = sb.getPermissionsState();
|
||||||
|
|
||||||
@@ -5611,7 +5640,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
|
enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
|
||||||
|
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, false /* checkShell */,
|
true /* requireFullPermission */, false /* checkShell */,
|
||||||
"getPermissionFlags");
|
"getPermissionFlags");
|
||||||
|
|
||||||
@@ -5620,17 +5650,18 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
if (pkg == null) {
|
if (pkg == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
final BasePermission bp = mSettings.mPermissions.get(name);
|
final BasePermission bp = mSettings.mPermissions.get(name);
|
||||||
if (bp == null) {
|
if (bp == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
final SettingBase sb = (SettingBase) pkg.mExtras;
|
||||||
SettingBase sb = (SettingBase) pkg.mExtras;
|
|
||||||
if (sb == null) {
|
if (sb == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (sb instanceof PackageSetting
|
||||||
|
&& filterAppAccessLPr((PackageSetting) sb, callingUid, userId)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
PermissionsState permissionsState = sb.getPermissionsState();
|
PermissionsState permissionsState = sb.getPermissionsState();
|
||||||
return permissionsState.getPermissionFlags(name, userId);
|
return permissionsState.getPermissionFlags(name, userId);
|
||||||
}
|
}
|
||||||
@@ -6171,7 +6202,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getFlagsForUid(int uid) {
|
public int getFlagsForUid(int uid) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
@@ -6181,6 +6213,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
return sus.pkgFlags;
|
return sus.pkgFlags;
|
||||||
} else if (obj instanceof PackageSetting) {
|
} else if (obj instanceof PackageSetting) {
|
||||||
final PackageSetting ps = (PackageSetting) obj;
|
final PackageSetting ps = (PackageSetting) obj;
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return ps.pkgFlags;
|
return ps.pkgFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6189,7 +6224,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPrivateFlagsForUid(int uid) {
|
public int getPrivateFlagsForUid(int uid) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
@@ -6199,6 +6235,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
return sus.pkgPrivateFlags;
|
return sus.pkgPrivateFlags;
|
||||||
} else if (obj instanceof PackageSetting) {
|
} else if (obj instanceof PackageSetting) {
|
||||||
final PackageSetting ps = (PackageSetting) obj;
|
final PackageSetting ps = (PackageSetting) obj;
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return ps.pkgPrivateFlags;
|
return ps.pkgPrivateFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8048,13 +8087,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
|
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return ParceledListSlice.emptyList();
|
return ParceledListSlice.emptyList();
|
||||||
}
|
}
|
||||||
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
|
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
|
||||||
flags = updateFlagsForPackage(flags, userId, null);
|
flags = updateFlagsForPackage(flags, userId, null);
|
||||||
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
|
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, false /* checkShell */,
|
true /* requireFullPermission */, false /* checkShell */,
|
||||||
"get installed packages");
|
"get installed packages");
|
||||||
|
|
||||||
@@ -8064,9 +8104,12 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
if (listUninstalled) {
|
if (listUninstalled) {
|
||||||
list = new ArrayList<>(mSettings.mPackages.size());
|
list = new ArrayList<>(mSettings.mPackages.size());
|
||||||
for (PackageSetting ps : mSettings.mPackages.values()) {
|
for (PackageSetting ps : mSettings.mPackages.values()) {
|
||||||
if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
|
if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final PackageInfo pi = generatePackageInfo(ps, flags, userId);
|
final PackageInfo pi = generatePackageInfo(ps, flags, userId);
|
||||||
if (pi != null) {
|
if (pi != null) {
|
||||||
list.add(pi);
|
list.add(pi);
|
||||||
@@ -8075,10 +8118,13 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
} else {
|
} else {
|
||||||
list = new ArrayList<>(mPackages.size());
|
list = new ArrayList<>(mPackages.size());
|
||||||
for (PackageParser.Package p : mPackages.values()) {
|
for (PackageParser.Package p : mPackages.values()) {
|
||||||
if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
|
final PackageSetting ps = (PackageSetting) p.mExtras;
|
||||||
Binder.getCallingUid(), userId, flags)) {
|
if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final PackageInfo pi = generatePackageInfo((PackageSetting)
|
final PackageInfo pi = generatePackageInfo((PackageSetting)
|
||||||
p.mExtras, flags, userId);
|
p.mExtras, flags, userId);
|
||||||
if (pi != null) {
|
if (pi != null) {
|
||||||
@@ -8165,7 +8211,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
|
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return ParceledListSlice.emptyList();
|
return ParceledListSlice.emptyList();
|
||||||
}
|
}
|
||||||
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
|
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
|
||||||
@@ -8184,9 +8231,12 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
effectiveFlags |= PackageManager.MATCH_ANY_USER;
|
effectiveFlags |= PackageManager.MATCH_ANY_USER;
|
||||||
}
|
}
|
||||||
if (ps.pkg != null) {
|
if (ps.pkg != null) {
|
||||||
if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
|
if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
|
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
|
||||||
ps.readUserState(userId), userId);
|
ps.readUserState(userId), userId);
|
||||||
if (ai != null) {
|
if (ai != null) {
|
||||||
@@ -8197,7 +8247,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
// Shared lib filtering done in generateApplicationInfoFromSettingsLPw
|
// Shared lib filtering done in generateApplicationInfoFromSettingsLPw
|
||||||
// and already converts to externally visible package name
|
// and already converts to externally visible package name
|
||||||
ai = generateApplicationInfoFromSettingsLPw(ps.name,
|
ai = generateApplicationInfoFromSettingsLPw(ps.name,
|
||||||
Binder.getCallingUid(), effectiveFlags, userId);
|
callingUid, effectiveFlags, userId);
|
||||||
}
|
}
|
||||||
if (ai != null) {
|
if (ai != null) {
|
||||||
list.add(ai);
|
list.add(ai);
|
||||||
@@ -8211,6 +8261,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
|
if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
|
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
|
||||||
ps.readUserState(userId), userId);
|
ps.readUserState(userId), userId);
|
||||||
if (ai != null) {
|
if (ai != null) {
|
||||||
@@ -9350,6 +9403,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean performDexOpt(String packageName,
|
public boolean performDexOpt(String packageName,
|
||||||
boolean checkProfiles, int compileReason, boolean force, boolean bootComplete) {
|
boolean checkProfiles, int compileReason, boolean force, boolean bootComplete) {
|
||||||
|
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
||||||
|
return false;
|
||||||
|
} else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int dexoptStatus = performDexOptWithStatus(
|
int dexoptStatus = performDexOptWithStatus(
|
||||||
packageName, checkProfiles, compileReason, force, bootComplete);
|
packageName, checkProfiles, compileReason, force, bootComplete);
|
||||||
return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
|
return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
|
||||||
@@ -9373,6 +9431,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
boolean bootComplete) {
|
boolean bootComplete) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
|
int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
|
||||||
targetCompilerFilter, force, bootComplete);
|
targetCompilerFilter, force, bootComplete);
|
||||||
@@ -9472,6 +9532,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
boolean force) {
|
boolean force) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
mDexManager.reconcileSecondaryDexFiles(packageName);
|
mDexManager.reconcileSecondaryDexFiles(packageName);
|
||||||
return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
|
return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
|
||||||
@@ -14368,19 +14430,23 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
|
public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
|
||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, false /* checkShell */,
|
true /* requireFullPermission */, false /* checkShell */,
|
||||||
"getApplicationHidden for user " + userId);
|
"getApplicationHidden for user " + userId);
|
||||||
PackageSetting pkgSetting;
|
PackageSetting ps;
|
||||||
long callingId = Binder.clearCallingIdentity();
|
long callingId = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
// writer
|
// writer
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
pkgSetting = mSettings.mPackages.get(packageName);
|
ps = mSettings.mPackages.get(packageName);
|
||||||
if (pkgSetting == null) {
|
if (ps == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return pkgSetting.getHidden(userId);
|
if (filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ps.getHidden(userId);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(callingId);
|
Binder.restoreCallingIdentity(callingId);
|
||||||
@@ -14396,8 +14462,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
|
||||||
null);
|
null);
|
||||||
PackageSetting pkgSetting;
|
PackageSetting pkgSetting;
|
||||||
final int uid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
enforceCrossUserPermission(uid, userId,
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, true /* checkShell */,
|
true /* requireFullPermission */, true /* checkShell */,
|
||||||
"installExistingPackage for user " + userId);
|
"installExistingPackage for user " + userId);
|
||||||
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
|
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
|
||||||
@@ -14880,10 +14946,16 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIntentVerificationStatus(String packageName, int userId) {
|
public int getIntentVerificationStatus(String packageName, int userId) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||||
}
|
}
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
|
if (ps == null
|
||||||
|
|| filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
|
return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||||
|
}
|
||||||
return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
|
return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14906,10 +14978,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
|
public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
|
||||||
String packageName) {
|
String packageName) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return ParceledListSlice.emptyList();
|
return ParceledListSlice.emptyList();
|
||||||
}
|
}
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
|
if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
|
return ParceledListSlice.emptyList();
|
||||||
|
}
|
||||||
return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
|
return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17075,12 +17152,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getPreviousCodePaths(String packageName) {
|
public List<String> getPreviousCodePaths(String packageName) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
final List<String> result = new ArrayList<>();
|
final List<String> result = new ArrayList<>();
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
if (getInstantAppPackageName(callingUid) != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
if (ps != null && ps.oldCodePaths != null) {
|
if (ps != null
|
||||||
|
&& ps.oldCodePaths != null
|
||||||
|
&& !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
result.addAll(ps.oldCodePaths);
|
result.addAll(ps.oldCodePaths);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -18310,8 +18390,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public void deletePackageVersioned(VersionedPackage versionedPackage,
|
public void deletePackageVersioned(VersionedPackage versionedPackage,
|
||||||
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
|
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.DELETE_PACKAGES, null);
|
android.Manifest.permission.DELETE_PACKAGES, null);
|
||||||
|
final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.ACCESS_INSTANT_APPS);
|
||||||
Preconditions.checkNotNull(versionedPackage);
|
Preconditions.checkNotNull(versionedPackage);
|
||||||
Preconditions.checkNotNull(observer);
|
Preconditions.checkNotNull(observer);
|
||||||
Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
|
Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
|
||||||
@@ -18376,6 +18459,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
public void run() {
|
public void run() {
|
||||||
mHandler.removeCallbacks(this);
|
mHandler.removeCallbacks(this);
|
||||||
int returnCode;
|
int returnCode;
|
||||||
|
final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
|
||||||
|
boolean doDeletePackage = true;
|
||||||
|
if (ps != null) {
|
||||||
|
final boolean targetIsInstantApp =
|
||||||
|
ps.getInstantApp(UserHandle.getUserId(callingUid));
|
||||||
|
doDeletePackage = !targetIsInstantApp
|
||||||
|
|| hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
if (doDeletePackage) {
|
||||||
if (!deleteAllUsers) {
|
if (!deleteAllUsers) {
|
||||||
returnCode = deletePackageX(internalPackageName, versionCode,
|
returnCode = deletePackageX(internalPackageName, versionCode,
|
||||||
userId, deleteFlags);
|
userId, deleteFlags);
|
||||||
@@ -18404,6 +18496,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
|
returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
observer.onPackageDeleted(packageName, returnCode, null);
|
observer.onPackageDeleted(packageName, returnCode, null);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -19212,6 +19307,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean getBlockUninstallForUser(String packageName, int userId) {
|
public boolean getBlockUninstallForUser(String packageName, int userId) {
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
|
if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return mSettings.getBlockUninstallLPr(userId, packageName);
|
return mSettings.getBlockUninstallLPr(userId, packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19561,9 +19660,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
|
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
|
||||||
|
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
true /* requireFullPermission */, false /* checkShell */, "clear application data");
|
true /* requireFullPermission */, false /* checkShell */, "clear application data");
|
||||||
|
|
||||||
|
final PackageSetting ps = mSettings.getPackageLPr(packageName);
|
||||||
|
if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
|
if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
|
||||||
throw new SecurityException("Cannot clear data for a protected package: "
|
throw new SecurityException("Cannot clear data for a protected package: "
|
||||||
+ packageName);
|
+ packageName);
|
||||||
@@ -19821,11 +19925,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
|
public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
|
||||||
final IPackageDataObserver observer) {
|
final IPackageDataObserver observer) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.DELETE_CACHE_FILES, null);
|
android.Manifest.permission.DELETE_CACHE_FILES, null);
|
||||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
enforceCrossUserPermission(callingUid, userId,
|
||||||
/* requireFullPermission= */ true, /* checkShell= */ false,
|
/* requireFullPermission= */ true, /* checkShell= */ false,
|
||||||
"delete application cache files");
|
"delete application cache files");
|
||||||
|
final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.ACCESS_INSTANT_APPS);
|
||||||
|
|
||||||
final PackageParser.Package pkg;
|
final PackageParser.Package pkg;
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
@@ -19835,6 +19942,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
// Queue up an async operation since the package deletion may take a little while.
|
// Queue up an async operation since the package deletion may take a little while.
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
final PackageSetting ps = (PackageSetting) pkg.mExtras;
|
||||||
|
boolean doClearData = true;
|
||||||
|
if (ps != null) {
|
||||||
|
final boolean targetIsInstantApp =
|
||||||
|
ps.getInstantApp(UserHandle.getUserId(callingUid));
|
||||||
|
doClearData = !targetIsInstantApp
|
||||||
|
|| hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
if (doClearData) {
|
||||||
synchronized (mInstallLock) {
|
synchronized (mInstallLock) {
|
||||||
final int flags = StorageManager.FLAG_STORAGE_DE
|
final int flags = StorageManager.FLAG_STORAGE_DE
|
||||||
| StorageManager.FLAG_STORAGE_CE;
|
| StorageManager.FLAG_STORAGE_CE;
|
||||||
@@ -19844,6 +19960,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
|
clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
|
||||||
}
|
}
|
||||||
clearExternalStorageDataSync(packageName, userId, false);
|
clearExternalStorageDataSync(packageName, userId, false);
|
||||||
|
}
|
||||||
if (observer != null) {
|
if (observer != null) {
|
||||||
try {
|
try {
|
||||||
observer.onRemoveCompleted(packageName, true);
|
observer.onRemoveCompleted(packageName, true);
|
||||||
@@ -20093,7 +20210,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
|
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final PackageSetting ps = mSettings.getPackageLPr(packageName);
|
||||||
|
if (ps != null
|
||||||
|
&& filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int user = UserHandle.getCallingUserId();
|
int user = UserHandle.getCallingUserId();
|
||||||
if (clearPackagePreferredActivitiesLPw(packageName, user)) {
|
if (clearPackagePreferredActivitiesLPw(packageName, user)) {
|
||||||
scheduleWritePackageRestrictionsLocked(user);
|
scheduleWritePackageRestrictionsLocked(user);
|
||||||
@@ -20743,7 +20864,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
|
public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||||
int callingUid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
enforceOwnerRights(ownerPackage, callingUid);
|
enforceOwnerRights(ownerPackage, callingUid);
|
||||||
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
|
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
@@ -20766,7 +20887,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
|
if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int callingUserId = UserHandle.getUserId(callingUid);
|
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||||
PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
|
PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
|
||||||
if (pi == null) {
|
if (pi == null) {
|
||||||
throw new IllegalArgumentException("Unknown package " + pkg + " on user "
|
throw new IllegalArgumentException("Unknown package " + pkg + " on user "
|
||||||
@@ -23402,13 +23523,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
public int movePackage(final String packageName, final String volumeUuid) {
|
public int movePackage(final String packageName, final String volumeUuid) {
|
||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
|
||||||
|
|
||||||
final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
|
||||||
final int moveId = mNextMoveId.getAndIncrement();
|
final int moveId = mNextMoveId.getAndIncrement();
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
movePackageInternal(packageName, volumeUuid, moveId, user);
|
movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
Slog.w(TAG, "Failed to move " + packageName, e);
|
Slog.w(TAG, "Failed to move " + packageName, e);
|
||||||
mMoveCallbacks.notifyStatusChanged(moveId,
|
mMoveCallbacks.notifyStatusChanged(moveId,
|
||||||
@@ -23420,7 +23542,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void movePackageInternal(final String packageName, final String volumeUuid,
|
private void movePackageInternal(final String packageName, final String volumeUuid,
|
||||||
final int moveId, UserHandle user) throws PackageManagerException {
|
final int moveId, final int callingUid, UserHandle user)
|
||||||
|
throws PackageManagerException {
|
||||||
final StorageManager storage = mContext.getSystemService(StorageManager.class);
|
final StorageManager storage = mContext.getSystemService(StorageManager.class);
|
||||||
final PackageManager pm = mContext.getPackageManager();
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
|
||||||
@@ -23440,10 +23563,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
final PackageParser.Package pkg = mPackages.get(packageName);
|
final PackageParser.Package pkg = mPackages.get(packageName);
|
||||||
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
final PackageSetting ps = mSettings.mPackages.get(packageName);
|
||||||
if (pkg == null || ps == null) {
|
if (pkg == null
|
||||||
|
|| ps == null
|
||||||
|
|| filterAppAccessLPr(ps, callingUid, user.getIdentifier())) {
|
||||||
throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
|
throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg.applicationInfo.isSystemApp()) {
|
if (pkg.applicationInfo.isSystemApp()) {
|
||||||
throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
|
throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
|
||||||
"Cannot move system application");
|
"Cannot move system application");
|
||||||
@@ -23913,6 +24037,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
|
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
|
||||||
throw new IllegalArgumentException("Unknown package: " + packageName);
|
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||||
}
|
}
|
||||||
|
final PackageSetting ps = (PackageSetting) pkg.mExtras;
|
||||||
|
if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
|
||||||
|
Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
|
||||||
|
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||||
|
}
|
||||||
KeySetManagerService ksms = mSettings.mKeySetManagerService;
|
KeySetManagerService ksms = mSettings.mKeySetManagerService;
|
||||||
return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
|
return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
|
||||||
}
|
}
|
||||||
@@ -24629,9 +24758,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRequestPackageInstalls(String packageName, int userId) {
|
public boolean canRequestPackageInstalls(String packageName, int userId) {
|
||||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return canRequestPackageInstallsInternal(packageName, 0, userId,
|
return canRequestPackageInstallsInternal(packageName, 0, userId,
|
||||||
true /* throwIfPermNotDeclared*/);
|
true /* throwIfPermNotDeclared*/);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user