diff options
Diffstat (limited to 'services/camera')
9 files changed, 180 insertions, 41 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 527e80b..6f073ed 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -33,6 +33,7 @@  #include <binder/MemoryBase.h>  #include <binder/MemoryHeapBase.h>  #include <binder/ProcessInfoService.h> +#include <camera/ICameraServiceProxy.h>  #include <cutils/atomic.h>  #include <cutils/properties.h>  #include <gui/Surface.h> @@ -230,6 +231,18 @@ void CameraService::onFirstRef()      }      CameraDeviceFactory::registerService(this); + +    CameraService::pingCameraServiceProxy(); +} + +void CameraService::pingCameraServiceProxy() { +    sp<IServiceManager> sm = defaultServiceManager(); +    sp<IBinder> binder = sm->getService(String16("media.camera.proxy")); +    if (binder == nullptr) { +        return; +    } +    sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder); +    proxyBinder->pingForUserUpdate();  }  CameraService::~CameraService() { @@ -992,6 +1005,10 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien                          "(PID %" PRId32 ", priority %" PRId32 ")", i->getKey().string(),                          String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),                          i->getPriority()); +                ALOGE("   Conflicts with: Device %s, client package %s (PID %" +                        PRId32 ", priority %" PRId32 ")", i->getKey().string(), +                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(), +                        i->getPriority());              }              // Log the client's attempt @@ -2051,7 +2068,7 @@ String8 CameraService::CameraClientManager::toString() const {          auto conflicting = i->getConflicting();          auto clientSp = i->getValue();          String8 packageName; -        userid_t clientUserId; +        userid_t clientUserId = 0;          if (clientSp.get() != nullptr) {              packageName = String8{clientSp->getPackageName()};              uid_t clientUid = clientSp->getClientUid(); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 2e4743f..3298772 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -720,6 +720,8 @@ private:      static String8 toString(std::set<userid_t> intSet); +    static void pingCameraServiceProxy(); +  };  template<class Func> diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 05ede92..f2d6ab2 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -1881,6 +1881,16 @@ void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {      mCaptureSequencer->notifyAutoExposure(newState, triggerId);  } +void Camera2Client::notifyShutter(const CaptureResultExtras& resultExtras, +                                  nsecs_t timestamp) { +    (void)resultExtras; +    (void)timestamp; + +    ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64, +            __FUNCTION__, resultExtras.requestId, timestamp); +    mCaptureSequencer->notifyShutter(resultExtras, timestamp); +} +  camera2::SharedParameters& Camera2Client::getParameters() {      return mParameters;  } diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h index a988037..3784aab 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.h +++ b/services/camera/libcameraservice/api1/Camera2Client.h @@ -106,6 +106,8 @@ public:      virtual void notifyAutoFocus(uint8_t newState, int triggerId);      virtual void notifyAutoExposure(uint8_t newState, int triggerId); +    virtual void notifyShutter(const CaptureResultExtras& resultExtras, +                               nsecs_t timestamp);      /**       * Interface used by independent components of Camera2Client. diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp index 9849f4d..d847e0f 100644 --- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp +++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp @@ -43,6 +43,8 @@ CaptureSequencer::CaptureSequencer(wp<Camera2Client> client):          mNewFrameReceived(false),          mNewCaptureReceived(false),          mShutterNotified(false), +        mHalNotifiedShutter(false), +        mShutterCaptureId(-1),          mClient(client),          mCaptureState(IDLE),          mStateTransitionCount(0), @@ -106,6 +108,16 @@ void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) {      }  } +void CaptureSequencer::notifyShutter(const CaptureResultExtras& resultExtras, +                                     nsecs_t timestamp) { +    ATRACE_CALL(); +    Mutex::Autolock l(mInputMutex); +    if (!mHalNotifiedShutter && resultExtras.requestId == mShutterCaptureId) { +        mHalNotifiedShutter = true; +        mShutterNotifySignal.signal(); +    } +} +  void CaptureSequencer::onResultAvailable(const CaptureResult &result) {      ATRACE_CALL();      ALOGV("%s: New result available.", __FUNCTION__); @@ -335,6 +347,11 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStart(      } else {          nextState = STANDARD_START;      } +    { +        Mutex::Autolock l(mInputMutex); +        mShutterCaptureId = mCaptureId; +        mHalNotifiedShutter = false; +    }      mShutterNotified = false;      return nextState; @@ -541,6 +558,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture(              return DONE;          }      } +      // TODO: Capture should be atomic with setStreamingRequest here      res = client->getCameraDevice()->capture(captureCopy);      if (res != OK) { @@ -560,6 +578,31 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(      ATRACE_CALL();      Mutex::Autolock l(mInputMutex); + +    // Wait for shutter callback +    while (!mHalNotifiedShutter) { +        if (mTimeoutCount <= 0) { +            break; +        } +        res = mShutterNotifySignal.waitRelative(mInputMutex, kWaitDuration); +        if (res == TIMED_OUT) { +            mTimeoutCount--; +            return STANDARD_CAPTURE_WAIT; +        } +    } + +    if (mHalNotifiedShutter) { +        if (!mShutterNotified) { +            SharedParameters::Lock l(client->getParameters()); +            /* warning: this also locks a SharedCameraCallbacks */ +            shutterNotifyLocked(l.mParameters, client, mMsgType); +            mShutterNotified = true; +        } +    } else if (mTimeoutCount <= 0) { +        ALOGW("Timed out waiting for shutter notification"); +        return DONE; +    } +      // Wait for new metadata result (mNewFrame)      while (!mNewFrameReceived) {          res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration); @@ -569,15 +612,6 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(          }      } -    // Approximation of the shutter being closed -    // - TODO: use the hal3 exposure callback in Camera3Device instead -    if (mNewFrameReceived && !mShutterNotified) { -        SharedParameters::Lock l(client->getParameters()); -        /* warning: this also locks a SharedCameraCallbacks */ -        shutterNotifyLocked(l.mParameters, client, mMsgType); -        mShutterNotified = true; -    } -      // Wait until jpeg was captured by JpegProcessor      while (mNewFrameReceived && !mNewCaptureReceived) {          res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration); @@ -591,6 +625,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(          return DONE;      }      if (mNewFrameReceived && mNewCaptureReceived) { +          if (mNewFrameId != mCaptureId) {              ALOGW("Mismatched capture frame IDs: Expected %d, got %d",                      mCaptureId, mNewFrameId); @@ -667,7 +702,6 @@ CaptureSequencer::CaptureState CaptureSequencer::manageBurstCaptureWait(          sp<Camera2Client> &/*client*/) {      status_t res;      ATRACE_CALL(); -      while (!mNewCaptureReceived) {          res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);          if (res == TIMED_OUT) { diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h index d42ab13..10252fb 100644 --- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h +++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h @@ -62,6 +62,10 @@ class CaptureSequencer:      // Notifications about AE state changes      void notifyAutoExposure(uint8_t newState, int triggerId); +    // Notifications about shutter (capture start) +    void notifyShutter(const CaptureResultExtras& resultExtras, +                       nsecs_t timestamp); +      // Notification from the frame processor      virtual void onResultAvailable(const CaptureResult &result); @@ -95,7 +99,10 @@ class CaptureSequencer:      sp<MemoryBase> mCaptureBuffer;      Condition mNewCaptureSignal; -    bool mShutterNotified; +    bool mShutterNotified; // Has CaptureSequencer sent shutter to Client +    bool mHalNotifiedShutter; // Has HAL sent shutter to CaptureSequencer +    int32_t mShutterCaptureId; // The captureId which is waiting for shutter notification +    Condition mShutterNotifySignal;      /**       * Internal to CaptureSequencer diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp index c662853..2f0117d 100644 --- a/services/camera/libcameraservice/common/CameraModule.cpp +++ b/services/camera/libcameraservice/common/CameraModule.cpp @@ -31,7 +31,7 @@ void CameraModule::deriveCameraCharacteristicsKeys(      // Keys added in HAL3.3      if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) { -        const size_t NUM_DERIVED_KEYS_HAL3_3 = 3; +        const size_t NUM_DERIVED_KEYS_HAL3_3 = 5;          Vector<uint8_t> controlModes;          uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;          chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1); @@ -80,6 +80,29 @@ void CameraModule::deriveCameraCharacteristicsKeys(          chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes); +        entry = chars.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS); +        // HAL3.2 devices passing existing CTS test should all support all LSC modes and LSC map +        bool lensShadingModeSupported = false; +        if (entry.count > 0) { +            for (size_t i = 0; i < entry.count; i++) { +                if (entry.data.i32[i] == ANDROID_SHADING_MODE) { +                    lensShadingModeSupported = true; +                    break; +                } +            } +        } +        Vector<uint8_t> lscModes; +        Vector<uint8_t> lscMapModes; +        lscModes.push(ANDROID_SHADING_MODE_FAST); +        lscModes.push(ANDROID_SHADING_MODE_HIGH_QUALITY); +        lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF); +        if (lensShadingModeSupported) { +            lscModes.push(ANDROID_SHADING_MODE_OFF); +            lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON); +        } +        chars.update(ANDROID_SHADING_AVAILABLE_MODES, lscModes); +        chars.update(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, lscMapModes); +          entry = chars.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);          Vector<int32_t> availableCharsKeys;          availableCharsKeys.setCapacity(entry.count + NUM_DERIVED_KEYS_HAL3_3); @@ -87,9 +110,12 @@ void CameraModule::deriveCameraCharacteristicsKeys(              availableCharsKeys.push(entry.data.i32[i]);          }          availableCharsKeys.push(ANDROID_CONTROL_AE_LOCK_AVAILABLE); -        availableCharsKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE); +        availableCharsKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE);          availableCharsKeys.push(ANDROID_CONTROL_AVAILABLE_MODES); +        availableCharsKeys.push(ANDROID_SHADING_AVAILABLE_MODES); +        availableCharsKeys.push(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES);          chars.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, availableCharsKeys); +      }      return;  } diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 445c9c2..45d9421 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -2613,6 +2613,21 @@ status_t Camera3Device::RequestThread::clear(      if (listener != NULL) {          for (RequestList::iterator it = mRequestQueue.begin();                   it != mRequestQueue.end(); ++it) { +            // Abort the input buffers for reprocess requests. +            if ((*it)->mInputStream != NULL) { +                camera3_stream_buffer_t inputBuffer; +                status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer); +                if (res != OK) { +                    ALOGW("%s: %d: couldn't get input buffer while clearing the request " +                            "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res); +                } else { +                    res = (*it)->mInputStream->returnInputBuffer(inputBuffer); +                    if (res != OK) { +                        ALOGE("%s: %d: couldn't return input buffer while clearing the request " +                                "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res); +                    } +                } +            }              // Set the frame number this request would have had, if it              // had been submitted; this frame number will not be reused.              // The requestId and burstId fields were set when the request was @@ -2752,29 +2767,11 @@ bool Camera3Device::RequestThread::threadLoop() {                 __FUNCTION__);      } -    camera3_stream_buffer_t inputBuffer;      uint32_t totalNumBuffers = 0;      // Fill in buffers -      if (nextRequest->mInputStream != NULL) { -        res = nextRequest->mInputStream->getInputBuffer(&inputBuffer); -        if (res != OK) { -            // Can't get input buffer from gralloc queue - this could be due to -            // disconnected queue or other producer misbehavior, so not a fatal -            // error -            ALOGE("RequestThread: Can't get input buffer, skipping request:" -                    " %s (%d)", strerror(-res), res); -            Mutex::Autolock l(mRequestLock); -            if (mListener != NULL) { -                mListener->notifyError( -                        ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, -                        nextRequest->mResultExtras); -            } -            cleanUpFailedRequest(request, nextRequest, outputBuffers); -            return true; -        } -        request.input_buffer = &inputBuffer; +        request.input_buffer = &nextRequest->mInputBuffer;          totalNumBuffers += 1;      } else {          request.input_buffer = NULL; @@ -2792,11 +2789,13 @@ bool Camera3Device::RequestThread::threadLoop() {              // error              ALOGE("RequestThread: Can't get output buffer, skipping request:"                      " %s (%d)", strerror(-res), res); -            Mutex::Autolock l(mRequestLock); -            if (mListener != NULL) { -                mListener->notifyError( -                        ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, -                        nextRequest->mResultExtras); +            { +                Mutex::Autolock l(mRequestLock); +                if (mListener != NULL) { +                    mListener->notifyError( +                            ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, +                            nextRequest->mResultExtras); +                }              }              cleanUpFailedRequest(request, nextRequest, outputBuffers);              return true; @@ -2865,6 +2864,12 @@ bool Camera3Device::RequestThread::threadLoop() {          nextRequest->mSettings.unlock(request.settings);      } +    // Unset as current request +    { +        Mutex::Autolock l(mRequestLock); +        mNextRequest.clear(); +    } +      // Remove any previously queued triggers (after unlock)      res = removeTriggers(mPrevRequest);      if (res != OK) { @@ -2890,6 +2895,13 @@ bool Camera3Device::RequestThread::isStreamPending(          sp<Camera3StreamInterface>& stream) {      Mutex::Autolock l(mRequestLock); +    if (mNextRequest != nullptr) { +        for (const auto& s : mNextRequest->mOutputStreams) { +            if (stream == s) return true; +        } +        if (stream == mNextRequest->mInputStream) return true; +    } +      for (const auto& request : mRequestQueue) {          for (const auto& s : request->mOutputStreams) {              if (stream == s) return true; @@ -2915,15 +2927,18 @@ void Camera3Device::RequestThread::cleanUpFailedRequest(      if (request.settings != NULL) {          nextRequest->mSettings.unlock(request.settings);      } -    if (request.input_buffer != NULL) { -        request.input_buffer->status = CAMERA3_BUFFER_STATUS_ERROR; -        nextRequest->mInputStream->returnInputBuffer(*(request.input_buffer)); +    if (nextRequest->mInputStream != NULL) { +        nextRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR; +        nextRequest->mInputStream->returnInputBuffer(nextRequest->mInputBuffer);      }      for (size_t i = 0; i < request.num_output_buffers; i++) {          outputBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;          nextRequest->mOutputStreams.editItemAt(i)->returnBuffer(              outputBuffers[i], 0);      } + +    Mutex::Autolock l(mRequestLock); +    mNextRequest.clear();  }  sp<Camera3Device::CaptureRequest> @@ -3006,7 +3021,28 @@ sp<Camera3Device::CaptureRequest>          nextRequest->mResultExtras.frameNumber = mFrameNumber++;          nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;          nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId; + +        // Since RequestThread::clear() removes buffers from the input stream, +        // get the right buffer here before unlocking mRequestLock +        if (nextRequest->mInputStream != NULL) { +            res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer); +            if (res != OK) { +                // Can't get input buffer from gralloc queue - this could be due to +                // disconnected queue or other producer misbehavior, so not a fatal +                // error +                ALOGE("%s: Can't get input buffer, skipping request:" +                        " %s (%d)", __FUNCTION__, strerror(-res), res); +                if (mListener != NULL) { +                    mListener->notifyError( +                            ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, +                            nextRequest->mResultExtras); +                } +                return NULL; +            } +        }      } +    mNextRequest = nextRequest; +      return nextRequest;  } diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 4fbcb2e..b9313fc 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -234,6 +234,7 @@ class Camera3Device :        public:          CameraMetadata                      mSettings;          sp<camera3::Camera3Stream>          mInputStream; +        camera3_stream_buffer_t             mInputBuffer;          Vector<sp<camera3::Camera3OutputStreamInterface> >                                              mOutputStreams;          CaptureResultExtras                 mResultExtras; @@ -501,6 +502,10 @@ class Camera3Device :          Condition          mRequestSignal;          RequestList        mRequestQueue;          RequestList        mRepeatingRequests; +        // The next request being prepped for submission to the HAL, no longer +        // on the request queue. Read-only even with mRequestLock held, outside +        // of threadLoop +        sp<const CaptureRequest> mNextRequest;          bool               mReconfigured;  | 
