Camera: fix race issue in Camera2 clients
Updating of the mDevice sp<> is racy.
This change will cause the Camera3Device object lives until
the client is destructed (which can be a few seconds after
camera app closed and GC kicking in to delete the client)
The benefit is the dumpDevice can remain lock free.
Also fix a problem where we call virtual function disconnect in
Camera3Device destructor.
Test: the double free problem cannot reproduce
Bug: 112639939
Change-Id: I77762db8f59cf33891631d13fc3bdb3830ae08fb
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 261cdbf..bf18c48 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -453,8 +453,6 @@
mDevice->disconnect();
- mDevice.clear();
-
CameraService::Client::disconnect();
return res;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ce006a7..aeea473 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -57,13 +57,13 @@
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
+ mDevice(new Camera3Device(cameraId)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
- mDevice = new Camera3Device(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
@@ -206,8 +206,6 @@
if (mDevice == 0) return;
mDevice->disconnect();
- mDevice.clear();
-
ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.string());
}
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e74fbdf..6693847 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -130,7 +130,10 @@
/** CameraDeviceBase instance wrapping HAL3+ entry */
const int mDeviceVersion;
- sp<CameraDeviceBase> mDevice;
+
+ // Set to const to avoid mDevice being updated (update of sp<> is racy) during
+ // dumpDevice (which is important to be lock free for debugging purpose)
+ const sp<CameraDeviceBase> mDevice;
/** Utility members */
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4c6718c..7656407 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -90,7 +90,7 @@
{
ATRACE_CALL();
ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
- disconnect();
+ disconnectImpl();
}
const String8& Camera3Device::getId() const {
@@ -275,6 +275,10 @@
}
status_t Camera3Device::disconnect() {
+ return disconnectImpl();
+}
+
+status_t Camera3Device::disconnectImpl() {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock stLock(mTrackerLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 51e1fb0..85f9614 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -210,6 +210,8 @@
private:
+ status_t disconnectImpl();
+
// internal typedefs
using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;