Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30dd3ee6 authored by Rucha Katakwar's avatar Rucha Katakwar
Browse files

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
parent 632eedc2
Loading
Loading
Loading
Loading
+90 −14
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ static const String16 sCameraOpenCloseListenerPermission(
        "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 @@ CameraService::CameraService() :
        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 @@ Status CameraService::connectDevice(
    }

    *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 @@ static bool tryLock(Mutex& mutex)
    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 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {

        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 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
            }
        }
    }

    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");

+8 −0
Original line number Diff line number Diff line
@@ -202,6 +202,8 @@ public:
            std::vector<hardware::CameraStatus>* cameraStatuses, bool isVendor = false,
            bool isProcessLocalTest = false);

    void cacheDump();

    // Monitored UIDs availability notification
    void                notifyMonitoredUids();

@@ -785,6 +787,12 @@ private:
    // 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;

+2 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ binder::Status Camera2ClientBase<TClientBase>::disconnect() {

    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();