Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4ae390f authored by Cliff Wu's avatar Cliff Wu Committed by Android (Google) Code Review
Browse files

Merge "Fixed camera streaming not being blocked when user taps camera on...

Merge "Fixed camera streaming not being blocked when user taps camera on personal streaming apps" into tm-qpr-dev
parents 5bca0e00 a120143a
Loading
Loading
Loading
Loading
+62 −37
Original line number Diff line number Diff line
@@ -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,9 +132,9 @@ 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;
                for (int packageUid : openCameraInfo.packageUids) {
                    if (runningUids.contains(packageUid)) {
                        InjectionSessionData data = mPackageToSessionData.get(packageName);
                        if (data == null) {
                            data = new InjectionSessionData();
@@ -135,6 +142,8 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
                            mPackageToSessionData.put(packageName, data);
                        }
                        startBlocking(packageName, cameraId);
                        break;
                    }
                }
            }
        }
@@ -155,13 +164,32 @@ 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)) {
            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);
                    }
                }
            }
            OpenCameraInfo openCameraInfo = new OpenCameraInfo();
            openCameraInfo.packageName = packageName;
                    openCameraInfo.packageUid = ainfo.uid;
            openCameraInfo.packageUids = packageUids;
            mAppsToBlockOnVirtualDevice.put(cameraId, openCameraInfo);
            CameraInjectionSession existingSession =
                    (data != null) ? data.cameraIdToSession.get(cameraId) : null;
@@ -172,21 +200,6 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
                    mPackageToSessionData.remove(packageName);
                }
            }
                    return;
                }
                if (data == null) {
                    data = new InjectionSessionData();
                    data.appUid = ainfo.uid;
                    mPackageToSessionData.put(packageName, data);
                }
                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;
        }
    }
}
+90 −4
Original line number Diff line number Diff line
@@ -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());
    }
}