Merge "Fixed camera streaming not being blocked when user taps camera on personal streaming apps" into tm-qpr-dev am: a4ae390f13
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19911205 Change-Id: I7ff8ecb73a46442aaa93300da8c2a84aecf43eec Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -22,14 +22,19 @@ import android.annotation.NonNull;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.hardware.camera2.CameraAccessException;
|
import android.hardware.camera2.CameraAccessException;
|
||||||
import android.hardware.camera2.CameraInjectionSession;
|
import android.hardware.camera2.CameraInjectionSession;
|
||||||
import android.hardware.camera2.CameraManager;
|
import android.hardware.camera2.CameraManager;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,6 +50,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
|
|||||||
private final CameraAccessBlockedCallback mBlockedCallback;
|
private final CameraAccessBlockedCallback mBlockedCallback;
|
||||||
private final CameraManager mCameraManager;
|
private final CameraManager mCameraManager;
|
||||||
private final PackageManager mPackageManager;
|
private final PackageManager mPackageManager;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private int mObserverCount = 0;
|
private int mObserverCount = 0;
|
||||||
@@ -66,7 +72,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
|
|||||||
|
|
||||||
static class OpenCameraInfo {
|
static class OpenCameraInfo {
|
||||||
public String packageName;
|
public String packageName;
|
||||||
public int packageUid;
|
public Set<Integer> packageUids;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CameraAccessBlockedCallback {
|
interface CameraAccessBlockedCallback {
|
||||||
@@ -85,6 +91,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
|
|||||||
mBlockedCallback = blockedCallback;
|
mBlockedCallback = blockedCallback;
|
||||||
mCameraManager = mContext.getSystemService(CameraManager.class);
|
mCameraManager = mContext.getSystemService(CameraManager.class);
|
||||||
mPackageManager = mContext.getPackageManager();
|
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++) {
|
for (int i = 0; i < mAppsToBlockOnVirtualDevice.size(); i++) {
|
||||||
final String cameraId = mAppsToBlockOnVirtualDevice.keyAt(i);
|
final String cameraId = mAppsToBlockOnVirtualDevice.keyAt(i);
|
||||||
final OpenCameraInfo openCameraInfo = mAppsToBlockOnVirtualDevice.get(cameraId);
|
final OpenCameraInfo openCameraInfo = mAppsToBlockOnVirtualDevice.get(cameraId);
|
||||||
int packageUid = openCameraInfo.packageUid;
|
final String packageName = openCameraInfo.packageName;
|
||||||
if (runningUids.contains(packageUid)) {
|
for (int packageUid : openCameraInfo.packageUids) {
|
||||||
final String packageName = openCameraInfo.packageName;
|
if (runningUids.contains(packageUid)) {
|
||||||
InjectionSessionData data = mPackageToSessionData.get(packageName);
|
InjectionSessionData data = mPackageToSessionData.get(packageName);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = new InjectionSessionData();
|
data = new InjectionSessionData();
|
||||||
data.appUid = packageUid;
|
data.appUid = packageUid;
|
||||||
mPackageToSessionData.put(packageName, data);
|
mPackageToSessionData.put(packageName, data);
|
||||||
|
}
|
||||||
|
startBlocking(packageName, cameraId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
startBlocking(packageName, cameraId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,37 +164,41 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
|
|||||||
@Override
|
@Override
|
||||||
public void onCameraOpened(@NonNull String cameraId, @NonNull String packageName) {
|
public void onCameraOpened(@NonNull String cameraId, @NonNull String packageName) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
InjectionSessionData data = mPackageToSessionData.get(packageName);
|
||||||
final ApplicationInfo ainfo = mPackageManager.getApplicationInfo(packageName, 0);
|
List<UserInfo> aliveUsers = mUserManager.getAliveUsers();
|
||||||
InjectionSessionData data = mPackageToSessionData.get(packageName);
|
ArraySet<Integer> packageUids = new ArraySet<>();
|
||||||
if (!mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(ainfo.uid)) {
|
for (UserInfo user : aliveUsers) {
|
||||||
OpenCameraInfo openCameraInfo = new OpenCameraInfo();
|
int userId = user.getUserHandle().getIdentifier();
|
||||||
openCameraInfo.packageName = packageName;
|
int appUid = queryUidFromPackageName(userId, packageName);
|
||||||
openCameraInfo.packageUid = ainfo.uid;
|
if (mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(appUid)) {
|
||||||
mAppsToBlockOnVirtualDevice.put(cameraId, openCameraInfo);
|
if (data == null) {
|
||||||
CameraInjectionSession existingSession =
|
data = new InjectionSessionData();
|
||||||
(data != null) ? data.cameraIdToSession.get(cameraId) : null;
|
data.appUid = appUid;
|
||||||
if (existingSession != null) {
|
mPackageToSessionData.put(packageName, data);
|
||||||
existingSession.close();
|
|
||||||
data.cameraIdToSession.remove(cameraId);
|
|
||||||
if (data.cameraIdToSession.isEmpty()) {
|
|
||||||
mPackageToSessionData.remove(packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (data.cameraIdToSession.containsKey(cameraId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startBlocking(packageName, cameraId);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
if (appUid != Process.INVALID_UID) {
|
||||||
|
packageUids.add(appUid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (data == null) {
|
}
|
||||||
data = new InjectionSessionData();
|
OpenCameraInfo openCameraInfo = new OpenCameraInfo();
|
||||||
data.appUid = ainfo.uid;
|
openCameraInfo.packageName = packageName;
|
||||||
mPackageToSessionData.put(packageName, data);
|
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);
|
||||||
}
|
}
|
||||||
if (data.cameraIdToSession.containsKey(cameraId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,13 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
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.CameraAccessException;
|
||||||
import android.hardware.camera2.CameraInjectionSession;
|
import android.hardware.camera2.CameraInjectionSession;
|
||||||
import android.hardware.camera2.CameraManager;
|
import android.hardware.camera2.CameraManager;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.testing.TestableContext;
|
import android.testing.TestableContext;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
|
||||||
@@ -51,12 +54,17 @@ import org.mockito.Captor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class CameraAccessControllerTest {
|
public class CameraAccessControllerTest {
|
||||||
private static final String FRONT_CAMERA = "0";
|
private static final String FRONT_CAMERA = "0";
|
||||||
private static final String REAR_CAMERA = "1";
|
private static final String REAR_CAMERA = "1";
|
||||||
private static final String TEST_APP_PACKAGE = "some.package";
|
private static final String TEST_APP_PACKAGE = "some.package";
|
||||||
private static final String OTHER_APP_PACKAGE = "other.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;
|
private CameraAccessController mController;
|
||||||
|
|
||||||
@@ -69,6 +77,8 @@ public class CameraAccessControllerTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private PackageManager mPackageManager;
|
private PackageManager mPackageManager;
|
||||||
@Mock
|
@Mock
|
||||||
|
private UserManager mUserManager;
|
||||||
|
@Mock
|
||||||
private VirtualDeviceManagerInternal mDeviceManagerInternal;
|
private VirtualDeviceManagerInternal mDeviceManagerInternal;
|
||||||
@Mock
|
@Mock
|
||||||
private CameraAccessController.CameraAccessBlockedCallback mBlockedCallback;
|
private CameraAccessController.CameraAccessBlockedCallback mBlockedCallback;
|
||||||
@@ -76,6 +86,7 @@ public class CameraAccessControllerTest {
|
|||||||
private ApplicationInfo mTestAppInfo = new ApplicationInfo();
|
private ApplicationInfo mTestAppInfo = new ApplicationInfo();
|
||||||
private ApplicationInfo mOtherAppInfo = new ApplicationInfo();
|
private ApplicationInfo mOtherAppInfo = new ApplicationInfo();
|
||||||
private ArraySet<Integer> mRunningUids = new ArraySet<>();
|
private ArraySet<Integer> mRunningUids = new ArraySet<>();
|
||||||
|
private List<UserInfo> mAliveUsers = new ArrayList<>();
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
ArgumentCaptor<CameraInjectionSession.InjectionStatusCallback> mInjectionCallbackCaptor;
|
ArgumentCaptor<CameraInjectionSession.InjectionStatusCallback> mInjectionCallbackCaptor;
|
||||||
@@ -84,6 +95,7 @@ public class CameraAccessControllerTest {
|
|||||||
public void setUp() throws PackageManager.NameNotFoundException {
|
public void setUp() throws PackageManager.NameNotFoundException {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext.addMockSystemService(CameraManager.class, mCameraManager);
|
mContext.addMockSystemService(CameraManager.class, mCameraManager);
|
||||||
|
mContext.addMockSystemService(UserManager.class, mUserManager);
|
||||||
mContext.setMockPackageManager(mPackageManager);
|
mContext.setMockPackageManager(mPackageManager);
|
||||||
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
|
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
|
||||||
LocalServices.addService(VirtualDeviceManagerInternal.class, mDeviceManagerInternal);
|
LocalServices.addService(VirtualDeviceManagerInternal.class, mDeviceManagerInternal);
|
||||||
@@ -92,10 +104,14 @@ public class CameraAccessControllerTest {
|
|||||||
mTestAppInfo.uid = Process.FIRST_APPLICATION_UID;
|
mTestAppInfo.uid = Process.FIRST_APPLICATION_UID;
|
||||||
mOtherAppInfo.uid = Process.FIRST_APPLICATION_UID + 1;
|
mOtherAppInfo.uid = Process.FIRST_APPLICATION_UID + 1;
|
||||||
mRunningUids.add(Process.FIRST_APPLICATION_UID);
|
mRunningUids.add(Process.FIRST_APPLICATION_UID);
|
||||||
when(mPackageManager.getApplicationInfo(eq(TEST_APP_PACKAGE), anyInt())).thenReturn(
|
mAliveUsers.add(new UserInfo(PERSONAL_PROFILE_USER_ID, "", 0));
|
||||||
mTestAppInfo);
|
when(mPackageManager.getApplicationInfoAsUser(
|
||||||
when(mPackageManager.getApplicationInfo(eq(OTHER_APP_PACKAGE), anyInt())).thenReturn(
|
eq(TEST_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
|
||||||
mOtherAppInfo);
|
anyInt())).thenReturn(mTestAppInfo);
|
||||||
|
when(mPackageManager.getApplicationInfoAsUser(
|
||||||
|
eq(OTHER_APP_PACKAGE), eq(PackageManager.GET_ACTIVITIES),
|
||||||
|
anyInt())).thenReturn(mOtherAppInfo);
|
||||||
|
when(mUserManager.getAliveUsers()).thenReturn(mAliveUsers);
|
||||||
mController.startObservingIfNeeded();
|
mController.startObservingIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,4 +243,74 @@ public class CameraAccessControllerTest {
|
|||||||
|
|
||||||
verify(mCameraManager, times(1)).injectCamera(any(), any(), any(), any(), any());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user