diff options
| author | Ruben Brunk <rubenbrunk@google.com> | 2015-06-16 11:00:37 -0700 | 
|---|---|---|
| committer | Ruben Brunk <rubenbrunk@google.com> | 2015-07-06 17:49:44 -0700 | 
| commit | 3450ba7879be6522ea46a56c5e66e5382f5dd5ba (patch) | |
| tree | 201ed5e416af4f44012e6b5c7f2b16bd30cfc673 | |
| parent | a3b3caaae3fc23b99c5c455ee429f79c270cfbae (diff) | |
| download | frameworks_av-3450ba7879be6522ea46a56c5e66e5382f5dd5ba.zip frameworks_av-3450ba7879be6522ea46a56c5e66e5382f5dd5ba.tar.gz frameworks_av-3450ba7879be6522ea46a56c5e66e5382f5dd5ba.tar.bz2  | |
camera2: Fix native binder interface and add tests.
- Add CameraBinderTests for limited coverage of native
  camera2 binder interfaces for the camera service.
- Fix several bugs in the native binder interfaces.
Bug: 18468810
Change-Id: Iab2d81a5cacd20daf7454aeeed033cc13d88452c
| -rw-r--r-- | camera/ICameraService.cpp | 3 | ||||
| -rw-r--r-- | camera/ICameraServiceListener.cpp | 14 | ||||
| -rw-r--r-- | camera/camera2/ICameraDeviceUser.cpp | 8 | ||||
| -rw-r--r-- | camera/camera2/OutputConfiguration.cpp | 5 | ||||
| -rw-r--r-- | camera/tests/Android.mk | 3 | ||||
| -rw-r--r-- | camera/tests/CameraBinderTests.cpp | 484 | ||||
| -rw-r--r-- | camera/tests/VendorTagDescriptorTests.cpp | 9 | ||||
| -rw-r--r-- | include/camera/camera2/OutputConfiguration.h | 2 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 2 | 
9 files changed, 514 insertions, 16 deletions
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp index 7bb24ee..7c9720f 100644 --- a/camera/ICameraService.cpp +++ b/camera/ICameraService.cpp @@ -285,6 +285,7 @@ public:          }          Parcel data, reply; +        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());          data.writeInt32(cameraId);          remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply); @@ -304,6 +305,7 @@ public:      virtual status_t supportsCameraApi(int cameraId, int apiVersion) {          Parcel data, reply; +        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());          data.writeInt32(cameraId);          data.writeInt32(apiVersion);          remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply); @@ -315,6 +317,7 @@ public:      virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {          Parcel data, reply; +        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());          data.writeInt32(eventId);          data.writeInt32Array(len, args);          remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply, diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp index 90a8bc2..0010325 100644 --- a/camera/ICameraServiceListener.cpp +++ b/camera/ICameraServiceListener.cpp @@ -45,8 +45,7 @@ public:      virtual void onStatusChanged(Status status, int32_t cameraId)      {          Parcel data, reply; -        data.writeInterfaceToken( -                              ICameraServiceListener::getInterfaceDescriptor()); +        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());          data.writeInt32(static_cast<int32_t>(status));          data.writeInt32(cameraId); @@ -60,8 +59,7 @@ public:      virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)      {          Parcel data, reply; -        data.writeInterfaceToken( -                              ICameraServiceListener::getInterfaceDescriptor()); +        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());          data.writeInt32(static_cast<int32_t>(status));          data.writeString16(cameraId); @@ -73,14 +71,12 @@ public:      }  }; -IMPLEMENT_META_INTERFACE(CameraServiceListener, -                         "android.hardware.ICameraServiceListener"); +IMPLEMENT_META_INTERFACE(CameraServiceListener, "android.hardware.ICameraServiceListener");  // ---------------------------------------------------------------------- -status_t BnCameraServiceListener::onTransact( -    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ +status_t BnCameraServiceListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, +        uint32_t flags) {      switch(code) {          case STATUS_CHANGED: {              CHECK_INTERFACE(ICameraServiceListener, data, reply); diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp index a7549f2..ffe974b 100644 --- a/camera/camera2/ICameraDeviceUser.cpp +++ b/camera/camera2/ICameraDeviceUser.cpp @@ -82,7 +82,7 @@ public:          reply.readExceptionCode();      } -    virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating, +    virtual int submitRequest(sp<CaptureRequest> request, bool repeating,                                int64_t *lastFrameNumber)      {          Parcel data, reply; @@ -111,13 +111,13 @@ public:              }          } -	if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) { +        if (res < 0 || (resFrameNumber != NO_ERROR)) {              res = FAILED_TRANSACTION;          }          return res;      } -    virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating, +    virtual int submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,                                    int64_t *lastFrameNumber)      {          Parcel data, reply; @@ -151,7 +151,7 @@ public:                  resFrameNumber = reply.readInt64(lastFrameNumber);              }          } -        if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) { +        if (res < 0 || (resFrameNumber != NO_ERROR)) {              res = FAILED_TRANSACTION;          }          return res; diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp index 24acaa0..20a23e0 100644 --- a/camera/camera2/OutputConfiguration.cpp +++ b/camera/camera2/OutputConfiguration.cpp @@ -65,6 +65,11 @@ OutputConfiguration::OutputConfiguration(const Parcel& parcel) {            gbp.get(), String8(name).string());  } +OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) { +    mGbp = gbp; +    mRotation = rotation; +} +  status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {      parcel.writeInt32(mRotation); diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk index 5d37f9e..3777d94 100644 --- a/camera/tests/Android.mk +++ b/camera/tests/Android.mk @@ -17,7 +17,8 @@ include $(CLEAR_VARS)  LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk  LOCAL_SRC_FILES:= \ -	VendorTagDescriptorTests.cpp +	VendorTagDescriptorTests.cpp \ +	CameraBinderTests.cpp  LOCAL_SHARED_LIBRARIES := \  	libutils \ diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp new file mode 100644 index 0000000..572fb72 --- /dev/null +++ b/camera/tests/CameraBinderTests.cpp @@ -0,0 +1,484 @@ +/* + * Copyright (C) 2015 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_NDEBUG 0 +#define LOG_TAG "CameraBinderTests" + +#include <binder/IInterface.h> +#include <binder/IServiceManager.h> +#include <binder/Parcel.h> +#include <binder/ProcessState.h> +#include <utils/Errors.h> +#include <utils/Log.h> +#include <utils/List.h> +#include <utils/String8.h> +#include <utils/String16.h> +#include <utils/Condition.h> +#include <utils/Mutex.h> +#include <system/graphics.h> +#include <hardware/gralloc.h> + +#include <camera/CameraMetadata.h> +#include <camera/ICameraService.h> +#include <camera/ICameraServiceListener.h> +#include <camera/camera2/CaptureRequest.h> +#include <camera/camera2/ICameraDeviceUser.h> +#include <camera/camera2/ICameraDeviceCallbacks.h> +#include <camera/camera2/OutputConfiguration.h> + +#include <gui/BufferItemConsumer.h> +#include <gui/IGraphicBufferProducer.h> +#include <gui/Surface.h> + +#include <gtest/gtest.h> +#include <unistd.h> +#include <stdint.h> +#include <utility> +#include <vector> +#include <map> +#include <algorithm> + +using namespace android; + +#define ASSERT_NOT_NULL(x) \ +    ASSERT_TRUE((x) != nullptr) + +#define SETUP_TIMEOUT 2000000000 // ns +#define IDLE_TIMEOUT 2000000000 // ns + +// Stub listener implementation +class TestCameraServiceListener : public BnCameraServiceListener { +    std::map<String16, TorchStatus> mCameraTorchStatuses; +    std::map<int32_t, Status> mCameraStatuses; +    mutable Mutex mLock; +    mutable Condition mCondition; +    mutable Condition mTorchCondition; +public: +    virtual ~TestCameraServiceListener() {}; + +    virtual void onStatusChanged(Status status, int32_t cameraId) { +        Mutex::Autolock l(mLock); +        mCameraStatuses[cameraId] = status; +        mCondition.broadcast(); +    }; + +    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) { +        Mutex::Autolock l(mLock); +        mCameraTorchStatuses[cameraId] = status; +        mTorchCondition.broadcast(); +    }; + +    bool waitForNumCameras(size_t num) const { +        Mutex::Autolock l(mLock); + +        if (mCameraStatuses.size() == num) { +            return true; +        } + +        while (mCameraStatuses.size() < num) { +            if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) { +                return false; +            } +        } +        return true; +    }; + +    bool waitForTorchState(TorchStatus status, int32_t cameraId) const { +        Mutex::Autolock l(mLock); + +        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); +        if (iter != mCameraTorchStatuses.end() && iter->second == status) { +            return true; +        } + +        bool foundStatus = false; +        while (!foundStatus) { +            if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) { +                return false; +            } +            const auto& iter = +                    mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); +            foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status); +        } +        return true; +    }; + +    TorchStatus getTorchStatus(int32_t cameraId) const { +        Mutex::Autolock l(mLock); +        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); +        if (iter == mCameraTorchStatuses.end()) { +            return ICameraServiceListener::TORCH_STATUS_UNKNOWN; +        } +        return iter->second; +    }; + +    Status getStatus(int32_t cameraId) const { +        Mutex::Autolock l(mLock); +        const auto& iter = mCameraStatuses.find(cameraId); +        if (iter == mCameraStatuses.end()) { +            return ICameraServiceListener::STATUS_UNKNOWN; +        } +        return iter->second; +    }; +}; + +// Callback implementation +class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks { +public: +    enum Status { +        IDLE, +        ERROR, +        PREPARED, +        RUNNING, +        SENT_RESULT, +        UNINITIALIZED +    }; + +protected: +    bool mError; +    Status mLastStatus; +    mutable std::vector<Status> mStatusesHit; +    mutable Mutex mLock; +    mutable Condition mStatusCondition; +public: +    TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {} + +    virtual ~TestCameraDeviceCallbacks() {} + +    virtual void onDeviceError(CameraErrorCode errorCode, +            const CaptureResultExtras& resultExtras) { +        ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode)); +        Mutex::Autolock l(mLock); +        mError = true; +        mLastStatus = ERROR; +        mStatusesHit.push_back(mLastStatus); +        mStatusCondition.broadcast(); +    } + +    virtual void onDeviceIdle() { +        Mutex::Autolock l(mLock); +        mLastStatus = IDLE; +        mStatusesHit.push_back(mLastStatus); +        mStatusCondition.broadcast(); +    } + +    virtual void onCaptureStarted(const CaptureResultExtras& resultExtras, +            int64_t timestamp) { +        Mutex::Autolock l(mLock); +        mLastStatus = RUNNING; +        mStatusesHit.push_back(mLastStatus); +        mStatusCondition.broadcast(); +    } + + +    virtual void onResultReceived(const CameraMetadata& metadata, +            const CaptureResultExtras& resultExtras) { +        Mutex::Autolock l(mLock); +        mLastStatus = SENT_RESULT; +        mStatusesHit.push_back(mLastStatus); +        mStatusCondition.broadcast(); +    } + +    virtual void onPrepared(int streamId) { +        Mutex::Autolock l(mLock); +        mLastStatus = PREPARED; +        mStatusesHit.push_back(mLastStatus); +        mStatusCondition.broadcast(); +    } + +    // Test helper functions: + +    bool hadError() const { +        Mutex::Autolock l(mLock); +        return mError; +    } + +    bool waitForStatus(Status status) const { +        Mutex::Autolock l(mLock); +        if (mLastStatus == status) { +            return true; +        } + +        while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status) +                == mStatusesHit.end()) { + +            if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) { +                mStatusesHit.clear(); +                return false; +            } +        } +        mStatusesHit.clear(); + +        return true; + +    } + +    void clearStatus() const { +        Mutex::Autolock l(mLock); +        mStatusesHit.clear(); +    } + +    bool waitForIdle() const { +        return waitForStatus(IDLE); +    } + +}; + +// Exercise basic binder calls for the camera service +TEST(CameraServiceBinderTest, CheckBinderCameraService) { +    ProcessState::self()->startThreadPool(); +    sp<IServiceManager> sm = defaultServiceManager(); +    sp<IBinder> binder = sm->getService(String16("media.camera")); +    ASSERT_NOT_NULL(binder); +    sp<ICameraService> service = interface_cast<ICameraService>(binder); + + +    int32_t numCameras = service->getNumberOfCameras(); +    EXPECT_LE(0, numCameras); + +    // Check listener binder calls +    sp<TestCameraServiceListener> listener(new TestCameraServiceListener()); +    EXPECT_EQ(OK, service->addListener(listener)); + +    EXPECT_TRUE(listener->waitForNumCameras(numCameras)); + +    for (int32_t i = 0; i < numCameras; i++) { +        // We only care about binder calls for the Camera2 API.  Camera1 is deprecated. +        status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2); +        if (camera2Support != OK) { +            EXPECT_EQ(-EOPNOTSUPP, camera2Support); +            continue; +        } + +        // Check metadata binder call +        CameraMetadata metadata; +        EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata)); +        EXPECT_FALSE(metadata.isEmpty()); + +        // Make sure we're available, or skip device tests otherwise +        ICameraServiceListener::Status s = listener->getStatus(i); +        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s); +        if (s != ICameraServiceListener::STATUS_AVAILABLE) { +            continue; +        } + +        // Check connect binder calls +        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks()); +        sp<ICameraDeviceUser> device; +        EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"), +                ICameraService::USE_CALLING_UID, /*out*/device)); +        ASSERT_NE(nullptr, device.get()); +        device->disconnect(); +        EXPECT_FALSE(callbacks->hadError()); + +        ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i); +        if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) { +            // Check torch calls +            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)), +                    /*enabled*/true, callbacks)); +            EXPECT_TRUE(listener->waitForTorchState( +                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i)); +            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)), +                    /*enabled*/false, callbacks)); +            EXPECT_TRUE(listener->waitForTorchState( +                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i)); +        } +    } + +    EXPECT_EQ(OK, service->removeListener(listener)); +} + +// Test fixture for client focused binder tests +class CameraClientBinderTest : public testing::Test { +protected: +    sp<ICameraService> service; +    int32_t numCameras; +    std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList; +    sp<TestCameraServiceListener> serviceListener; + +    std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) { + +        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks()); +        sp<ICameraDeviceUser> device; +        { +            SCOPED_TRACE("openNewDevice"); +            EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"), +                    ICameraService::USE_CALLING_UID, /*out*/device)); +        } +        auto p = std::make_pair(callbacks, device); +        openDeviceList.push_back(p); +        return p; +    } + +    void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) { +        if (p.second.get() != nullptr) { +            p.second->disconnect(); +            { +                SCOPED_TRACE("closeDevice"); +                EXPECT_FALSE(p.first->hadError()); +            } +        } +        auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p); +        if (iter != openDeviceList.end()) { +            openDeviceList.erase(iter); +        } +    } + +    virtual void SetUp() { +        ProcessState::self()->startThreadPool(); +        sp<IServiceManager> sm = defaultServiceManager(); +        sp<IBinder> binder = sm->getService(String16("media.camera")); +        service = interface_cast<ICameraService>(binder); +        serviceListener = new TestCameraServiceListener(); +        service->addListener(serviceListener); +        numCameras = service->getNumberOfCameras(); +    } + +    virtual void TearDown() { +        service = nullptr; +        numCameras = 0; +        for (auto& p : openDeviceList) { +            closeDevice(p); +        } +    } + +}; + +TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) { +    ASSERT_NOT_NULL(service); + +    EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras)); +    for (int32_t i = 0; i < numCameras; i++) { +        // Make sure we're available, or skip device tests otherwise +        ICameraServiceListener::Status s = serviceListener->getStatus(i); +        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s); +        if (s != ICameraServiceListener::STATUS_AVAILABLE) { +            continue; +        } + +        auto p = openNewDevice(i); +        sp<TestCameraDeviceCallbacks> callbacks = p.first; +        sp<ICameraDeviceUser> device = p.second; + +        // Setup a buffer queue; I'm just using the vendor opaque format here as that is +        // guaranteed to be present +        sp<IGraphicBufferProducer> gbProducer; +        sp<IGraphicBufferConsumer> gbConsumer; +        BufferQueue::createBufferQueue(&gbProducer, &gbConsumer); +        sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer, +                GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true); +        EXPECT_TRUE(opaqueConsumer.get() != nullptr); +        opaqueConsumer->setName(String8("nom nom nom")); + +        // Set to VGA dimens for default, as that is guaranteed to be present +        EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480)); +        EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)); + +        sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false)); + +        OutputConfiguration output(gbProducer, /*rotation*/0); + +        // Can we configure? +        EXPECT_EQ(OK, device->beginConfigure()); +        status_t streamId = device->createStream(output); +        EXPECT_LE(0, streamId); +        EXPECT_EQ(OK, device->endConfigure()); +        EXPECT_FALSE(callbacks->hadError()); + +        // Can we make requests? +        CameraMetadata requestTemplate; +        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1, +                /*out*/&requestTemplate)); +        sp<CaptureRequest> request(new CaptureRequest()); +        request->mMetadata = requestTemplate; +        request->mSurfaceList.add(surface); +        request->mIsReprocess = false; +        int64_t lastFrameNumber = 0; +        int64_t lastFrameNumberPrev = 0; +        callbacks->clearStatus(); +        int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber); +        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); +        EXPECT_LE(0, requestId); + +        // Can we stop requests? +        EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber)); +        EXPECT_TRUE(callbacks->waitForIdle()); +        EXPECT_FALSE(callbacks->hadError()); + +        // Can we do it again? +        lastFrameNumberPrev = lastFrameNumber; +        lastFrameNumber = 0; +        requestTemplate.clear(); +        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1, +                /*out*/&requestTemplate)); +        sp<CaptureRequest> request2(new CaptureRequest()); +        request2->mMetadata = requestTemplate; +        request2->mSurfaceList.add(surface); +        request2->mIsReprocess = false; +        callbacks->clearStatus(); +        int requestId2 = device->submitRequest(request2, /*streaming*/true, +                /*out*/&lastFrameNumber); +        EXPECT_EQ(-1, lastFrameNumber); +        lastFrameNumber = 0; +        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); +        EXPECT_LE(0, requestId2); +        EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber)); +        EXPECT_TRUE(callbacks->waitForIdle()); +        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber); +        sleep(/*second*/1); // allow some time for errors to show up, if any +        EXPECT_FALSE(callbacks->hadError()); + +        // Can we do it with a request list? +        lastFrameNumberPrev = lastFrameNumber; +        lastFrameNumber = 0; +        requestTemplate.clear(); +        CameraMetadata requestTemplate2; +        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1, +                /*out*/&requestTemplate)); +        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1, +                /*out*/&requestTemplate2)); +        sp<CaptureRequest> request3(new CaptureRequest()); +        sp<CaptureRequest> request4(new CaptureRequest()); +        request3->mMetadata = requestTemplate; +        request3->mSurfaceList.add(surface); +        request3->mIsReprocess = false; +        request4->mMetadata = requestTemplate2; +        request4->mSurfaceList.add(surface); +        request4->mIsReprocess = false; +        List<sp<CaptureRequest>> requestList; +        requestList.push_back(request3); +        requestList.push_back(request4); + +        callbacks->clearStatus(); +        int requestId3 = device->submitRequestList(requestList, /*streaming*/false, +                /*out*/&lastFrameNumber); +        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); +        EXPECT_TRUE(callbacks->waitForIdle()); +        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber); +        sleep(/*second*/1); // allow some time for errors to show up, if any +        EXPECT_FALSE(callbacks->hadError()); + +        // Can we unconfigure? +        EXPECT_EQ(OK, device->beginConfigure()); +        EXPECT_EQ(OK, device->deleteStream(streamId)); +        EXPECT_EQ(OK, device->endConfigure()); +        sleep(/*second*/1); // allow some time for errors to show up, if any +        EXPECT_FALSE(callbacks->hadError()); + +        closeDevice(p); +    } + +}; diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp index 6624e79..9082dbf 100644 --- a/camera/tests/VendorTagDescriptorTests.cpp +++ b/camera/tests/VendorTagDescriptorTests.cpp @@ -53,6 +53,10 @@ static bool ContainsTag(uint32_t* tagArray, size_t size, uint32_t tag) {  extern "C" { +static int zero_get_tag_count(const vendor_tag_ops_t* vOps) { +    return 0; +} +  static int default_get_tag_count(const vendor_tag_ops_t* vOps) {      return VENDOR_TAG_COUNT_ERR;  } @@ -173,10 +177,13 @@ TEST(VendorTagDescriptorTest, ErrorConditions) {      vendor_tag_ops_t vOps;      FillWithDefaults(&vOps); +    // Make empty tag count +    vOps.get_tag_count = zero_get_tag_count; +      // Ensure create fails when using null vOps      EXPECT_EQ(BAD_VALUE, VendorTagDescriptor::createDescriptorFromOps(/*vOps*/NULL, vDesc)); -    // Ensure create works when there are no vtags defined in a well-formed vOps +    // Ensure creat succeeds for empty vendor tag ops      ASSERT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc));      // Ensure defaults are returned when no vtags are defined, or tag is unknown diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h index e6b679f..5bcbe15 100644 --- a/include/camera/camera2/OutputConfiguration.h +++ b/include/camera/camera2/OutputConfiguration.h @@ -39,6 +39,8 @@ public:      // getRotation will be INVALID_ROTATION if error occurred      OutputConfiguration(const Parcel& parcel); +    OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation); +  private:      sp<IGraphicBufferProducer> mGbp;      int                        mRotation; diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index f42fada..92df4e3 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -1292,7 +1292,7 @@ void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size  status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {      ALOGV("%s: Add listener %p", __FUNCTION__, listener.get()); -    if (listener == 0) { +    if (listener == nullptr) {          ALOGE("%s: Listener must not be null", __FUNCTION__);          return BAD_VALUE;      }  | 
