When setting camera, ensure calling user is the same as logged in user.

When the VideoProvider API is used to change the camera, in addition to
performing permission checks on the caller, adding logic to ensure that
the calling UserHandle is the currently logged in User (this is to ensure
that a background app can't access the camera).

Test: Unit, manual
Bug: 32747443
Change-Id: I0856f991c520dd1f5fa0146919941c052cba8a01
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 4e33482..87b460e 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.telecom.Connection;
 import android.telecom.InCallService;
 import android.telecom.Log;
@@ -88,6 +89,11 @@
      */
     private Call mCall;
 
+    /**
+     * Interface providing access to the currently logged in user.
+     */
+    private CurrentUserProxy mCurrentUserProxy;
+
     private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
         @Override
         public void binderDied() {
@@ -106,7 +112,8 @@
      * @throws RemoteException Remote exception.
      */
     VideoProviderProxy(TelecomSystem.SyncRoot lock,
-            IVideoProvider videoProvider, Call call) throws RemoteException {
+            IVideoProvider videoProvider, Call call, CurrentUserProxy currentUserProxy)
+            throws RemoteException {
 
         super(Looper.getMainLooper());
 
@@ -118,6 +125,7 @@
         mVideoCallListenerBinder = new VideoCallListenerBinder();
         mConectionServiceVideoProvider.addVideoCallback(mVideoCallListenerBinder);
         mCall = call;
+        mCurrentUserProxy = currentUserProxy;
     }
 
     /**
@@ -301,13 +309,15 @@
     public void onSetCamera(String cameraId, String callingPackage, int callingUid,
             int callingPid) {
         synchronized (mLock) {
-            logFromInCall("setCamera: " + cameraId + " callingPackage=" + callingPackage);
+            logFromInCall("setCamera: " + cameraId + " callingPackage=" + callingPackage +
+                    "; callingUid=" + callingUid);
 
             if (!TextUtils.isEmpty(cameraId)) {
                 if (!canUseCamera(mCall.getContext(), callingPackage, callingUid, callingPid)) {
                     // Calling app is not permitted to use the camera.  Ignore the request and send
                     // back a call session event indicating the error.
-                    Log.i(this, "onSetCamera: camera permission denied; package=%d, uid=%d, pid=%d",
+                    Log.i(this, "onSetCamera: camera permission denied; package=%d, uid=%d, "
+                            + "pid=%d",
                             callingPackage, callingUid, callingPid);
                     VideoProviderProxy.this.handleCallSessionEvent(
                             Connection.VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR);
@@ -529,11 +539,20 @@
      * @param context The context.
      * @param callingPackage The package name of the caller (i.e. Dialer).
      * @param callingUid The UID of the caller.
+     * @param callingPid The PID of the caller.
      * @return {@code true} if the calling uid and package can use the camera, {@code false}
      *      otherwise.
      */
     private boolean canUseCamera(Context context, String callingPackage, int callingUid,
             int callingPid) {
+
+        UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
+        UserHandle currentUserHandle = mCurrentUserProxy.getCurrentUserHandle();
+        if (currentUserHandle != null && !currentUserHandle.equals(callingUser)) {
+            Log.w(this, "canUseCamera attempt to user camera by background user.");
+            return false;
+        }
+
         try {
             context.enforcePermission(Manifest.permission.CAMERA, callingPid, callingUid,
                     "Camera permission required.");
@@ -549,7 +568,7 @@
             return appOpsManager != null && appOpsManager.noteOp(AppOpsManager.OP_CAMERA,
                     callingUid, callingPackage) == AppOpsManager.MODE_ALLOWED;
         } catch (SecurityException se) {
-            Log.w(this, "canUserCamera got appOpps Exception " + se.toString());
+            Log.w(this, "canUseCamera got appOpps Exception " + se.toString());
             return false;
         }
     }