CameraService and Stagefright: Support AppOps

Camera:
- Signal to AppOpsService when camera usage starts and stops
- Listen to permissions revocations and act on them
- Currently just kill camera connection when permissions lost

Stagefright:
- Pass on client name, UID to camera as needed

Bug: 8181262
Change-Id: I9e33c9d05e9daa77dbb2d795045d08eb887ec8f0
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index fdbc747..c935d97 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -51,7 +51,8 @@
     SET_PARAMETERS,
     SET_PREVIEW_SURFACE,
     SET_CAMERA,
-    SET_LISTENER
+    SET_LISTENER,
+    SET_CLIENT_NAME
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -217,6 +218,16 @@
         return reply.readInt32();
     }
 
+    status_t setClientName(const String16& clientName)
+    {
+        ALOGV("setClientName(%s)", String8(clientName).string());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeString16(clientName);
+        remote()->transact(SET_CLIENT_NAME, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t prepare()
     {
         ALOGV("prepare");
@@ -423,6 +434,12 @@
             reply->writeInt32(setListener(listener));
             return NO_ERROR;
         } break;
+        case SET_CLIENT_NAME: {
+            ALOGV("SET_CLIENT_NAME");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(setClientName(data.readString16()));
+            return NO_ERROR;
+        }
         case SET_PREVIEW_SURFACE: {
             ALOGV("SET_PREVIEW_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 660b1b2..3ac98cc 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -656,6 +656,27 @@
     return NO_ERROR;
 }
 
+status_t MediaRecorder::setClientName(const String16& clientName)
+{
+    ALOGV("setClientName");
+    if (mMediaRecorder == NULL) {
+        ALOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    bool isInvalidState = (mCurrentState &
+                           (MEDIA_RECORDER_PREPARED |
+                            MEDIA_RECORDER_RECORDING |
+                            MEDIA_RECORDER_ERROR));
+    if (isInvalidState) {
+        ALOGE("setClientName is called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    mMediaRecorder->setClientName(clientName);
+
+    return NO_ERROR;
+}
+
 void MediaRecorder::notify(int msg, int ext1, int ext2)
 {
     ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index c6d8b76..a52b238 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -99,7 +99,7 @@
         return PERMISSION_DENIED;
     }
     Mutex::Autolock lock(mLock);
-    if (mRecorder == NULL)	{
+    if (mRecorder == NULL)     {
         ALOGE("recorder is not initialized");
         return NO_INIT;
     }
@@ -325,6 +325,16 @@
     return mRecorder->setListener(listener);
 }
 
+status_t MediaRecorderClient::setClientName(const String16& clientName) {
+    ALOGV("setClientName(%s)", String8(clientName).string());
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        ALOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setClientName(clientName);
+}
+
 status_t MediaRecorderClient::dump(int fd, const Vector<String16>& args) const {
     if (mRecorder != NULL) {
         return mRecorder->dump(fd, args);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 5623917..bd0eaf1 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -46,6 +46,7 @@
     virtual     status_t   setParameters(const String8& params);
     virtual     status_t   setListener(
                               const sp<IMediaRecorderClient>& listener);
+    virtual     status_t   setClientName(const String16& clientName);
     virtual     status_t   prepare();
     virtual     status_t   getMaxAmplitude(int* max);
     virtual     status_t   start();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 497dda6..f570856 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -730,6 +730,12 @@
     return OK;
 }
 
+status_t StagefrightRecorder::setClientName(const String16& clientName) {
+    mClientName = clientName;
+
+    return OK;
+}
+
 status_t StagefrightRecorder::prepare() {
     return OK;
 }
@@ -737,6 +743,8 @@
 status_t StagefrightRecorder::start() {
     CHECK_GE(mOutputFd, 0);
 
+    // Get UID here for permission checking
+    mClientUid = IPCThreadState::self()->getCallingUid();
     if (mWriter != NULL) {
         ALOGE("File writer is not avaialble");
         return UNKNOWN_ERROR;
@@ -1312,13 +1320,14 @@
         }
 
         mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
-                mCamera, mCameraProxy, mCameraId,
+                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
                 videoSize, mFrameRate, mPreviewSurface,
                 mTimeBetweenTimeLapseFrameCaptureUs);
         *cameraSource = mCameraSourceTimeLapse;
     } else {
         *cameraSource = CameraSource::CreateFromCamera(
-                mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
+                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
+                videoSize, mFrameRate,
                 mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
     }
     mCamera.clear();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 351efd4..fbe6fa6 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -56,6 +56,7 @@
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
+    virtual status_t setClientName(const String16& clientName);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t pause();
@@ -72,6 +73,8 @@
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<Surface> mPreviewSurface;
     sp<IMediaRecorderClient> mListener;
+    String16 mClientName;
+    uid_t mClientUid;
     sp<MediaWriter> mWriter;
     int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index efd7af7..f8557d0 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -121,13 +121,14 @@
     CHECK(!"Unknown color format");
 }
 
-CameraSource *CameraSource::Create() {
+CameraSource *CameraSource::Create(const String16 &clientName) {
     Size size;
     size.width = -1;
     size.height = -1;
 
     sp<ICamera> camera;
-    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
+    return new CameraSource(camera, NULL, 0, clientName, -1,
+            size, -1, NULL, false);
 }
 
 // static
@@ -135,14 +136,16 @@
     const sp<ICamera>& camera,
     const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
+    const String16& clientName,
+    uid_t clientUid,
     Size videoSize,
     int32_t frameRate,
     const sp<Surface>& surface,
     bool storeMetaDataInVideoBuffers) {
 
     CameraSource *source = new CameraSource(camera, proxy, cameraId,
-                    videoSize, frameRate, surface,
-                    storeMetaDataInVideoBuffers);
+            clientName, clientUid, videoSize, frameRate, surface,
+            storeMetaDataInVideoBuffers);
     return source;
 }
 
@@ -150,6 +153,8 @@
     const sp<ICamera>& camera,
     const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
+    const String16& clientName,
+    uid_t clientUid,
     Size videoSize,
     int32_t frameRate,
     const sp<Surface>& surface,
@@ -173,6 +178,7 @@
     mVideoSize.height = -1;
 
     mInitCheck = init(camera, proxy, cameraId,
+                    clientName, clientUid,
                     videoSize, frameRate,
                     storeMetaDataInVideoBuffers);
     if (mInitCheck != OK) releaseCamera();
@@ -184,10 +190,10 @@
 
 status_t CameraSource::isCameraAvailable(
     const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
-    int32_t cameraId) {
+    int32_t cameraId, const String16& clientName, uid_t clientUid) {
 
     if (camera == 0) {
-        mCamera = Camera::connect(cameraId);
+        mCamera = Camera::connect(cameraId, clientName, clientUid);
         if (mCamera == 0) return -EBUSY;
         mCameraFlags &= ~FLAGS_HOT_CAMERA;
     } else {
@@ -469,6 +475,8 @@
         const sp<ICamera>& camera,
         const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
+        const String16& clientName,
+        uid_t clientUid,
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
@@ -476,7 +484,7 @@
     ALOGV("init");
     status_t err = OK;
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    err = initWithCameraAccess(camera, proxy, cameraId,
+    err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid,
                                videoSize, frameRate,
                                storeMetaDataInVideoBuffers);
     IPCThreadState::self()->restoreCallingIdentity(token);
@@ -487,13 +495,16 @@
         const sp<ICamera>& camera,
         const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
+        const String16& clientName,
+        uid_t clientUid,
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
     ALOGV("initWithCameraAccess");
     status_t err = OK;
 
-    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+    if ((err = isCameraAvailable(camera, proxy, cameraId,
+            clientName, clientUid)) != OK) {
         ALOGE("Camera connection could not be established.");
         return err;
     }
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 26ce7ae..2ed2223 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -36,6 +36,8 @@
         const sp<ICamera> &camera,
         const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
+        const String16& clientName,
+        uid_t clientUid,
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
@@ -43,6 +45,7 @@
 
     CameraSourceTimeLapse *source = new
             CameraSourceTimeLapse(camera, proxy, cameraId,
+                clientName, clientUid,
                 videoSize, videoFrameRate, surface,
                 timeBetweenFrameCaptureUs);
 
@@ -59,11 +62,14 @@
         const sp<ICamera>& camera,
         const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
+        const String16& clientName,
+        uid_t clientUid,
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
         int64_t timeBetweenFrameCaptureUs)
-    : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
+      : CameraSource(camera, proxy, cameraId, clientName, clientUid,
+                videoSize, videoFrameRate, surface, true),
       mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
       mLastTimeLapseFrameRealTimestampUs(0),
       mSkipCurrentFrame(false) {