summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/Camera.cpp6
-rw-r--r--camera/ICameraService.cpp14
-rw-r--r--cmds/stagefright/record.cpp3
-rw-r--r--include/camera/Camera.h10
-rw-r--r--include/camera/ICameraService.h20
-rw-r--r--include/media/IMediaRecorder.h1
-rw-r--r--include/media/MediaRecorderBase.h1
-rw-r--r--include/media/mediarecorder.h1
-rw-r--r--include/media/stagefright/CameraSource.h28
-rw-r--r--include/media/stagefright/CameraSourceTimeLapse.h5
-rw-r--r--media/libmedia/IMediaRecorder.cpp19
-rw-r--r--media/libmedia/mediarecorder.cpp21
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp12
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h1
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp13
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h3
-rw-r--r--media/libstagefright/CameraSource.cpp27
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp8
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp15
-rw-r--r--services/camera/libcameraservice/Camera2Client.h2
-rw-r--r--services/camera/libcameraservice/CameraClient.cpp18
-rw-r--r--services/camera/libcameraservice/CameraClient.h2
-rw-r--r--services/camera/libcameraservice/CameraService.cpp171
-rw-r--r--services/camera/libcameraservice/CameraService.h57
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.cpp6
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.h2
26 files changed, 388 insertions, 78 deletions
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index be395ba..d8dc2a5 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -19,6 +19,7 @@
#define LOG_TAG "Camera"
#include <utils/Log.h>
#include <utils/threads.h>
+#include <utils/String16.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
@@ -116,14 +117,15 @@ status_t Camera::getCameraInfo(int cameraId,
return cs->getCameraInfo(cameraId, cameraInfo);
}
-sp<Camera> Camera::connect(int cameraId)
+sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
+ int clientUid)
{
ALOGV("connect");
sp<Camera> c = new Camera();
sp<ICameraClient> cl = c;
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
- c->mCamera = cs->connect(cl, cameraId);
+ c->mCamera = cs->connect(cl, cameraId, clientPackageName, clientUid);
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 8237c66..fdf20ff 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -56,12 +56,15 @@ public:
}
// connect to camera service
- virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
+ const String16 &clientPackageName, int clientUid)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(cameraClient->asBinder());
data.writeInt32(cameraId);
+ data.writeString16(clientPackageName);
+ data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT, data, &reply);
return interface_cast<ICamera>(reply.readStrongBinder());
}
@@ -103,8 +106,13 @@ status_t BnCameraService::onTransact(
} break;
case CONNECT: {
CHECK_INTERFACE(ICameraService, data, reply);
- sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
- sp<ICamera> camera = connect(cameraClient, data.readInt32());
+ sp<ICameraClient> cameraClient =
+ interface_cast<ICameraClient>(data.readStrongBinder());
+ int32_t cameraId = data.readInt32();
+ const String16 clientName = data.readString16();
+ int32_t clientUid = data.readInt32();
+ sp<ICamera> camera = connect(cameraClient, cameraId,
+ clientName, clientUid);
reply->writeStrongBinder(camera->asBinder());
return NO_ERROR;
} break;
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 45c3f7b..b7a40c2 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -264,7 +264,8 @@ int main(int argc, char **argv) {
#endif
#if 0
- CameraSource *source = CameraSource::Create();
+ CameraSource *source = CameraSource::Create(
+ String16(argv[0], strlen(argv[0])));
source->start();
printf("source = %p\n", source);
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 8b87de6..be2b7f4 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -53,6 +53,7 @@ class ICamera;
class Surface;
class Mutex;
class String8;
+class String16;
// ref-counted object for callbacks
class CameraListener: virtual public RefBase
@@ -67,12 +68,19 @@ public:
class Camera : public BnCameraClient, public IBinder::DeathRecipient
{
public:
+ enum {
+ USE_CALLING_UID = -1
+ };
+
// construct a camera client from an existing remote
static sp<Camera> create(const sp<ICamera>& camera);
static int32_t getNumberOfCameras();
static status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo);
- static sp<Camera> connect(int cameraId);
+ static sp<Camera> connect(int cameraId,
+ const String16& clientPackageName,
+ int clientUid);
+
virtual ~Camera();
void init();
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 11d7b65..aa64243 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -37,18 +37,28 @@ public:
CONNECT_PRO
};
+ enum {
+ USE_CALLING_UID = -1
+ };
+
public:
DECLARE_META_INTERFACE(CameraService);
virtual int32_t getNumberOfCameras() = 0;
virtual status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo) = 0;
- virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient,
- int cameraId) = 0;
+ /**
+ * clientPackageName and clientUid are used for permissions checking. if
+ * clientUid == USE_CALLING_UID, then the calling UID is used instead. Only
+ * trusted callers can set a clientUid other than USE_CALLING_UID.
+ */
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient,
+ int cameraId,
+ const String16& clientPackageName,
+ int clientUid) = 0;
- virtual sp<IProCameraUser>
- connect(const sp<IProCameraCallbacks>& cameraCb,
- int cameraId) = 0;
+ virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb,
+ int cameraId) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 54af0d3..8d7f11d 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -47,6 +47,7 @@ public:
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t setClientName(const String16& clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t getMaxAmplitude(int* max) = 0;
virtual status_t start() = 0;
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 803bc64..8dd40d2 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -48,6 +48,7 @@ struct MediaRecorderBase {
virtual status_t setOutputFileAuxiliary(int fd) {return INVALID_OPERATION;}
virtual status_t setParameters(const String8& params) = 0;
virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t setClientName(const String16& clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index da6b507..3b33479 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -219,6 +219,7 @@ public:
status_t setVideoFrameRate(int frames_per_second);
status_t setParameters(const String8& params);
status_t setListener(const sp<MediaRecorderListener>& listener);
+ status_t setClientName(const String16& clientName);
status_t prepare();
status_t getMaxAmplitude(int* max);
status_t start();
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 6d6b8a9..cf38b14 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -25,6 +25,7 @@
#include <camera/CameraParameters.h>
#include <utils/List.h>
#include <utils/RefBase.h>
+#include <utils/String16.h>
namespace android {
@@ -39,9 +40,11 @@ public:
* settings (such as video size, frame rate, color format, etc)
* from the default camera.
*
+ * @param clientName The package/process name of the client application.
+ * This is used for permissions checking.
* @return NULL on error.
*/
- static CameraSource *Create();
+ static CameraSource *Create(const String16 &clientName);
/**
* Factory method to create a new CameraSource.
@@ -52,7 +55,11 @@ public:
*
* @param cameraId the id of the camera that the source will connect
* to if camera is NULL; otherwise ignored.
- *
+ * @param clientName the package/process name of the camera-using
+ * application if camera is NULL; otherwise ignored. Used for
+ * permissions checking.
+ * @param clientUid the UID of the camera-using application if camera is
+ * NULL; otherwise ignored. Used for permissions checking.
* @param videoSize the dimension (in pixels) of the video frame
* @param frameRate the target frames per second
* @param surface the preview surface for display where preview
@@ -71,6 +78,8 @@ public:
static CameraSource *CreateFromCamera(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,
@@ -158,7 +167,7 @@ protected:
int64_t mTimeBetweenFrameCaptureUs;
CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId,
+ int32_t cameraId, const String16& clientName, uid_t clientUid,
Size videoSize, int32_t frameRate,
const sp<Surface>& surface,
bool storeMetaDataInVideoBuffers);
@@ -198,17 +207,20 @@ private:
status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, Size videoSize, int32_t frameRate,
- bool storeMetaDataInVideoBuffers);
+ int32_t cameraId, const String16& clientName, uid_t clientUid,
+ Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
status_t initWithCameraAccess(
const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, Size videoSize, int32_t frameRate,
- bool storeMetaDataInVideoBuffers);
+ int32_t cameraId, const String16& clientName, uid_t clientUid,
+ Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
status_t isCameraAvailable(const sp<ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId);
+ int32_t cameraId,
+ const String16& clientName,
+ uid_t clientUid);
+
status_t isCameraColorFormatSupported(const CameraParameters& params);
status_t configureCamera(CameraParameters* params,
int32_t width, int32_t height,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0936da2..774772b 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -22,6 +22,7 @@
#include <utils/RefBase.h>
#include <utils/threads.h>
+#include <utils/String16.h>
namespace android {
@@ -35,6 +36,8 @@ public:
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,
@@ -108,6 +111,8 @@ private:
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,
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 @@ enum {
SET_PARAMETERS,
SET_PREVIEW_SURFACE,
SET_CAMERA,
- SET_LISTENER
+ SET_LISTENER,
+ SET_CLIENT_NAME
};
class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -217,6 +218,16 @@ public:
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 @@ status_t BnMediaRecorder::onTransact(
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 @@ status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
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 @@ status_t MediaRecorderClient::setVideoSource(int vs)
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 @@ status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listen
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 @@ public:
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 @@ status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listen
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::prepare() {
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 @@ status_t StagefrightRecorder::setupCameraSource(
}
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 @@ struct StagefrightRecorder : public MediaRecorderBase {
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 @@ private:
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 @@ static int32_t getColorFormat(const char* colorFormat) {
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 @@ CameraSource *CameraSource::CreateFromCamera(
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 @@ CameraSource::CameraSource(
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 @@ CameraSource::CameraSource(
mVideoSize.height = -1;
mInitCheck = init(camera, proxy, cameraId,
+ clientName, clientUid,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
if (mInitCheck != OK) releaseCamera();
@@ -184,10 +190,10 @@ status_t CameraSource::initCheck() const {
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 @@ status_t CameraSource::init(
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 @@ status_t CameraSource::init(
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 @@ status_t CameraSource::initWithCameraAccess(
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 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
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 *CameraSourceTimeLapse::CreateFromCamera(
CameraSourceTimeLapse *source = new
CameraSourceTimeLapse(camera, proxy, cameraId,
+ clientName, clientUid,
videoSize, videoFrameRate, surface,
timeBetweenFrameCaptureUs);
@@ -59,11 +62,14 @@ CameraSourceTimeLapse::CameraSourceTimeLapse(
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) {
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index e8b3b7f..38d6949 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -40,12 +40,14 @@ static int getCallingPid() {
Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid):
- Client(cameraService, cameraClient,
- cameraId, cameraFacing, clientPid, servicePid),
+ Client(cameraService, cameraClient, clientPackageName,
+ cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraClient(cameraClient),
mParameters(cameraId, cameraFacing)
{
@@ -73,6 +75,12 @@ status_t Camera2Client::initialize(camera_module_t *module)
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
+ // Verify ops permissions
+ res = startCameraOps();
+ if (res != OK) {
+ return res;
+ }
+
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
@@ -741,8 +749,7 @@ void Camera2Client::stopPreviewL() {
switch (state) {
case Parameters::DISCONNECTED:
- ALOGE("%s: Camera %d: Call before initialized",
- __FUNCTION__, mCameraId);
+ // Nothing to do.
break;
case Parameters::STOPPED:
case Parameters::VIDEO_SNAPSHOT:
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index a4d4478..173b65e 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -72,9 +72,11 @@ public:
Camera2Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid);
virtual ~Camera2Client();
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index f67c9f4..90f8f40 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -35,9 +35,12 @@ static int getCallingPid() {
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- int cameraId, int cameraFacing, int clientPid, int servicePid):
- Client(cameraService, cameraClient,
- cameraId, cameraFacing, clientPid, servicePid)
+ const String16& clientPackageName,
+ int cameraId, int cameraFacing,
+ int clientPid, int clientUid,
+ int servicePid):
+ Client(cameraService, cameraClient, clientPackageName,
+ cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
int callingPid = getCallingPid();
LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
@@ -57,10 +60,17 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService,
status_t CameraClient::initialize(camera_module_t *module) {
int callingPid = getCallingPid();
+ status_t res;
+
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
+ // Verify ops permissions
+ res = startCameraOps();
+ if (res != OK) {
+ return res;
+ }
+
char camera_device_name[10];
- status_t res;
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h
index 74829ce..00dc90c 100644
--- a/services/camera/libcameraservice/CameraClient.h
+++ b/services/camera/libcameraservice/CameraClient.h
@@ -53,9 +53,11 @@ public:
// Interface used by CameraService
CameraClient(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ int clientUid,
int servicePid);
~CameraClient();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index eb8bc05..ec1c3f0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <pthread.h>
+#include <binder/AppOpsManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryBase.h>
@@ -72,7 +73,7 @@ static int getCallingUid() {
static CameraService *gCameraService;
CameraService::CameraService()
-:mSoundRef(0), mModule(0)
+ :mSoundRef(0), mModule(0)
{
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
@@ -155,10 +156,27 @@ int CameraService::getDeviceVersion(int cameraId, int* facing) {
}
sp<ICamera> CameraService::connect(
- const sp<ICameraClient>& cameraClient, int cameraId) {
+ const sp<ICameraClient>& cameraClient,
+ int cameraId,
+ const String16& clientPackageName,
+ int clientUid) {
+
+ String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
- LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
+ LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
+ clientName8.string(), cameraId);
+
+ if (clientUid == USE_CALLING_UID) {
+ clientUid = getCallingUid();
+ } else {
+ // We only trust our own process to forward client UIDs
+ if (callingPid != getpid()) {
+ ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)",
+ callingPid);
+ return NULL;
+ }
+ }
if (!mModule) {
ALOGE("Camera HAL module not loaded");
@@ -208,8 +226,10 @@ sp<ICamera> CameraService::connect(
would be fine
*/
if (mBusy[cameraId]) {
- ALOGW("CameraService::connect X (pid %d) rejected"
- " (camera %d is still busy).", callingPid, cameraId);
+
+ ALOGW("CameraService::connect X (pid %d, \"%s\") rejected"
+ " (camera %d is still busy).", callingPid,
+ clientName8.string(), cameraId);
return NULL;
}
@@ -218,13 +238,15 @@ sp<ICamera> CameraService::connect(
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
- client = new CameraClient(this, cameraClient, cameraId,
- facing, callingPid, getpid());
+ client = new CameraClient(this, cameraClient,
+ clientPackageName, cameraId,
+ facing, callingPid, clientUid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
- client = new Camera2Client(this, cameraClient, cameraId,
- facing, callingPid, getpid());
+ client = new Camera2Client(this, cameraClient,
+ clientPackageName, cameraId,
+ facing, callingPid, clientUid, getpid());
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
@@ -283,8 +305,8 @@ sp<IProCameraUser> CameraService::connect(
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
- client = new ProCamera2Client(this, cameraCb, cameraId,
- facing, callingPid, getpid());
+ client = new ProCamera2Client(this, cameraCb, String16(),
+ cameraId, facing, callingPid, USE_CALLING_UID, getpid());
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
@@ -302,7 +324,8 @@ sp<IProCameraUser> CameraService::connect(
cameraCb->asBinder()->linkToDeath(this);
- LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
+ LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
+ getpid());
return client;
@@ -522,10 +545,15 @@ void CameraService::playSound(sound_kind kind) {
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- int cameraId, int cameraFacing, int clientPid, int servicePid) :
+ const String16& clientPackageName,
+ int cameraId, int cameraFacing,
+ int clientPid, uid_t clientUid,
+ int servicePid) :
CameraService::BasicClient(cameraService, cameraClient->asBinder(),
- cameraId, cameraFacing,
- clientPid, servicePid)
+ clientPackageName,
+ cameraId, cameraFacing,
+ clientPid, clientUid,
+ servicePid)
{
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
@@ -534,6 +562,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
cameraService->setCameraBusy(cameraId);
cameraService->loadSound();
+
LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
}
@@ -542,23 +571,27 @@ CameraService::Client::~Client() {
mDestructionStarted = true;
mCameraService->releaseSound();
-
+ finishCameraOps();
// unconditionally disconnect. function is idempotent
Client::disconnect();
}
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
- const sp<IBinder>& remoteCallback,
- int cameraId, int cameraFacing,
- int clientPid, int servicePid)
+ const sp<IBinder>& remoteCallback,
+ const String16& clientPackageName,
+ int cameraId, int cameraFacing,
+ int clientPid, uid_t clientUid,
+ int servicePid):
+ mClientPackageName(clientPackageName)
{
mCameraService = cameraService;
mRemoteCallback = remoteCallback;
mCameraId = cameraId;
mCameraFacing = cameraFacing;
mClientPid = clientPid;
+ mClientUid = clientUid;
mServicePid = servicePid;
-
+ mOpsActive = false;
mDestructionStarted = false;
}
@@ -570,6 +603,66 @@ void CameraService::BasicClient::disconnect() {
mCameraService->removeClientByRemote(mRemoteCallback);
}
+status_t CameraService::BasicClient::startCameraOps() {
+ int32_t res;
+
+ mOpsCallback = new OpsCallback(this);
+
+ mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
+ mClientPackageName, mOpsCallback);
+ res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
+ mClientUid, mClientPackageName);
+
+ if (res != AppOpsManager::MODE_ALLOWED) {
+ ALOGI("Camera %d: Access for \"%s\" has been revoked",
+ mCameraId, String8(mClientPackageName).string());
+ return PERMISSION_DENIED;
+ }
+ mOpsActive = true;
+ return OK;
+}
+
+status_t CameraService::BasicClient::finishCameraOps() {
+ if (mOpsActive) {
+ mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
+ mClientPackageName);
+ mOpsActive = false;
+ }
+ mAppOpsManager.stopWatchingMode(mOpsCallback);
+ mOpsCallback.clear();
+
+ return OK;
+}
+
+void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
+ String8 name(packageName);
+ String8 myName(mClientPackageName);
+
+ if (op != AppOpsManager::OP_CAMERA) {
+ ALOGW("Unexpected app ops notification received: %d", op);
+ return;
+ }
+
+ int32_t res;
+ res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
+ mClientUid, mClientPackageName);
+ ALOGV("checkOp returns: %d, %s ", res,
+ res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
+ res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
+ res == AppOpsManager::MODE_ERRORED ? "ERRORED" :
+ "UNKNOWN");
+
+ if (res != AppOpsManager::MODE_ALLOWED) {
+ ALOGI("Camera %d: Access for \"%s\" revoked", mCameraId,
+ myName.string());
+ // Reset the client PID to allow server-initiated disconnect,
+ // and to prevent further calls by client.
+ mClientPid = getCallingPid();
+ notifyError();
+ disconnect();
+ }
+}
+
// ----------------------------------------------------------------------------
Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
@@ -592,25 +685,43 @@ CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
return client;
}
+void CameraService::Client::notifyError() {
+ mCameraClient->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+}
+
// NOTE: function is idempotent
void CameraService::Client::disconnect() {
BasicClient::disconnect();
mCameraService->setCameraFree(mCameraId);
}
+CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
+ mClient(client) {
+}
+
+void CameraService::Client::OpsCallback::opChanged(int32_t op,
+ const String16& packageName) {
+ sp<BasicClient> client = mClient.promote();
+ if (client != NULL) {
+ client->opChanged(op, packageName);
+ }
+}
+
// ----------------------------------------------------------------------------
// IProCamera
// ----------------------------------------------------------------------------
CameraService::ProClient::ProClient(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- int cameraId,
- int cameraFacing,
- int clientPid,
- int servicePid)
- : CameraService::BasicClient(cameraService, remoteCallback->asBinder(),
- cameraId, cameraFacing,
- clientPid, servicePid)
+ const sp<IProCameraCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ int cameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+ int servicePid)
+ : CameraService::BasicClient(cameraService, remoteCallback->asBinder(),
+ clientPackageName, cameraId, cameraFacing,
+ clientPid, clientUid, servicePid)
{
mRemoteCallback = remoteCallback;
}
@@ -683,6 +794,10 @@ status_t CameraService::ProClient::cancelStream(int streamId) {
return INVALID_OPERATION;
}
+void CameraService::ProClient::notifyError() {
+ ALOGE("%s: not implemented yet", __FUNCTION__);
+}
+
// ----------------------------------------------------------------------------
static const int kDumpLockRetries = 50;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 9e0f62a..b017505 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -19,7 +19,9 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <utils/Vector.h>
+#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
+#include <binder/IAppOpsCallback.h>
#include <camera/ICameraService.h>
#include <hardware/camera.h>
@@ -54,9 +56,11 @@ public:
virtual int32_t getNumberOfCameras();
virtual status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo);
- virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
- virtual sp<IProCameraUser>
- connect(const sp<IProCameraCallbacks>& cameraCb, int cameraId);
+
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
+ const String16& clientPackageName, int clientUid);
+ virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb,
+ int cameraId);
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
@@ -100,9 +104,11 @@ public:
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid);
virtual ~BasicClient();
@@ -117,12 +123,41 @@ public:
sp<CameraService> mCameraService; // immutable after constructor
int mCameraId; // immutable after constructor
int mCameraFacing; // immutable after constructor
+ const String16 mClientPackageName;
pid_t mClientPid;
+ uid_t mClientUid; // immutable after constructor
pid_t mServicePid; // immutable after constructor
// - The app-side Binder interface to receive callbacks from us
wp<IBinder> mRemoteCallback; // immutable after constructor
- };
+
+ // permissions management
+ status_t startCameraOps();
+ status_t finishCameraOps();
+
+ // Notify client about a fatal error
+ virtual void notifyError() = 0;
+ private:
+ AppOpsManager mAppOpsManager;
+
+ class OpsCallback : public BnAppOpsCallback {
+ public:
+ OpsCallback(wp<BasicClient> client);
+ virtual void opChanged(int32_t op, const String16& packageName);
+
+ private:
+ wp<BasicClient> mClient;
+
+ }; // class OpsCallback
+
+ sp<OpsCallback> mOpsCallback;
+ // Track whether startCameraOps was called successfully, to avoid
+ // finishing what we didn't start.
+ bool mOpsActive;
+
+ // IAppOpsCallback interface, indirected through opListener
+ virtual void opChanged(int32_t op, const String16& packageName);
+ }; // class BasicClient
class Client : public BnCamera, public BasicClient
{
@@ -153,9 +188,11 @@ public:
// Interface used by CameraService
Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid);
~Client();
@@ -169,19 +206,24 @@ public:
// convert client from cookie. Client lock should be acquired before getting Client.
static Client* getClientFromCookie(void* user);
+ virtual void notifyError();
+
// Initialized in constructor
// - The app-side Binder interface to receive callbacks from us
sp<ICameraClient> mCameraClient;
- };
+
+ }; // class Client
class ProClient : public BnProCameraUser, public BasicClient {
public:
ProClient(const sp<CameraService>& cameraService,
const sp<IProCameraCallbacks>& remoteCallback,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid);
virtual ~ProClient();
@@ -217,9 +259,10 @@ public:
virtual status_t cancelStream(int streamId);
protected:
- sp<IProCameraCallbacks> mRemoteCallback;
+ virtual void notifyError();
- };
+ sp<IProCameraCallbacks> mRemoteCallback;
+ }; // class ProClient
private:
diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp
index c264e2a..eda3012 100644
--- a/services/camera/libcameraservice/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/ProCamera2Client.cpp
@@ -43,12 +43,14 @@ static int getCallingUid() {
ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
const sp<IProCameraCallbacks>& remoteCallback,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid):
- ProClient(cameraService, remoteCallback,
- cameraId, cameraFacing, clientPid, servicePid),
+ ProClient(cameraService, remoteCallback, clientPackageName,
+ cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback)
{
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h
index cd0a2ae..9f514f4 100644
--- a/services/camera/libcameraservice/ProCamera2Client.h
+++ b/services/camera/libcameraservice/ProCamera2Client.h
@@ -77,9 +77,11 @@ public:
ProCamera2Client(const sp<CameraService>& cameraService,
const sp<IProCameraCallbacks>& remoteCallback,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
+ uid_t clientUid,
int servicePid);
virtual ~ProCamera2Client();