diff options
| -rw-r--r-- | camera/ICameraService.cpp | 11 | ||||
| -rw-r--r-- | include/camera/ICameraService.h | 10 | ||||
| -rw-r--r-- | include/media/stagefright/ACodec.h | 1 | ||||
| -rw-r--r-- | media/libstagefright/ACodec.cpp | 9 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 102 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.h | 8 | ||||
| -rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.cpp | 63 | ||||
| -rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.h | 11 | 
8 files changed, 179 insertions, 36 deletions
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp index 7c9720f..b359f57 100644 --- a/camera/ICameraService.cpp +++ b/camera/ICameraService.cpp @@ -94,11 +94,18 @@ public:      {      } -    // get number of cameras available +    // get number of cameras available that support standard camera operations      virtual int32_t getNumberOfCameras()      { +        return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE); +    } + +    // get number of cameras available of a given type +    virtual int32_t getNumberOfCameras(int type) +    {          Parcel data, reply;          data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); +        data.writeInt32(type);          remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);          if (readExceptionCode(reply)) return 0; @@ -337,7 +344,7 @@ status_t BnCameraService::onTransact(          case GET_NUMBER_OF_CAMERAS: {              CHECK_INTERFACE(ICameraService, data, reply);              reply->writeNoException(); -            reply->writeInt32(getNumberOfCameras()); +            reply->writeInt32(getNumberOfCameras(data.readInt32()));              return NO_ERROR;          } break;          case GET_CAMERA_INFO: { diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h index 5f85635..1b68b5f 100644 --- a/include/camera/ICameraService.h +++ b/include/camera/ICameraService.h @@ -64,6 +64,11 @@ public:      };      enum { +        CAMERA_TYPE_BACKWARD_COMPATIBLE = 0, +        CAMERA_TYPE_ALL = 1, +    }; + +    enum {          CAMERA_HAL_API_VERSION_UNSPECIFIED = -1      }; @@ -81,7 +86,12 @@ public:  public:      DECLARE_META_INTERFACE(CameraService); +    // Get the number of cameras that support basic color camera operation +    // (type CAMERA_TYPE_BACKWARD_COMPATIBLE)      virtual int32_t  getNumberOfCameras() = 0; +    // Get the number of cameras of the specified type, one of CAMERA_TYPE_* +    // enums +    virtual int32_t  getNumberOfCameras(int cameraType) = 0;      virtual status_t getCameraInfo(int cameraId,              /*out*/              struct CameraInfo* cameraInfo) = 0; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 05f6786..8b5b862 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -236,6 +236,7 @@ private:      bool mSentFormat;      bool mIsVideo;      bool mIsEncoder; +    bool mFatalError;      bool mShutdownInProgress;      bool mExplicitShutdown; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index fb654b8..8d9bd21 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -497,6 +497,7 @@ ACodec::ACodec()        mSentFormat(false),        mIsVideo(false),        mIsEncoder(false), +      mFatalError(false),        mShutdownInProgress(false),        mExplicitShutdown(false),        mEncoderDelay(0), @@ -1312,6 +1313,11 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {          return NULL;      } +    if (mFatalError) { +        ALOGW("not dequeuing from native window due to fatal error"); +        return NULL; +    } +      int fenceFd = -1;      do {          status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); @@ -4460,6 +4466,9 @@ void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {              ALOGW("Invalid OMX error %#x", error);          }      } + +    mFatalError = true; +      notify->setInt32("err", internalError);      notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.      notify->post(); diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 92df4e3..43a8ec4 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -171,6 +171,7 @@ void CameraService::onFirstRef()      }      mNumberOfCameras = mModule->getNumberOfCameras(); +    mNumberOfNormalCameras = mNumberOfCameras;      mFlashlight = new CameraFlashlight(*mModule, *this);      status_t res = mFlashlight->findFlashUnits(); @@ -179,27 +180,41 @@ void CameraService::onFirstRef()          ALOGE("Failed to find flash units.");      } +    int latestStrangeCameraId = INT_MAX;      for (int i = 0; i < mNumberOfCameras; i++) {          String8 cameraId = String8::format("%d", i); +        // Get camera info + +        struct camera_info info; +        bool haveInfo = true; +        status_t rc = mModule->getCameraInfo(i, &info); +        if (rc != NO_ERROR) { +            ALOGE("%s: Received error loading camera info for device %d, cost and" +                    " conflicting devices fields set to defaults for this device.", +                    __FUNCTION__, i); +            haveInfo = false; +        } + +        // Check for backwards-compatibility support +        if (haveInfo) { +            if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) { +                delete mModule; +                mModule = nullptr; +                return; +            } +        } +          // Defaults to use for cost and conflicting devices          int cost = 100;          char** conflicting_devices = nullptr;          size_t conflicting_devices_length = 0;          // If using post-2.4 module version, query the cost + conflicting devices from the HAL -        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) { -            struct camera_info info; -            status_t rc = mModule->getCameraInfo(i, &info); -            if (rc == NO_ERROR) { -                cost = info.resource_cost; -                conflicting_devices = info.conflicting_devices; -                conflicting_devices_length = info.conflicting_devices_length; -            } else { -                ALOGE("%s: Received error loading camera info for device %d, cost and" -                        " conflicting devices fields set to defaults for this device.", -                        __FUNCTION__, i); -            } +        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) { +            cost = info.resource_cost; +            conflicting_devices = info.conflicting_devices; +            conflicting_devices_length = info.conflicting_devices_length;          }          std::set<String8> conflicting; @@ -382,9 +397,21 @@ void CameraService::onTorchStatusChangedLocked(const String8& cameraId,      }  } -  int32_t CameraService::getNumberOfCameras() { -    return mNumberOfCameras; +    return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE); +} + +int32_t CameraService::getNumberOfCameras(int type) { +    switch (type) { +        case CAMERA_TYPE_BACKWARD_COMPATIBLE: +            return mNumberOfNormalCameras; +        case CAMERA_TYPE_ALL: +            return mNumberOfCameras; +        default: +            ALOGW("%s: Unknown camera type %d, returning 0", +                    __FUNCTION__, type); +            return 0; +    }  }  status_t CameraService::getCameraInfo(int cameraId, @@ -1494,6 +1521,53 @@ bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {  } +/** + * Check camera capabilities, such as support for basic color operation + */ +int CameraService::checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId) { + +    // Assume all devices pre-v3.3 are backward-compatible +    bool isBackwardCompatible = true; +    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0 +            && info.device_version >= CAMERA_DEVICE_API_VERSION_3_3) { +        isBackwardCompatible = false; +        status_t res; +        camera_metadata_ro_entry_t caps; +        res = find_camera_metadata_ro_entry( +            info.static_camera_characteristics, +            ANDROID_REQUEST_AVAILABLE_CAPABILITIES, +            &caps); +        if (res != 0) { +            ALOGW("%s: Unable to find camera capabilities for camera device %d", +                    __FUNCTION__, id); +            caps.count = 0; +        } +        for (size_t i = 0; i < caps.count; i++) { +            if (caps.data.u8[i] == +                    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) { +                isBackwardCompatible = true; +                break; +            } +        } +    } + +    if (!isBackwardCompatible) { +        mNumberOfNormalCameras--; +        *latestStrangeCameraId = id; +    } else { +        if (id > *latestStrangeCameraId) { +            ALOGE("%s: Normal camera ID %d higher than strange camera ID %d. " +                    "This is not allowed due backward-compatibility requirements", +                    __FUNCTION__, id, *latestStrangeCameraId); +            logServiceError("Invalid order of camera devices", ENODEV); +            mNumberOfCameras = 0; +            mNumberOfNormalCameras = 0; +            return INVALID_OPERATION; +        } +    } +    return OK; +} +  std::shared_ptr<CameraService::CameraState> CameraService::getCameraState(          const String8& cameraId) const {      std::shared_ptr<CameraState> state; diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 3298772..7f4d43f 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -100,7 +100,9 @@ public:      /////////////////////////////////////////////////////////////////////      // ICameraService +    virtual int32_t     getNumberOfCameras(int type);      virtual int32_t     getNumberOfCameras(); +      virtual status_t    getCameraInfo(int cameraId,                                        struct CameraInfo* cameraInfo);      virtual status_t    getCameraCharacteristics(int cameraId, @@ -509,6 +511,11 @@ private:      std::set<userid_t> mAllowedUsers;      /** +     * Check camera capabilities, such as support for basic color operation +     */ +    int checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId); + +    /**       * Get the camera state for a given camera id.       *       * This acquires mCameraStatesLock. @@ -610,6 +617,7 @@ private:      void dumpEventLog(int fd);      int                 mNumberOfCameras; +    int                 mNumberOfNormalCameras;      // sounds      MediaPlayer*        newMediaPlayer(const char *file); diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 0a4440f..0c941fb 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -60,6 +60,7 @@ Camera3Device::Camera3Device(int id):          mIsConstrainedHighSpeedConfiguration(false),          mHal3Device(NULL),          mStatus(STATUS_UNINITIALIZED), +        mStatusWaiters(0),          mUsePartialResult(false),          mNumPartialResults(1),          mNextResultFrameNumber(0), @@ -191,7 +192,8 @@ status_t Camera3Device::initialize(CameraModule *module)      mDeviceVersion = device->common.version;      mDeviceInfo = info.static_camera_characteristics;      mHal3Device = device; -    mStatus = STATUS_UNCONFIGURED; + +    internalUpdateStatusLocked(STATUS_UNCONFIGURED);      mNextStreamId = 0;      mDummyStreamId = NO_STREAM;      mNeedConfig = true; @@ -296,7 +298,7 @@ status_t Camera3Device::disconnect() {              mHal3Device = NULL;          } -        mStatus = STATUS_UNINITIALIZED; +        internalUpdateStatusLocked(STATUS_UNINITIALIZED);      }      ALOGV("%s: X", __FUNCTION__); @@ -1166,6 +1168,13 @@ status_t Camera3Device::waitUntilDrainedLocked() {      return res;  } + +void Camera3Device::internalUpdateStatusLocked(Status status) { +    mStatus = status; +    mRecentStatusUpdates.add(mStatus); +    mStatusChanged.broadcast(); +} +  // Pause to reconfigure  status_t Camera3Device::internalPauseAndWaitLocked() {      mRequestThread->setPaused(true); @@ -1196,23 +1205,40 @@ status_t Camera3Device::internalResumeLocked() {      return OK;  } -status_t Camera3Device::waitUntilStateThenRelock(bool active, -        nsecs_t timeout) { +status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {      status_t res = OK; -    if (active == (mStatus == STATUS_ACTIVE)) { -        // Desired state already reached -        return res; + +    size_t startIndex = 0; +    if (mStatusWaiters == 0) { +        // Clear the list of recent statuses if there are no existing threads waiting on updates to +        // this status list +        mRecentStatusUpdates.clear(); +    } else { +        // If other threads are waiting on updates to this status list, set the position of the +        // first element that this list will check rather than clearing the list. +        startIndex = mRecentStatusUpdates.size();      } +    mStatusWaiters++; +      bool stateSeen = false;      do { -        mRecentStatusUpdates.clear(); +        if (active == (mStatus == STATUS_ACTIVE)) { +            // Desired state is current +            break; +        }          res = mStatusChanged.waitRelative(mLock, timeout);          if (res != OK) break; -        // Check state change history during wait -        for (size_t i = 0; i < mRecentStatusUpdates.size(); i++) { +        // This is impossible, but if not, could result in subtle deadlocks and invalid state +        // transitions. +        LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(), +                "%s: Skipping status updates in Camera3Device, may result in deadlock.", +                __FUNCTION__); + +        // Encountered desired state since we began waiting +        for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {              if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {                  stateSeen = true;                  break; @@ -1220,6 +1246,8 @@ status_t Camera3Device::waitUntilStateThenRelock(bool active,          }      } while (!stateSeen); +    mStatusWaiters--; +      return res;  } @@ -1461,9 +1489,7 @@ void Camera3Device::notifyStatus(bool idle) {          }          ALOGV("%s: Camera %d: Now %s", __FUNCTION__, mId,                  idle ? "idle" : "active"); -        mStatus = idle ? STATUS_CONFIGURED : STATUS_ACTIVE; -        mRecentStatusUpdates.add(mStatus); -        mStatusChanged.signal(); +        internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);          // Skip notifying listener if we're doing some user-transparent          // state changes @@ -1672,7 +1698,7 @@ status_t Camera3Device::configureStreamsLocked() {          // Return state to that at start of call, so that future configures          // properly clean things up -        mStatus = STATUS_UNCONFIGURED; +        internalUpdateStatusLocked(STATUS_UNCONFIGURED);          mNeedConfig = true;          ALOGV("%s: Camera %d: Stream configuration failed", __FUNCTION__, mId); @@ -1719,11 +1745,8 @@ status_t Camera3Device::configureStreamsLocked() {      mNeedConfig = false; -    if (mDummyStreamId == NO_STREAM) { -        mStatus = STATUS_CONFIGURED; -    } else { -        mStatus = STATUS_UNCONFIGURED; -    } +    internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ? +            STATUS_CONFIGURED : STATUS_UNCONFIGURED);      ALOGV("%s: Camera %d: Stream configuration complete", __FUNCTION__, mId); @@ -1831,7 +1854,7 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {      mErrorCause = errorCause;      mRequestThread->setPaused(true); -    mStatus = STATUS_ERROR; +    internalUpdateStatusLocked(STATUS_ERROR);      // Notify upstream about a device error      if (mListener != NULL) { diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 8bd0f8e..5287058 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -207,7 +207,11 @@ class Camera3Device :          STATUS_CONFIGURED,          STATUS_ACTIVE      }                          mStatus; + +    // Only clear mRecentStatusUpdates, mStatusWaiters from waitUntilStateThenRelock      Vector<Status>             mRecentStatusUpdates; +    int                        mStatusWaiters; +      Condition                  mStatusChanged;      // Tracking cause of fatal errors when in STATUS_ERROR @@ -278,6 +282,13 @@ class Camera3Device :      virtual CameraMetadata getLatestRequestLocked();      /** +     * Update the current device status and wake all waiting threads. +     * +     * Must be called with mLock held. +     */ +    void internalUpdateStatusLocked(Status status); + +    /**       * Pause processing and flush everything, but don't tell the clients.       * This is for reconfiguring outputs transparently when according to the       * CameraDeviceBase interface we shouldn't need to.  | 
