Camera: Fix & improve camera device error analytics
- Pass deviceError in onClose.
- If cameraservice watchdog triggers, send onClose to note down
a device error.
Test: Fake device error and observe logs
Bug: 239057315
Change-Id: I0dbbb3c05d3318b8839e3a8d4cd369e600b29e48
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index 74497d1..e80064a 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CameraServiceWatchdog"
#include "CameraServiceWatchdog.h"
+#include "utils/CameraServiceProxyWrapper.h"
namespace android {
@@ -43,6 +44,8 @@
if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
currentThreadId);
+ mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
+ true /*deviceError*/);
// We use abort here so we can get a tombstone for better
// debugging.
abort();
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index e35d69e..6617873 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -32,10 +32,13 @@
#include <chrono>
#include <thread>
#include <time.h>
+#include <utils/String8.h>
#include <utils/Thread.h>
#include <utils/Log.h>
#include <unordered_map>
+#include "utils/CameraServiceProxyWrapper.h"
+
// Used to wrap the call of interest in start and stop calls
#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
@@ -50,12 +53,18 @@
class CameraServiceWatchdog : public Thread {
public:
- explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
- mCycleLengthMs(kCycleLengthMs), mEnabled(true) {};
+ explicit CameraServiceWatchdog(const String8 &cameraId,
+ std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
+ mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
+ mCycleLengthMs(kCycleLengthMs), mEnabled(true),
+ mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
- explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs, bool enabled) :
- mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs), mEnabled(enabled)
- {};
+ explicit CameraServiceWatchdog (const String8 &cameraId, size_t maxCycles,
+ uint32_t cycleLengthMs, bool enabled,
+ std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
+ mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
+ mCycleLengthMs(cycleLengthMs), mEnabled(enabled),
+ mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
virtual ~CameraServiceWatchdog() {};
@@ -75,8 +84,8 @@
// Lock for mEnabled
mEnabledLock.lock();
- sp<CameraServiceWatchdog> tempWatchdog =
- new CameraServiceWatchdog(cycles, cycleLength, mEnabled);
+ sp<CameraServiceWatchdog> tempWatchdog = new CameraServiceWatchdog(
+ mCameraId, cycles, cycleLength, mEnabled, mCameraServiceProxyWrapper);
mEnabledLock.unlock();
status_t status = tempWatchdog->run("CameraServiceWatchdog");
@@ -134,11 +143,14 @@
Mutex mWatchdogLock; // Lock for condition variable
Mutex mEnabledLock; // Lock for enabled status
Condition mWatchdogCondition; // Condition variable for stop/start
+ String8 mCameraId; // Camera Id the watchdog belongs to
bool mPause; // True if tid map is empty
uint32_t mMaxCycles; // Max cycles
uint32_t mCycleLengthMs; // Length of time elapsed per cycle
bool mEnabled; // True if watchdog is enabled
+ std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
+
std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
};
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index d20638c..23a70db 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -501,12 +501,13 @@
ALOGV("Camera %d: Disconnecting device", mCameraId);
+ bool hasDeviceError = mDevice->hasDeviceError();
mDevice->disconnect();
CameraService::Client::disconnect();
int32_t closeLatencyMs = ns2ms(systemTime() - startTime);
- mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs);
+ mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs, hasDeviceError);
return res;
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e59b110..34b3948 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -2100,10 +2100,11 @@
mCompositeStreamMap.clear();
}
+ bool hasDeviceError = mDevice->hasDeviceError();
Camera2ClientBase::detachDevice();
int32_t closeLatencyMs = ns2ms(systemTime() - startTime);
- mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs);
+ mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs, hasDeviceError);
}
/** Device-related methods */
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index f06ed1c..0a2819c 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -158,7 +158,8 @@
}
/** Start watchdog thread */
- mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog = new CameraServiceWatchdog(TClientBase::mCameraIdStr,
+ mCameraServiceProxyWrapper);
res = mCameraServiceWatchdog->run("Camera2ClientBaseWatchdog");
if (res != OK) {
ALOGE("%s: Unable to start camera service watchdog thread: %s (%d)",
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 065d0d1..6f15653 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -475,6 +475,11 @@
virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
/**
+ * If the device is in eror state
+ */
+ virtual bool hasDeviceError() = 0;
+
+ /**
* Set bitmask for image dump flag
*/
void setImageDumpMask(int mask) { mImageDumpMask = mask; }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4047c13..c0e6a1b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -230,7 +230,7 @@
mInjectionMethods = createCamera3DeviceInjectionMethods(this);
/** Start watchdog thread */
- mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog = new CameraServiceWatchdog(mId, mCameraServiceProxyWrapper);
res = mCameraServiceWatchdog->run("CameraServiceWatchdog");
if (res != OK) {
SET_ERR_L("Unable to start camera service watchdog thread: %s (%d)",
@@ -4178,6 +4178,12 @@
mStreamUseCaseOverrides.clear();
}
+bool Camera3Device::hasDeviceError() {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+ return mStatus == STATUS_ERROR;
+}
+
void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
if (mNextRequests.empty()) {
return;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 21cf6fc..1635a90 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -313,6 +313,9 @@
// Get the status trackeer for the camera device
wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }
+ // Whether the device is in error state
+ bool hasDeviceError();
+
/**
* The injection camera session to replace the internal camera
* session.
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index bed576f..7aaf6b2 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -46,11 +46,13 @@
}
void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onClose(
- sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs) {
+ sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs,
+ bool deviceError) {
Mutex::Autolock l(mLock);
mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_CLOSED;
mSessionStats.mLatencyMs = latencyMs;
+ mSessionStats.mDeviceError = deviceError;
updateProxyDeviceState(proxyBinder);
}
@@ -259,7 +261,7 @@
sessionStats->onOpen(proxyBinder);
}
-void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs) {
+void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs, bool deviceError) {
std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
{
Mutex::Autolock l(mLock);
@@ -275,13 +277,15 @@
__FUNCTION__, id.c_str());
return;
}
+
mSessionStatsMap.erase(id);
- ALOGV("%s: Erasing id %s", __FUNCTION__, id.c_str());
+ ALOGV("%s: Erasing id %s, deviceError %d", __FUNCTION__, id.c_str(), deviceError);
}
- ALOGV("%s: id %s, latencyMs %d", __FUNCTION__, id.c_str(), latencyMs);
+ ALOGV("%s: id %s, latencyMs %d, deviceError %d", __FUNCTION__,
+ id.c_str(), latencyMs, deviceError);
sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
- sessionStats->onClose(proxyBinder, latencyMs);
+ sessionStats->onClose(proxyBinder, latencyMs, deviceError);
}
bool CameraServiceProxyWrapper::isCameraDisabled(int userId) {
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index 0f77fc9..f90a841 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -54,7 +54,8 @@
{ }
void onOpen(sp<hardware::ICameraServiceProxy>& proxyBinder);
- void onClose(sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs);
+ void onClose(sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs,
+ bool deviceError);
void onStreamConfigured(int operatingMode, bool internalReconfig, int32_t latencyMs);
void onActive(sp<hardware::ICameraServiceProxy>& proxyBinder, float maxPreviewFps);
void onIdle(sp<hardware::ICameraServiceProxy>& proxyBinder,
@@ -83,7 +84,7 @@
int32_t latencyMs);
// Close
- void logClose(const String8& id, int32_t latencyMs);
+ void logClose(const String8& id, int32_t latencyMs, bool deviceError);
// Stream configuration
void logStreamConfigured(const String8& id, int operatingMode, bool internalReconfig,