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

Commit 3060a2c8 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8540474 from d5e3531f to tm-release

Change-Id: I411220a0b2bce7e9a36a2119b60a3e11d111803b
parents 4d3b7736 d5e3531f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -2098,12 +2098,13 @@ status_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface) {
}

PipelineWatcher::Clock::duration CCodecBufferChannel::elapsed() {
    // When client pushed EOS, we want all the work to be done quickly.
    // Otherwise, component may have stalled work due to input starvation up to
    // the sum of the delay in the pipeline.
    // TODO(b/231253301): When client pushed EOS, the pipeline could have less
    //                    number of frames.
    size_t n = 0;
    if (!mInputMetEos) {
    size_t outputDelay = mOutput.lock()->outputDelay;
    {
        Mutexed<Input>::Locked input(mInput);
        n = input->inputDelay + input->pipelineDelay + outputDelay;
    }
+5 −3
Original line number Diff line number Diff line
@@ -564,9 +564,11 @@ status_t CameraSource::initWithCameraAccess(
    // Set the preview display. Skip this if mSurface is null because
    // applications may already set a surface to the camera.
    if (mSurface != NULL) {
        // This CHECK is good, since we just passed the lock/unlock
        // check earlier by calling mCamera->setParameters().
        CHECK_EQ((status_t)OK, mCamera->setPreviewTarget(mSurface));
        // Surface may be set incorrectly or could already be used even if we just
        // passed the lock/unlock check earlier by calling mCamera->setParameters().
        if ((err = mCamera->setPreviewTarget(mSurface)) != OK) {
            return err;
        }
    }

    // Use buffer queue to receive video buffers from camera
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ cc_library_shared {

    srcs: [
        "CameraService.cpp",
        "CameraServiceWatchdog.cpp",
        "CameraFlashlight.cpp",
        "common/Camera2ClientBase.cpp",
        "common/CameraDeviceBase.cpp",
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 "CameraServiceWatchdog"

#include "CameraServiceWatchdog.h"

namespace android {

bool CameraServiceWatchdog::threadLoop()
{
    {
        AutoMutex _l(mWatchdogLock);

        while (mPause) {
            mWatchdogCondition.wait(mWatchdogLock);
        }
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(mCycleLengthMs));

    {
        AutoMutex _l(mWatchdogLock);

        for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
            uint32_t currentThreadId = it->first;

            tidToCycleCounterMap[currentThreadId]++;

            if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
                ALOGW("CameraServiceWatchdog triggering kill for pid: %d", getpid());
                kill(getpid(), SIGKILL);
            }
        }
    }

    return true;
}

void CameraServiceWatchdog::requestExit()
{
    Thread::requestExit();

    AutoMutex _l(mWatchdogLock);

    tidToCycleCounterMap.clear();

    if (mPause) {
        mPause = false;
        mWatchdogCondition.signal();
    }
}

void CameraServiceWatchdog::stop(uint32_t tid)
{
    AutoMutex _l(mWatchdogLock);

    tidToCycleCounterMap.erase(tid);

    if (tidToCycleCounterMap.empty()) {
        mPause = true;
    }
}

void CameraServiceWatchdog::start(uint32_t tid)
{
    AutoMutex _l(mWatchdogLock);

    tidToCycleCounterMap[tid] = 0;

    if (mPause) {
        mPause = false;
        mWatchdogCondition.signal();
    }
}

}   // namespace android
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 */

/**
 * The CameraService watchdog is used to help detect bad states in the
 * Camera HAL. The threadloop uses cycle counters, assigned to each calling
 * thread, to monitor the elapsing time and kills the process when the
 * expected duration has exceeded.
 * Notes on multi-threaded behaviors:
 *    - The threadloop is blocked/paused when there are no calls being
 *   monitored.
 *   - The start and stop functions handle simultaneous call monitoring
 *   and single call monitoring differently. See function documentation for
 *   more details.
 */

#include <chrono>
#include <thread>
#include <time.h>
#include <utils/Thread.h>
#include <utils/Log.h>
#include <unordered_map>

// 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) \
        watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);

// Default cycles and cycle length values used to calculate permitted elapsed time
const static size_t   kMaxCycles     = 100;
const static uint32_t kCycleLengthMs = 100;

namespace android {

class CameraServiceWatchdog : public Thread {

public:
    explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
            mCycleLengthMs(kCycleLengthMs) {};

    explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs) :
            mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs) {};

    virtual ~CameraServiceWatchdog() {};

    virtual void requestExit();

    /** Used to wrap monitored calls in start and stop functions using custom timer values */
    template<typename T>
    auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
        auto res = NULL;

        if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
            // Create another instance of the watchdog to prevent disruption
            // of timer for current monitored calls
            sp<CameraServiceWatchdog> tempWatchdog =
                    new CameraServiceWatchdog(cycles, cycleLength);
            tempWatchdog->run("CameraServiceWatchdog");
            res = tempWatchdog->watchThread(func, tid);
            tempWatchdog->requestExit();
            tempWatchdog.clear();
        } else {
            // If custom timer values are equivalent to set class timer values, use
            // current thread
            res = watchThread(func, tid);
        }

        return res;
    }

    /** Used to wrap monitored calls in start and stop functions using class timer values */
    template<typename T>
    auto watchThread(T func, uint32_t tid) {
        auto res = NULL;

        start(tid);
        res = func();
        stop(tid);

        return res;
    }

private:

    /**
     * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
     * start() unblocks and starts the watchdog
     */
    void start(uint32_t tid);

    /**
     * If there are no calls left to be monitored, stop blocks/pauses threadloop
     * otherwise stop() erases the cycle counter to end watchdog for the calling thread
     */
    void stop(uint32_t tid);

    virtual bool    threadLoop();

    Mutex           mWatchdogLock;        // Lock for condition variable
    Condition       mWatchdogCondition;   // Condition variable for stop/start
    bool            mPause;               // True if thread is currently paused
    uint32_t        mMaxCycles;           // Max cycles
    uint32_t        mCycleLengthMs;       // Length of time elapsed per cycle

    std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
};

}   // namespace android
Loading