summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Cliff Wu <cliffwu@google.com> 2022-09-23 00:17:47 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-09-23 00:17:47 +0000
commita4ae390f137b11c5013a450a239b3ba95fbc9f8e (patch)
treea51fea206d43b85fbf8d39505b67e6252a620a66
parent5bca0e0058912a4bccd89ce9e233d70599506907 (diff)
parenta120143a974668dffea4805a76b61417a8f46a21 (diff)
Merge "Fixed camera streaming not being blocked when user taps camera on personal streaming apps" into tm-qpr-dev
-rw-r--r--services/companion/java/com/android/server/companion/virtual/CameraAccessController.java99
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java94
2 files changed, 152 insertions, 41 deletions
diff --git a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
index ec0da490adcf..2904f28fca01 100644
--- a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
+++ b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
@@ -22,14 +22,19 @@ import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraInjectionSession;
import android.hardware.camera2.CameraManager;
+import android.os.Process;
+import android.os.UserManager;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import java.util.List;
import java.util.Set;
/**
@@ -45,6 +50,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
private final CameraAccessBlockedCallback mBlockedCallback;
private final CameraManager mCameraManager;
private final PackageManager mPackageManager;
+ private final UserManager mUserManager;
@GuardedBy("mLock")
private int mObserverCount = 0;
@@ -66,7 +72,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
static class OpenCameraInfo {
public String packageName;
- public int packageUid;
+ public Set<Integer> packageUids;
}
interface CameraAccessBlockedCallback {
@@ -85,6 +91,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
mBlockedCallback = blockedCallback;
mCameraManager = mContext.getSystemService(CameraManager.class);
mPackageManager = mContext.getPackageManager();
+ mUserManager = mContext.getSystemService(UserManager.class);
}
/**
@@ -125,16 +132,18 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
for (int i = 0; i < mAppsToBlockOnVirtualDevice.size(); i++) {
final String cameraId = mAppsToBlockOnVirtualDevice.keyAt(i);
final OpenCameraInfo openCameraInfo = mAppsToBlockOnVirtualDevice.get(cameraId);
- int packageUid = openCameraInfo.packageUid;
- if (runningUids.contains(packageUid)) {
- final String packageName = openCameraInfo.packageName;
- InjectionSessionData data = mPackageToSessionData.get(packageName);
- if (data == null) {
- data = new InjectionSessionData();
- data.appUid = packageUid;
- mPackageToSessionData.put(packageName, data);
+ final String packageName = openCameraInfo.packageName;
+ for (int packageUid : openCameraInfo.packageUids) {
+ if (runningUids.contains(packageUid)) {
+ InjectionSessionData data = mPackageToSessionData.get(packageName);
+ if (data == null) {
+ data = new InjectionSessionData();
+ data.appUid = packageUid;
+ mPackageToSessionData.put(packageName, data);
+ }
+ startBlocking(packageName, cameraId);
+ break;
}
- startBlocking(packageName, cameraId);
}
}
}
@@ -155,37 +164,41 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
@Override
public void onCameraOpened(@NonNull String cameraId, @NonNull String packageName) {
synchronized (mLock) {
- try {
- final ApplicationInfo ainfo = mPackageManager.getApplicationInfo(packageName, 0);
- InjectionSessionData data = mPackageToSessionData.get(packageName);
- if (!mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(ainfo.uid)) {
- OpenCameraInfo openCameraInfo = new OpenCameraInfo();
- openCameraInfo.packageName = packageName;
- openCameraInfo.packageUid = ainfo.uid;
- mAppsToBlockOnVirtualDevice.put(cameraId, openCameraInfo);
- CameraInjectionSession existingSession =
- (data != null) ? data.cameraIdToSession.get(cameraId) : null;
- if (existingSession != null) {
- existingSession.close();
- data.cameraIdToSession.remove(cameraId);
- if (data.cameraIdToSession.isEmpty()) {
- mPackageToSessionData.remove(packageName);
- }
+ InjectionSessionData data = mPackageToSessionData.get(packageName);
+ List<UserInfo> aliveUsers = mUserManager.getAliveUsers();
+ ArraySet<Integer> packageUids = new ArraySet<>();
+ for (UserInfo user : aliveUsers) {
+ int userId = user.getUserHandle().getIdentifier();
+ int appUid = queryUidFromPackageName(userId, packageName);
+ if (mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(appUid)) {
+ if (data == null) {
+ data = new InjectionSessionData();
+ data.appUid = appUid;
+ mPackageToSessionData.put(packageName, data);
+ }
+ if (data.cameraIdToSession.containsKey(cameraId)) {
+ return;
}
+ startBlocking(packageName, cameraId);
return;
+ } else {
+ if (appUid != Process.INVALID_UID) {
+ packageUids.add(appUid);
+ }
}
- if (data == null) {
- data = new InjectionSessionData();
- data.appUid = ainfo.uid;
- mPackageToSessionData.put(packageName, data);
- }
- if (data.cameraIdToSession.containsKey(cameraId)) {
- return;
+ }
+ OpenCameraInfo openCameraInfo = new OpenCameraInfo();
+ openCameraInfo.packageName = packageName;
+ openCameraInfo.packageUids = packageUids;
+ mAppsToBlockOnVirtualDevice.put(cameraId, openCameraInfo);
+ CameraInjectionSession existingSession =
+ (data != null) ? data.cameraIdToSession.get(cameraId) : null;
+ if (existingSession != null) {
+ existingSession.close();
+ data.cameraIdToSession.remove(cameraId);
+ if (data.cameraIdToSession.isEmpty()) {
+ mPackageToSessionData.remove(packageName);
}
- startBlocking(packageName, cameraId);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "onCameraOpened - unknown package " + packageName, e);
- return;
}
}
}
@@ -274,4 +287,16 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
}
}
}
+
+ private int queryUidFromPackageName(int userId, String packageName) {
+ try {
+ final ApplicationInfo ainfo =
+ mPackageManager.getApplicationInfoAsUser(packageName,
+ PackageManager.GET_ACTIVITIES, userId);
+ return ainfo.uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(TAG, "queryUidFromPackageName - unknown package " + packageName, e);
+ return Process.INVALID_UID;
+ }
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
index c4c3abc1388e..145e66c92f14 100644
--- a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
@@ -30,10 +30,13 @@ import static org.mockito.Mockito.when;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraInjectionSession;
import android.hardware.camera2.CameraManager;
import android.os.Process;
+import android.os.UserManager;
import android.testing.TestableContext;
import android.util.ArraySet;
@@ -51,12 +54,17 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(AndroidJUnit4.class)
public class CameraAccessControllerTest {
private static final String FRONT_CAMERA = "0";
private static final String REAR_CAMERA = "1";
private static final String TEST_APP_PACKAGE = "some.package";
private static final String OTHER_APP_PACKAGE = "other.package";
+ private static final int PERSONAL_PROFILE_USER_ID = 0;
+ private static final int WORK_PROFILE_USER_ID = 10;
private CameraAccessController mController;
@@ -69,6 +77,8 @@ public class CameraAccessControllerTest {
@Mock
private PackageManager mPackageManager;
@Mock
+ private UserManager mUserManager;
+ @Mock
private VirtualDeviceManagerInternal mDeviceManagerInternal;
@Mock
private CameraAccessController.CameraAccessBlockedCallback mBlockedCallback;
@@ -76,6 +86,7 @@ public class CameraAccessControllerTest {
private ApplicationInfo mTestAppInfo = new ApplicationInfo();
private ApplicationInfo mOtherAppInfo = new ApplicationInfo();
private ArraySet<Integer> mRunningUids = new ArraySet<>();
+ private List<UserInfo> mAliveUsers = new ArrayList<>();
@Captor
ArgumentCaptor<CameraInjectionSession.InjectionStatusCallback> mInjectionCallbackCaptor;
@@ -84,6 +95,7 @@ public class CameraAccessControllerTest {
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
mContext.addMockSystemService(CameraManager.class, mCameraManager);
+ mContext.addMockSystemService(UserManager.class, mUserManager);
mContext.setMockPackageManager(mPackageManager);
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
LocalServices.addService(VirtualDeviceManagerInternal.class, mDeviceManagerInternal);
@@ -92,10 +104,14 @@ public class CameraAccessControllerTest {
mTestAppInfo.uid = Process.FIRST_APPLICATION_UID;
mOtherAppInfo.uid = Process.FIRST_APPLICATION_UID + 1;
mRunningUids.add(Process.FIRST_APPLICATION_UID);
- when(mPackageManager.getApplicationInfo(eq(TEST_APP_PACKAGE), anyInt())).thenReturn(
- mTestAppInfo);
- when(mPackageManager.getApplicationInfo(eq(OTHER_APP_PACKAGE), anyInt())).thenReturn(
- mOtherAppInfo);
+ mAliveUsers.add(new UserInfo(PERSONAL_PROFILE_USER_ID, "", 0));
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ anyInt())).thenReturn(mTestAppInfo);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(OTHER_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ anyInt())).thenReturn(mOtherAppInfo);
+ when(mUserManager.getAliveUsers()).thenReturn(mAliveUsers);
mController.startObservingIfNeeded();
}
@@ -227,4 +243,74 @@ public class CameraAccessControllerTest {
verify(mCameraManager, times(1)).injectCamera(any(), any(), any(), any(), any());
}
+
+ @Test
+ public void multipleUsers_getPersonalProfileAppUid_cameraBlocked()
+ throws CameraAccessException, NameNotFoundException {
+ mAliveUsers.add(new UserInfo(WORK_PROFILE_USER_ID, "", 0));
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(PERSONAL_PROFILE_USER_ID))).thenReturn(mTestAppInfo);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(WORK_PROFILE_USER_ID))).thenThrow(NameNotFoundException.class);
+ when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(
+ eq(mTestAppInfo.uid))).thenReturn(true);
+ mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE);
+
+ verify(mCameraManager).injectCamera(eq(TEST_APP_PACKAGE), eq(FRONT_CAMERA), anyString(),
+ any(), any());
+ }
+
+ @Test
+ public void multipleUsers_getPersonalProfileAppUid_noCameraBlocking()
+ throws CameraAccessException, NameNotFoundException {
+ mAliveUsers.add(new UserInfo(WORK_PROFILE_USER_ID, "", 0));
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(PERSONAL_PROFILE_USER_ID))).thenReturn(mTestAppInfo);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(WORK_PROFILE_USER_ID))).thenThrow(NameNotFoundException.class);
+ when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(
+ eq(mTestAppInfo.uid))).thenReturn(false);
+ mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE);
+
+ verify(mCameraManager, never()).injectCamera(any(), any(), any(), any(), any());
+ }
+
+ @Test
+ public void multipleUsers_getWorkProfileAppUid_cameraBlocked()
+ throws CameraAccessException, NameNotFoundException {
+ mAliveUsers.add(new UserInfo(WORK_PROFILE_USER_ID, "", 0));
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(PERSONAL_PROFILE_USER_ID))).thenThrow(NameNotFoundException.class);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(WORK_PROFILE_USER_ID))).thenReturn(mTestAppInfo);
+ when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(
+ eq(mTestAppInfo.uid))).thenReturn(true);
+ mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE);
+
+ verify(mCameraManager).injectCamera(eq(TEST_APP_PACKAGE), eq(FRONT_CAMERA), anyString(),
+ any(), any());
+ }
+
+ @Test
+ public void multipleUsers_getWorkProfileAppUid_noCameraBlocking()
+ throws CameraAccessException, NameNotFoundException {
+ mAliveUsers.add(new UserInfo(WORK_PROFILE_USER_ID, "", 0));
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(PERSONAL_PROFILE_USER_ID))).thenThrow(NameNotFoundException.class);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
+ eq(WORK_PROFILE_USER_ID))).thenReturn(mTestAppInfo);
+ when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(
+ eq(mTestAppInfo.uid))).thenReturn(false);
+ mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE);
+
+ verify(mCameraManager, never()).injectCamera(any(), any(), any(), any(), any());
+ }
}