Camera:Retain dumpsys logs from previous open session.
When cameraserver is started and no devices have been open yet, there
will be no previous retained info in the dumpsys.If a single device is
open and closed, dumpsys taken during closed camera will show the
previous open session info.
If multiple devices are open and any of the devices disconnect, info for
all the devices open will be retained and will be available in dumpsys
output.
All the cached data will be cleared during new connect device session.
bug: 185140738
Test: Tested locally. Camera CTS tests pass.
Change-Id: I60470ab148c5df2a5de0cf3abcf02e07cbc99a0d
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 83d2bc9..9c7b506 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -131,6 +131,8 @@
"android.permission.CAMERA_OPEN_CLOSE_LISTENER");
static const String16
sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
+static int sMemFd = -1;
+const char *sFileName = "lastOpenSessionDumpFile";
static constexpr int32_t kVendorClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
@@ -148,6 +150,11 @@
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
+
+ sMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+ if (sMemFd == -1) {
+ ALOGE("%s:Error while creating the file:%s", __FUNCTION__, sFileName);
+ }
}
void CameraService::onFirstRef()
@@ -1637,6 +1644,21 @@
}
*device = client;
+
+ Mutex::Autolock lock(mServiceLock);
+
+ // Clear the previous cached logs and reposition the
+ // file offset to beginning of the file to log new data.
+ // If either truncate or lseek fails, close the previous file and create a new one.
+ if ((ftruncate(sMemFd, 0) == -1) || (lseek(sMemFd, 0, SEEK_SET) == -1)) {
+ ALOGE("%s: Error while truncating the file:%s", __FUNCTION__, sFileName);
+ // Close the previous memfd.
+ close(sMemFd);
+ // If failure to wipe the data, then create a new file and
+ // assign the new value to sMemFd.
+ sMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+ }
+
return ret;
}
@@ -3832,6 +3854,27 @@
return locked;
}
+void CameraService::cacheDump() {
+ const Vector<String16>& args = Vector<String16>();
+ ATRACE_CALL();
+
+ Mutex::Autolock lock(mServiceLock);
+
+ Mutex::Autolock l(mCameraStatesLock);
+
+ // Start collecting the info for open sessions and store it in temp file.
+ for (const auto& state : mCameraStates) {
+ String8 cameraId = state.first;
+
+ auto clientDescriptor = mActiveClientManager.get(cameraId);
+ if (clientDescriptor != nullptr) {
+ dprintf(sMemFd, "== Camera device %s dynamic info: ==\n", cameraId.string());
+ // Log the current open session info before device is disconnected.
+ dumpOpenSessionClientLogs(sMemFd, args, cameraId);
+ }
+ }
+}
+
status_t CameraService::dump(int fd, const Vector<String16>& args) {
ATRACE_CALL();
@@ -3898,21 +3941,10 @@
auto clientDescriptor = mActiveClientManager.get(cameraId);
if (clientDescriptor != nullptr) {
- dprintf(fd, " Device %s is open. Client instance dump:\n",
- cameraId.string());
- dprintf(fd, " Client priority score: %d state: %d\n",
- clientDescriptor->getPriority().getScore(),
- clientDescriptor->getPriority().getState());
- dprintf(fd, " Client PID: %d\n", clientDescriptor->getOwnerId());
-
- auto client = clientDescriptor->getValue();
- dprintf(fd, " Client package: %s\n",
- String8(client->getPackageName()).string());
-
- client->dumpClient(fd, args);
+ // log the current open session info
+ dumpOpenSessionClientLogs(fd, args, cameraId);
} else {
- dprintf(fd, " Device %s is closed, no client instance\n",
- cameraId.string());
+ dumpClosedSessionClientLogs(fd, cameraId);
}
}
@@ -3969,9 +4001,53 @@
}
}
}
+
+ Mutex::Autolock lock(mServiceLock);
+
+ // Dump info from previous open sessions.
+ // Reposition the offset to beginning of the file before reading
+
+ if ((sMemFd >= 0) && (lseek(sMemFd, 0, SEEK_SET) != -1)) {
+ dprintf(fd, "\n**********Dumpsys from previous open session**********\n");
+ ssize_t size_read;
+ char buf[4096];
+ while ((size_read = read(sMemFd, buf, (sizeof(buf) - 1))) > 0) {
+ // Read data from file to a small buffer and write it to fd.
+ write(fd, buf, size_read);
+ if (size_read == -1){
+ ALOGE("%s: Error during reading the file:%s", __FUNCTION__, sFileName);
+ break;
+ }
+ }
+ dprintf(fd, "\n**********End of Dumpsys from previous open session**********\n");
+ } else {
+ ALOGE("%s: Error during reading the file:%s", __FUNCTION__, sFileName);
+ }
return NO_ERROR;
}
+void CameraService::dumpOpenSessionClientLogs(int fd,
+ const Vector<String16>& args, const String8& cameraId) {
+ auto clientDescriptor = mActiveClientManager.get(cameraId);
+ dprintf(fd, " Device %s is open. Client instance dump:\n",
+ cameraId.string());
+ dprintf(fd, " Client priority score: %d state: %d\n",
+ clientDescriptor->getPriority().getScore(),
+ clientDescriptor->getPriority().getState());
+ dprintf(fd, " Client PID: %d\n", clientDescriptor->getOwnerId());
+
+ auto client = clientDescriptor->getValue();
+ dprintf(fd, " Client package: %s\n",
+ String8(client->getPackageName()).string());
+
+ client->dumpClient(fd, args);
+}
+
+void CameraService::dumpClosedSessionClientLogs(int fd, const String8& cameraId) {
+ dprintf(fd, " Device %s is closed, no client instance\n",
+ cameraId.string());
+}
+
void CameraService::dumpEventLog(int fd) {
dprintf(fd, "\n== Camera service events log (most recent at top): ==\n");
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d1ed59a..7b0037e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -202,6 +202,8 @@
std::vector<hardware::CameraStatus>* cameraStatuses, bool isVendor = false,
bool isProcessLocalTest = false);
+ void cacheDump();
+
// Monitored UIDs availability notification
void notifyMonitoredUids();
@@ -785,6 +787,12 @@
// Return NO_ERROR if the device with a give ID can be connected to
status_t checkIfDeviceIsUsable(const String8& cameraId) const;
+ // Adds client logs during open session to the file pointed by fd.
+ void dumpOpenSessionClientLogs(int fd, const Vector<String16>& args, const String8& cameraId);
+
+ // Adds client logs during closed session to the file pointed by fd.
+ void dumpClosedSessionClientLogs(int fd, const String8& cameraId);
+
// Container for managing currently active application-layer clients
CameraClientManager mActiveClientManager;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ce479a1..56e5ae1 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -195,6 +195,8 @@
ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
+ // Before detaching the device, cache the info from current open session
+ Camera2ClientBase::getCameraService()->cacheDump();
detachDevice();
CameraService::BasicClient::disconnect();