summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.cpp55
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.h1
-rw-r--r--services/camera/libcameraservice/camera2/Parameters.cpp26
3 files changed, 82 insertions, 0 deletions
diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp
index 575b075..251fdab 100644
--- a/services/camera/libcameraservice/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/ProCamera2Client.cpp
@@ -203,6 +203,10 @@ status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
CameraMetadata metadata(request);
+ if (!enforceRequestPermissions(metadata)) {
+ return PERMISSION_DENIED;
+ }
+
if (streaming) {
return mDevice->setStreamingRequest(metadata);
} else {
@@ -388,4 +392,55 @@ void ProCamera2Client::onFrameAvailable(int32_t frameId,
}
+bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
+
+ const int pid = IPCThreadState::self()->getCallingPid();
+ const int selfPid = getpid();
+ camera_metadata_entry_t entry;
+
+ /**
+ * Mixin default important security values
+ * - android.led.transmit = defaulted ON
+ */
+ CameraMetadata staticInfo = mDevice->info();
+ entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
+ for(size_t i = 0; i < entry.count; ++i) {
+ uint8_t led = entry.data.u8[i];
+
+ switch(led) {
+ case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
+ uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
+ if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
+ metadata.update(ANDROID_LED_TRANSMIT,
+ &transmitDefault, 1);
+ }
+ break;
+ }
+ }
+ }
+
+ // We can do anything!
+ if (pid == selfPid) {
+ return true;
+ }
+
+ /**
+ * Permission check special fields in the request
+ * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
+ */
+ entry = metadata.find(ANDROID_LED_TRANSMIT);
+ if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
+ String16 permissionString =
+ String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
+ if (!checkCallingPermission(permissionString)) {
+ const int uid = IPCThreadState::self()->getCallingUid();
+ ALOGE("Permission Denial: "
+ "can't disable transmit LED pid=%d, uid=%d", pid, uid);
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace android
diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h
index 1dec263..faee9f9 100644
--- a/services/camera/libcameraservice/ProCamera2Client.h
+++ b/services/camera/libcameraservice/ProCamera2Client.h
@@ -110,6 +110,7 @@ private:
static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
/** Utility members */
+ bool enforceRequestPermissions(CameraMetadata& metadata);
// Whether or not we have an exclusive lock on the device
// - if no we can't modify the request queue.
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index d13fe8b..a304b35 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -1588,6 +1588,32 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
ATRACE_CALL();
status_t res;
+ /**
+ * Mixin default important security values
+ * - android.led.transmit = defaulted ON
+ */
+ camera_metadata_ro_entry_t entry = staticInfo(ANDROID_LED_AVAILABLE_LEDS,
+ /*minimumCount*/0);
+ for(size_t i = 0; i < entry.count; ++i) {
+ uint8_t led = entry.data.u8[i];
+
+ switch(led) {
+ // Transmit LED is unconditionally on when using
+ // the android.hardware.Camera API
+ case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
+ uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
+ res = request->update(ANDROID_LED_TRANSMIT,
+ &transmitDefault, 1);
+ if (res != OK) return res;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Construct metadata from parameters
+ */
+
uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
res = request->update(ANDROID_REQUEST_METADATA_MODE,
&metadataMode, 1);