Merge "Kill app if cross profile app op gets revoked" into rvc-dev am: 45c68542f9 am: 0571d3ab0d am: 2ae2b39211
Change-Id: I0cccb3df18cf87840c6c4d3a82712962215454b7
This commit is contained in:
@@ -50,6 +50,7 @@ import android.os.IBinder;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.permission.PermissionManager;
|
||||||
import android.stats.devicepolicy.DevicePolicyEnums;
|
import android.stats.devicepolicy.DevicePolicyEnums;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -458,6 +459,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
|||||||
+ packageName + " on user ID " + userId);
|
+ packageName + " on user ID " + userId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean hadPermission = hasInteractAcrossProfilesPermission(
|
||||||
|
packageName, uid, PermissionChecker.PID_UNKNOWN);
|
||||||
|
|
||||||
final int callingUid = mInjector.getCallingUid();
|
final int callingUid = mInjector.getCallingUid();
|
||||||
if (isPermissionGranted(
|
if (isPermissionGranted(
|
||||||
Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
|
Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
|
||||||
@@ -472,6 +477,22 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
|||||||
}
|
}
|
||||||
sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
|
sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
|
||||||
maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
|
maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
|
||||||
|
maybeKillUid(packageName, uid, hadPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kills the process represented by the given UID if it has lost the permission to
|
||||||
|
* interact across profiles.
|
||||||
|
*/
|
||||||
|
private void maybeKillUid(
|
||||||
|
String packageName, int uid, boolean hadPermission) {
|
||||||
|
if (!hadPermission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hasInteractAcrossProfilesPermission(packageName, uid, PermissionChecker.PID_UNKNOWN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInjector.killUid(packageName, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeLogSetInteractAcrossProfilesAppOp(
|
private void maybeLogSetInteractAcrossProfilesAppOp(
|
||||||
@@ -774,6 +795,18 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
|||||||
String permission, int uid, int owningUid, boolean exported) {
|
String permission, int uid, int owningUid, boolean exported) {
|
||||||
return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
|
return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void killUid(String packageName, int uid) {
|
||||||
|
try {
|
||||||
|
ActivityManager.getService().killApplication(
|
||||||
|
packageName,
|
||||||
|
UserHandle.getAppId(uid),
|
||||||
|
UserHandle.getUserId(uid),
|
||||||
|
PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED);
|
||||||
|
} catch (RemoteException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -813,6 +846,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
|||||||
void sendBroadcastAsUser(Intent intent, UserHandle user);
|
void sendBroadcastAsUser(Intent intent, UserHandle user);
|
||||||
|
|
||||||
int checkComponentPermission(String permission, int uid, int owningUid, boolean exported);
|
int checkComponentPermission(String permission, int uid, int owningUid, boolean exported);
|
||||||
|
|
||||||
|
void killUid(String packageName, int uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalService extends CrossProfileAppsInternal {
|
class LocalService extends CrossProfileAppsInternal {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import android.content.pm.IPackageManager;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManagerInternal;
|
import android.content.pm.PackageManagerInternal;
|
||||||
|
import android.content.pm.PermissionInfo;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -106,6 +107,7 @@ public class CrossProfileAppsServiceImplRoboTest {
|
|||||||
new CrossProfileAppsServiceImpl(mContext, mInjector);
|
new CrossProfileAppsServiceImpl(mContext, mInjector);
|
||||||
private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
|
private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
|
||||||
private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>();
|
private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>();
|
||||||
|
private final Set<Integer> mKilledUids = new HashSet<>();
|
||||||
|
|
||||||
@Mock private PackageManagerInternal mPackageManagerInternal;
|
@Mock private PackageManagerInternal mPackageManagerInternal;
|
||||||
@Mock private IPackageManager mIPackageManager;
|
@Mock private IPackageManager mIPackageManager;
|
||||||
@@ -388,6 +390,33 @@ public class CrossProfileAppsServiceImplRoboTest {
|
|||||||
assertThat(receivedManifestCanInteractAcrossProfilesChangedBroadcast()).isTrue();
|
assertThat(receivedManifestCanInteractAcrossProfilesChangedBroadcast()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setInteractAcrossProfilesAppOp_toAllowed_doesNotKillApp() {
|
||||||
|
mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
|
||||||
|
CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
|
||||||
|
assertThat(mKilledUids).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setInteractAcrossProfilesAppOp_toDisallowed_killsAppsInBothProfiles() {
|
||||||
|
shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
|
||||||
|
mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
|
||||||
|
CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
|
||||||
|
|
||||||
|
mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
|
||||||
|
CROSS_PROFILE_APP_PACKAGE_NAME, MODE_DEFAULT);
|
||||||
|
|
||||||
|
assertThat(mKilledUids).contains(WORK_PROFILE_UID);
|
||||||
|
assertThat(mKilledUids).contains(PERSONAL_PROFILE_UID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PermissionInfo createCrossProfilesPermissionInfo() {
|
||||||
|
PermissionInfo permissionInfo = new PermissionInfo();
|
||||||
|
permissionInfo.name = Manifest.permission.INTERACT_ACROSS_PROFILES;
|
||||||
|
permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP;
|
||||||
|
return permissionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
|
public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
|
||||||
mockUninstallCrossProfileAppFromWorkProfile();
|
mockUninstallCrossProfileAppFromWorkProfile();
|
||||||
@@ -678,5 +707,10 @@ public class CrossProfileAppsServiceImplRoboTest {
|
|||||||
// ShadowActivityThread with Robolectric. This method is currently not supported there.
|
// ShadowActivityThread with Robolectric. This method is currently not supported there.
|
||||||
return mContext.checkPermission(permission, Process.myPid(), uid);
|
return mContext.checkPermission(permission, Process.myPid(), uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void killUid(String packageName, int uid) {
|
||||||
|
mKilledUids.add(uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ import android.content.pm.PermissionInfo;
|
|||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.permission.PermissionManager;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
@@ -692,5 +694,17 @@ public class CrossProfileAppsServiceImplTest {
|
|||||||
String permission, int uid, int owningUid, boolean exported) {
|
String permission, int uid, int owningUid, boolean exported) {
|
||||||
return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
|
return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void killUid(String packageName, int uid) {
|
||||||
|
try {
|
||||||
|
ActivityManager.getService().killApplication(
|
||||||
|
packageName,
|
||||||
|
UserHandle.getAppId(uid),
|
||||||
|
UserHandle.getUserId(uid),
|
||||||
|
PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED);
|
||||||
|
} catch (RemoteException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user