Merge changes from topic 'camera-hardening'
* changes:
camera: Add support to pass native handles across binders
Camera: Fix client permission check
Add cameraserver process
diff --git a/camera/Android.mk b/camera/Android.mk
index 471cb0d..de23953 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -52,6 +52,7 @@
LOCAL_C_INCLUDES += \
system/media/camera/include \
system/media/private/camera/include \
+ frameworks/native/include/media/openmax \
LOCAL_MODULE:= libcamera_client
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index cd3b84c..1289348 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -72,9 +72,9 @@
}
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
- int clientUid)
+ int clientUid, int clientPid)
{
- return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
+ return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}
status_t Camera::connectLegacy(int cameraId, int halVersion,
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 5d50aa8..9ee7ae5 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -92,7 +92,7 @@
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
- int clientUid)
+ int clientUid, int clientPid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
@@ -103,7 +103,7 @@
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
- /*out*/ c->mCamera);
+ clientPid, /*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 04244ac..26eebe3 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <camera/CameraUtils.h>
+#include <media/hardware/HardwareAPI.h>
#include <system/window.h>
#include <system/graphics.h>
@@ -121,5 +122,19 @@
return OK;
}
+// Return whether the image data contains a native handle.
+bool CameraUtils::isNativeHandleMetadata(const sp<IMemory>& imageData) {
+ if (imageData == nullptr) {
+ return false;
+ }
+
+ if (imageData->size() == sizeof(VideoNativeHandleMetadata)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(imageData->pointer());
+ return metadata->eType == kMetadataBufferTypeNativeHandleSource;
+ }
+
+ return false;
+}
} /* namespace android */
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index cce5a9a..1dd8912 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -21,9 +21,11 @@
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
+#include <camera/CameraUtils.h>
#include <camera/ICamera.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
+#include <media/hardware/HardwareAPI.h>
namespace android {
@@ -149,7 +151,22 @@
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(mem));
+
+ native_handle_t *nh = nullptr;
+ if (CameraUtils::isNativeHandleMetadata(mem)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(mem->pointer());
+ nh = metadata->pHandle;
+ data.writeNativeHandle(nh);
+ }
+
remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+
+ if (nh) {
+ // Close the native handle because camera received a dup copy.
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ }
}
status_t setVideoBufferMode(int32_t videoBufferMode)
@@ -348,6 +365,14 @@
ALOGV("RELEASE_RECORDING_FRAME");
CHECK_INTERFACE(ICamera, data, reply);
sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+
+ if (CameraUtils::isNativeHandleMetadata(mem)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(mem->pointer());
+ metadata->pHandle = data.readNativeHandle();
+ // releaseRecordingFrame will be responsble to close the native handle.
+ }
+
releaseRecordingFrame(mem);
return NO_ERROR;
} break;
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 179a341..4282f9a 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2008, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
**
-** http://www.apache.org/licenses/LICENSE-2.0
+** http://www.apache.org/licenses/LICENSE-2.0
**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
@@ -20,7 +20,9 @@
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
+#include <camera/CameraUtils.h>
#include <camera/ICameraClient.h>
+#include <media/hardware/HardwareAPI.h>
namespace android {
@@ -75,6 +77,13 @@
data.writeInt64(timestamp);
data.writeInt32(msgType);
data.writeStrongBinder(IInterface::asBinder(imageData));
+ // If imageData is metadata and it contains a native handle, write the native handle to
+ // parcel.
+ if (CameraUtils::isNativeHandleMetadata(imageData)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(imageData->pointer());
+ data.writeNativeHandle(metadata->pHandle);
+ }
remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -118,6 +127,19 @@
nsecs_t timestamp = data.readInt64();
int32_t msgType = data.readInt32();
sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+
+ // If the image data contains a native handle, read the native handle from the parcel
+ // and replace the native handle in the image data. (The native handle in image data is
+ // not serielized/deserialized so it's not valid in the process.)
+ if (CameraUtils::isNativeHandleMetadata(imageData)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(imageData->pointer());
+ metadata->pHandle = data.readNativeHandle();
+
+ // The native handle will be freed in
+ // BpCameraRecordingProxyListener::releaseRecordingFrame.
+ }
+
dataCallbackTimestamp(timestamp, msgType, imageData);
return NO_ERROR;
} break;
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index 3dc0ffb..d128f5b 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -16,10 +16,12 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ICameraRecordingProxy"
+#include <camera/CameraUtils.h>
#include <camera/ICameraRecordingProxy.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
#include <stdint.h>
#include <utils/Log.h>
@@ -64,7 +66,22 @@
Parcel data, reply;
data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(mem));
+
+ native_handle_t *nh = nullptr;
+ if (CameraUtils::isNativeHandleMetadata(mem)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(mem->pointer());
+ nh = metadata->pHandle;
+ data.writeNativeHandle(nh);
+ }
+
remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+
+ if (nh) {
+ // Close the native handle because camera received a dup copy.
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ }
}
};
@@ -94,7 +111,16 @@
ALOGV("RELEASE_RECORDING_FRAME");
CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+
+ if (CameraUtils::isNativeHandleMetadata(mem)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(mem->pointer());
+ metadata->pHandle = data.readNativeHandle();
+
+ // releaseRecordingFrame will be responsble to close the native handle.
+ }
releaseRecordingFrame(mem);
+
return NO_ERROR;
} break;
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index cf848fc..447174e 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -16,9 +16,11 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/CameraUtils.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
#include <utils/Log.h>
namespace android {
@@ -43,7 +45,22 @@
data.writeInt64(timestamp);
data.writeInt32(msgType);
data.writeStrongBinder(IInterface::asBinder(imageData));
+ native_handle_t* nh = nullptr;
+
+ if (CameraUtils::isNativeHandleMetadata(imageData)) {
+ VideoNativeHandleMetadata *metadata =
+ (VideoNativeHandleMetadata*)(imageData->pointer());
+ nh = metadata->pHandle;
+ data.writeNativeHandle(nh);
+ }
+
remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+
+ // The native handle is dupped in ICameraClient so we need to free it here.
+ if (nh) {
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ }
}
};
@@ -61,6 +78,15 @@
nsecs_t timestamp = data.readInt64();
int32_t msgType = data.readInt32();
sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+
+ if (CameraUtils::isNativeHandleMetadata(imageData)) {
+ VideoNativeHandleMetadata *meta = (VideoNativeHandleMetadata*)(imageData->pointer());
+ meta->pHandle = data.readNativeHandle();
+
+ // The native handle will be freed in
+ // BpCameraRecordingProxyListener::releaseRecordingFrame.
+ }
+
dataCallbackTimestamp(timestamp, msgType, imageData);
return NO_ERROR;
} break;
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index b359f57..4a042a6 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -172,7 +172,7 @@
// connect to camera service (android.hardware.Camera)
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
- const String16 &clientPackageName, int clientUid,
+ const String16 &clientPackageName, int clientUid, int clientPid,
/*out*/
sp<ICamera>& device)
{
@@ -182,6 +182,7 @@
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
+ data.writeInt32(clientPid);
status_t status;
status = remote()->transact(BnCameraService::CONNECT, data, &reply);
@@ -396,9 +397,10 @@
int32_t cameraId = data.readInt32();
const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
+ int32_t clientPid = data.readInt32();
sp<ICamera> camera;
status_t status = connect(cameraClient, cameraId,
- clientName, clientUid, /*out*/camera);
+ clientName, clientUid, clientPid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk
new file mode 100644
index 0000000..4d8339c
--- /dev/null
+++ b/camera/cameraserver/Android.mk
@@ -0,0 +1,37 @@
+# Copyright 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_cameraserver.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcameraservice \
+ libcutils \
+ libutils \
+ libbinder
+
+LOCAL_C_INCLUDES := \
+ frameworks/av/services/camera/libcameraservice \
+ system/media/camera/include
+
+LOCAL_MODULE:= cameraserver
+LOCAL_32_BIT_ONLY := true
+
+LOCAL_INIT_RC := cameraserver.rc
+
+include $(BUILD_EXECUTABLE)
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
new file mode 100644
index 0000000..37e2688
--- /dev/null
+++ b/camera/cameraserver/cameraserver.rc
@@ -0,0 +1,5 @@
+service cameraserver /system/bin/cameraserver
+ class main
+ user cameraserver
+ group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
+ ioprio rt 4
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
new file mode 100644
index 0000000..f4be468
--- /dev/null
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "cameraserver"
+//#define LOG_NDEBUG 0
+
+// from LOCAL_C_INCLUDES
+#include "CameraService.h"
+
+using namespace android;
+
+int main(int argc __unused, char** argv __unused)
+{
+ signal(SIGPIPE, SIG_IGN);
+
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ ALOGI("ServiceManager: %p", sm.get());
+ CameraService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index f7bf29c..f19d296 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -52,7 +52,7 @@
typedef ICamera TCamUser;
typedef ICameraClient TCamCallbacks;
typedef status_t (ICameraService::*TCamConnectService)(const sp<ICameraClient>&,
- int, const String16&, int,
+ int, const String16&, int, int,
/*out*/
sp<ICamera>&);
static TCamConnectService fnConnectService;
@@ -67,12 +67,15 @@
enum {
USE_CALLING_UID = ICameraService::USE_CALLING_UID
};
+ enum {
+ USE_CALLING_PID = ICameraService::USE_CALLING_PID
+ };
// construct a camera client from an existing remote
static sp<Camera> create(const sp<ICamera>& camera);
static sp<Camera> connect(int cameraId,
const String16& clientPackageName,
- int clientUid);
+ int clientUid, int clientPid);
static status_t connectLegacy(int cameraId, int halVersion,
const String16& clientPackageName,
diff --git a/include/camera/CameraBase.h b/include/camera/CameraBase.h
index 1b93157..d8561ed 100644
--- a/include/camera/CameraBase.h
+++ b/include/camera/CameraBase.h
@@ -61,7 +61,7 @@
static sp<TCam> connect(int cameraId,
const String16& clientPackageName,
- int clientUid);
+ int clientUid, int clientPid);
virtual void disconnect();
void setListener(const sp<TCamListener>& listener);
diff --git a/include/camera/CameraUtils.h b/include/camera/CameraUtils.h
index c06f05d..f596f80 100644
--- a/include/camera/CameraUtils.h
+++ b/include/camera/CameraUtils.h
@@ -17,8 +17,10 @@
#ifndef ANDROID_CAMERA_CLIENT_CAMERAUTILS_H
#define ANDROID_CAMERA_CLIENT_CAMERAUTILS_H
+#include <binder/IMemory.h>
#include <camera/CameraMetadata.h>
#include <utils/Errors.h>
+#include <utils/RefBase.h>
#include <stdint.h>
@@ -39,6 +41,12 @@
*/
static status_t getRotationTransform(const CameraMetadata& staticInfo,
/*out*/int32_t* transform);
+
+ /**
+ * Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
+ */
+ static bool isNativeHandleMetadata(const sp<IMemory>& imageData);
+
private:
CameraUtils();
};
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 1b68b5f..d568b4d 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -55,6 +55,10 @@
};
enum {
+ USE_CALLING_PID = -1
+ };
+
+ enum {
USE_CALLING_UID = -1
};
@@ -113,14 +117,17 @@
virtual status_t removeListener(const sp<ICameraServiceListener>& listener)
= 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.
+ * clientPackageName, clientUid, and clientPid are used for permissions checking. If
+ * clientUid == USE_CALLING_UID, then the calling UID is used instead. If
+ * clientPid == USE_CALLING_PID, then the calling PID is used instead. Only
+ * trusted callers can set a clientUid and clientPid other than USE_CALLING_UID and
+ * USE_CALLING_UID respectively.
*/
virtual status_t connect(const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
+ int clientPid,
/*out*/
sp<ICamera>& device) = 0;
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 769adf8..3d00d30 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -61,6 +61,8 @@
* permissions checking.
* @param clientUid the UID of the camera-using application if camera is
* NULL; otherwise ignored. Used for permissions checking.
+ * @param clientPid the PID 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
@@ -81,6 +83,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
@@ -198,7 +201,7 @@
int64_t mTimeBetweenFrameCaptureUs;
CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, const String16& clientName, uid_t clientUid,
+ int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
bool storeMetaDataInVideoBuffers);
@@ -258,12 +261,12 @@
void processBufferQueueFrame(const BufferItem& buffer);
status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, const String16& clientName, uid_t clientUid,
+ int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
status_t initWithCameraAccess(
const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, const String16& clientName, uid_t clientUid,
+ int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
// Initialize the buffer queue used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
@@ -274,7 +277,8 @@
const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
const String16& clientName,
- uid_t clientUid);
+ uid_t clientUid,
+ pid_t clientPid);
status_t isCameraColorFormatSupported(const CameraParameters& params);
status_t configureCamera(CameraParameters* params,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 34213be..1023027 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -38,6 +38,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t videoFrameRate,
const sp<IGraphicBufferProducer>& surface,
@@ -114,6 +115,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t videoFrameRate,
const sp<IGraphicBufferProducer>& surface,
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3cbf6f2..533b6e0 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -782,8 +782,9 @@
return INVALID_OPERATION;
}
- // Get UID here for permission checking
+ // Get UID and PID here for permission checking
mClientUid = IPCThreadState::self()->getCallingUid();
+ mClientPid = IPCThreadState::self()->getCallingPid();
status_t status = OK;
@@ -1451,13 +1452,13 @@
}
mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
- mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
+ mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
videoSize, mFrameRate, mPreviewSurface,
mTimeBetweenCaptureUs);
*cameraSource = mCameraSourceTimeLapse;
} else {
*cameraSource = CameraSource::CreateFromCamera(
- mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
+ mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
videoSize, mFrameRate,
mPreviewSurface);
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index a799e9d..761e987 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -80,6 +80,7 @@
sp<IMediaRecorderClient> mListener;
String16 mClientName;
uid_t mClientUid;
+ pid_t mClientPid;
sp<MediaWriter> mWriter;
int mOutputFd;
sp<AudioSource> mAudioSourceNode;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index dab623b..d302f82 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -142,8 +142,8 @@
size.height = -1;
sp<ICamera> camera;
- return new CameraSource(camera, NULL, 0, clientName, -1,
- size, -1, NULL, false);
+ return new CameraSource(camera, NULL, 0, clientName, Camera::USE_CALLING_UID,
+ Camera::USE_CALLING_PID, size, -1, NULL, false);
}
// static
@@ -153,13 +153,14 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
bool storeMetaDataInVideoBuffers) {
CameraSource *source = new CameraSource(camera, proxy, cameraId,
- clientName, clientUid, videoSize, frameRate, surface,
+ clientName, clientUid, clientPid, videoSize, frameRate, surface,
storeMetaDataInVideoBuffers);
return source;
}
@@ -170,6 +171,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
@@ -193,7 +195,7 @@
mVideoSize.height = -1;
mInitCheck = init(camera, proxy, cameraId,
- clientName, clientUid,
+ clientName, clientUid, clientPid,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
if (mInitCheck != OK) releaseCamera();
@@ -205,10 +207,10 @@
status_t CameraSource::isCameraAvailable(
const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
- int32_t cameraId, const String16& clientName, uid_t clientUid) {
+ int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid) {
if (camera == 0) {
- mCamera = Camera::connect(cameraId, clientName, clientUid);
+ mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid);
if (mCamera == 0) return -EBUSY;
mCameraFlags &= ~FLAGS_HOT_CAMERA;
} else {
@@ -492,6 +494,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t frameRate,
bool storeMetaDataInVideoBuffers) {
@@ -499,7 +502,7 @@
ALOGV("init");
status_t err = OK;
int64_t token = IPCThreadState::self()->clearCallingIdentity();
- err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid,
+ err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid, clientPid,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
IPCThreadState::self()->restoreCallingIdentity(token);
@@ -583,6 +586,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t frameRate,
bool storeMetaDataInVideoBuffers) {
@@ -590,7 +594,7 @@
status_t err = OK;
if ((err = isCameraAvailable(camera, proxy, cameraId,
- clientName, clientUid)) != OK) {
+ clientName, clientUid, clientPid)) != OK) {
ALOGE("Camera connection could not be established.");
return err;
}
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 0acd9d0..202ec42 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -40,6 +40,7 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t videoFrameRate,
const sp<IGraphicBufferProducer>& surface,
@@ -48,7 +49,7 @@
CameraSourceTimeLapse *source = new
CameraSourceTimeLapse(camera, proxy, cameraId,
- clientName, clientUid,
+ clientName, clientUid, clientPid,
videoSize, videoFrameRate, surface,
timeBetweenFrameCaptureUs,
storeMetaDataInVideoBuffers);
@@ -68,12 +69,13 @@
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
+ pid_t clientPid,
Size videoSize,
int32_t videoFrameRate,
const sp<IGraphicBufferProducer>& surface,
int64_t timeBetweenFrameCaptureUs,
bool storeMetaDataInVideoBuffers)
- : CameraSource(camera, proxy, cameraId, clientName, clientUid,
+ : CameraSource(camera, proxy, cameraId, clientName, clientUid, clientPid,
videoSize, videoFrameRate, surface,
storeMetaDataInVideoBuffers),
mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 7e3041b..e006e89 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -40,7 +40,6 @@
ALOGI("ServiceManager: %p", sm.get());
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
- CameraService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index fcdcdb5..f0bcc0b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -46,6 +46,7 @@
#include <utils/Log.h>
#include <utils/String16.h>
#include <utils/Trace.h>
+#include <private/android_filesystem_config.h>
#include <system/camera_vendor_tags.h>
#include <system/camera_metadata.h>
#include <system/camera.h>
@@ -783,13 +784,13 @@
status_t CameraService::initializeShimMetadata(int cameraId) {
int uid = getCallingUid();
- String16 internalPackageName("media");
+ String16 internalPackageName("cameraserver");
String8 id = String8::format("%d", cameraId);
status_t ret = NO_ERROR;
sp<Client> tmp = nullptr;
if ((ret = connectHelper<ICameraClient,Client>(sp<ICameraClient>{nullptr}, id,
- static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED), internalPackageName, uid, API_1,
- false, true, tmp)) != NO_ERROR) {
+ static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED), internalPackageName, uid,
+ USE_CALLING_PID, API_1, false, true, tmp)) != NO_ERROR) {
ALOGE("%s: Error %d (%s) initializing shim metadata.", __FUNCTION__, ret, strerror(ret));
return ret;
}
@@ -856,22 +857,52 @@
return INVALID_OPERATION;
}
-status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid)
- const {
+// Can camera service trust the caller based on the calling UID?
+static bool isTrustedCallingUid(uid_t uid) {
+ switch (uid) {
+ case AID_MEDIA: // mediaserver
+ case AID_CAMERASERVER: // cameraserver
+ return true;
+ default:
+ return false;
+ }
+}
+
+status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid,
+ /*inout*/int& clientPid) const {
int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
+ // Check if we can trust clientUid
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 %d)",
- callingPid, clientUid);
- return PERMISSION_DENIED;
- }
+ clientUid = callingUid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
+ "(don't trust clientUid %d)", callingPid, callingUid, clientUid);
+ return PERMISSION_DENIED;
}
+ // Check if we can trust clientPid
+ if (clientPid == USE_CALLING_PID) {
+ clientPid = callingPid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
+ "(don't trust clientPid %d)", callingPid, callingUid, clientPid);
+ return PERMISSION_DENIED;
+ }
+
+ // If it's not calling from cameraserver, check the permission.
+ if (callingPid != getpid() &&
+ !checkPermission(String16("android.permission.CAMERA"), clientPid, clientUid)) {
+ ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
+ return PERMISSION_DENIED;
+ }
+
+ // Only use passed in clientPid to check permission. Use calling PID as the client PID that's
+ // connected to camera service directly.
+ clientPid = callingPid;
+
if (!mModule) {
ALOGE("CameraService::connect X (PID %d) rejected (camera HAL module not loaded)",
callingPid);
@@ -1144,6 +1175,7 @@
int cameraId,
const String16& clientPackageName,
int clientUid,
+ int clientPid,
/*out*/
sp<ICamera>& device) {
@@ -1152,7 +1184,7 @@
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
- clientPackageName, clientUid, API_1, false, false, /*out*/client);
+ clientPackageName, clientUid, clientPid, API_1, false, false, /*out*/client);
if(ret != NO_ERROR) {
logRejected(id, getCallingPid(), String8(clientPackageName),
@@ -1193,7 +1225,7 @@
status_t ret = NO_ERROR;
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, clientPackageName,
- clientUid, API_1, true, false, /*out*/client);
+ clientUid, USE_CALLING_PID, API_1, true, false, /*out*/client);
if(ret != NO_ERROR) {
logRejected(id, getCallingPid(), String8(clientPackageName),
@@ -1218,8 +1250,8 @@
String8 id = String8::format("%d", cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, API_2, false, false,
- /*out*/client);
+ CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, USE_CALLING_PID,
+ API_2, false, false, /*out*/client);
if(ret != NO_ERROR) {
logRejected(id, getCallingPid(), String8(clientPackageName),
@@ -1785,21 +1817,6 @@
// Permission checks
switch (code) {
- case BnCameraService::CONNECT:
- case BnCameraService::CONNECT_DEVICE:
- case BnCameraService::CONNECT_LEGACY: {
- if (pid != selfPid) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.CAMERA"))) {
- const int uid = getCallingUid();
- ALOGE("Permission Denial: "
- "can't use the camera pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
- break;
- }
case BnCameraService::NOTIFY_SYSTEM_EVENT: {
if (pid != selfPid) {
// Ensure we're being called by system_server, or similar process with
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c1c2aef..66de77f 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -116,7 +116,7 @@
virtual status_t getCameraVendorTagDescriptor(/*out*/ sp<VendorTagDescriptor>& desc);
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
- const String16& clientPackageName, int clientUid,
+ const String16& clientPackageName, int clientUid, int clientPid,
/*out*/
sp<ICamera>& device);
@@ -488,7 +488,8 @@
virtual void onFirstRef();
// Check if we can connect, before we acquire the service lock.
- status_t validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const;
+ status_t validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid,
+ /*inout*/int& clientPid) const;
// Handle active client evictions, and update service state.
// Only call with with mServiceLock held.
@@ -501,8 +502,9 @@
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
status_t connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId, int halVersion,
- const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
- bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
+ const String16& clientPackageName, int clientUid, int clientPid,
+ apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
+ /*out*/sp<CLIENT>& device);
// Lock guarding camera service state
Mutex mServiceLock;
@@ -801,12 +803,11 @@
template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
- int halVersion, const String16& clientPackageName, int clientUid,
+ int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
status_t ret = NO_ERROR;
String8 clientName8(clientPackageName);
- int clientPid = getCallingPid();
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
@@ -826,7 +827,8 @@
}
// Enforce client permissions and do basic sanity checks
- if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
+ if((ret = validateConnectLocked(cameraId, /*inout*/clientUid, /*inout*/clientPid)) !=
+ NO_ERROR) {
return ret;
}
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index c17fc65..5ac5743 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -371,7 +371,7 @@
ATRACE_CALL();
Mutex::Autolock icl(mBinderSerializationLock);
- // Allow both client and the media server to disconnect at all times
+ // Allow both client and the cameraserver to disconnect at all times
int callingPid = getCallingPid();
if (callingPid != mClientPid && callingPid != mServicePid) return;
@@ -1233,6 +1233,7 @@
}
void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
+ (void)mem;
ATRACE_CALL();
ALOGW("%s: Not supported in buffer queue mode.", __FUNCTION__);
}
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index cba4590..6aeab98 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -234,7 +234,7 @@
LOG1("disconnect E (pid %d)", callingPid);
Mutex::Autolock lock(mLock);
- // Allow both client and the media server to disconnect at all times
+ // Allow both client and the cameraserver to disconnect at all times
if (callingPid != mClientPid && callingPid != mServicePid) {
ALOGW("different client - don't disconnect");
return;
@@ -1001,6 +1001,7 @@
}
status_t CameraClient::setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer) {
+ (void)bufferProducer;
ALOGE("%s: %d: CameraClient doesn't support setting a video target.", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}