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

Commit addae1cf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "camera2: Add support for secondary surface for stream"

parents 7a667f66 0129d52d
Loading
Loading
Loading
Loading
+86 −23
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ namespace android {
const int OutputConfiguration::INVALID_ROTATION = -1;
const int OutputConfiguration::INVALID_SET_ID = -1;

sp<IGraphicBufferProducer> OutputConfiguration::getGraphicBufferProducer() const {
    return mGbp;
const std::vector<sp<IGraphicBufferProducer>>&
        OutputConfiguration::getGraphicBufferProducers() const {
    return mGbps;
}

int OutputConfiguration::getRotation() const {
@@ -104,11 +105,31 @@ status_t OutputConfiguration::readFromParcel(const android::Parcel* parcel) {
        return err;
    }

    // numSurfaces is the total number of surfaces for this OutputConfiguration,
    // regardless the surface is deferred or not.
    int numSurfaces = 0;
    if ((err = parcel->readInt32(&numSurfaces)) != OK) {
        ALOGE("%s: Failed to read maxSurfaces from parcel", __FUNCTION__);
        return err;
    }
    if (numSurfaces < 1) {
        ALOGE("%s: there has to be at least 1 surface per"
              " outputConfiguration", __FUNCTION__);
        return BAD_VALUE;
    }

    // Read all surfaces from parcel. If a surface is deferred, readFromPacel
    // returns error, and a null surface is put into the mGbps. We assume all
    // deferred surfaces are after non-deferred surfaces in the parcel.
    // TODO: Need better way to detect deferred surface than using error
    // return from readFromParcel.
    std::vector<sp<IGraphicBufferProducer>> gbps;
    for (int i = 0; i < numSurfaces; i++) {
        view::Surface surfaceShim;
        if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
            // Read surface failure for deferred surface configuration is expected.
        if (surfaceType == SURFACE_TYPE_SURFACE_VIEW ||
                surfaceType == SURFACE_TYPE_SURFACE_TEXTURE) {
            if ((surfaceType == SURFACE_TYPE_SURFACE_VIEW ||
                    surfaceType == SURFACE_TYPE_SURFACE_TEXTURE)) {
                ALOGV("%s: Get null surface from a deferred surface configuration (%dx%d)",
                        __FUNCTION__, width, height);
                err = OK;
@@ -117,24 +138,27 @@ status_t OutputConfiguration::readFromParcel(const android::Parcel* parcel) {
                return err;
            }
        }
        gbps.push_back(surfaceShim.graphicBufferProducer);
        ALOGV("%s: OutputConfiguration: gbps[%d] : %p, name %s", __FUNCTION__,
                i, gbps[i].get(), String8(surfaceShim.name).string());
    }

    mGbp = surfaceShim.graphicBufferProducer;
    mRotation = rotation;
    mSurfaceSetID = setID;
    mSurfaceType = surfaceType;
    mWidth = width;
    mHeight = height;
    mGbps = std::move(gbps);

    ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d,"
            "surfaceType = %d", __FUNCTION__, mGbp.get(), String8(surfaceShim.name).string(),
            mRotation, mSurfaceSetID, mSurfaceType);
    ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d",
            __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType);

    return err;
}

OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
        int surfaceSetID) {
    mGbp = gbp;
    mGbps.push_back(gbp);
    mRotation = rotation;
    mSurfaceSetID = surfaceSetID;
}
@@ -159,14 +183,53 @@ status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
    err = parcel->writeInt32(mHeight);
    if (err != OK) return err;

    int numSurfaces = mGbps.size();
    err = parcel->writeInt32(numSurfaces);
    if (err != OK) return err;

    for (int i = 0; i < numSurfaces; i++) {
        view::Surface surfaceShim;
        surfaceShim.name = String16("unknown_name"); // name of surface
    surfaceShim.graphicBufferProducer = mGbp;
        surfaceShim.graphicBufferProducer = mGbps[i];

        err = surfaceShim.writeToParcel(parcel);
        if (err != OK) return err;
    }

    return OK;
}

bool OutputConfiguration::gbpsEqual(const OutputConfiguration& other) const {
    const std::vector<sp<IGraphicBufferProducer> >& otherGbps =
            other.getGraphicBufferProducers();

    if (mGbps.size() != otherGbps.size()) {
        return false;
    }

    for (size_t i = 0; i < mGbps.size(); i++) {
        if (mGbps[i] != otherGbps[i]) {
            return false;
        }
    }

    return true;
}

bool OutputConfiguration::gbpsLessThan(const OutputConfiguration& other) const {
    const std::vector<sp<IGraphicBufferProducer> >& otherGbps =
            other.getGraphicBufferProducers();

    if (mGbps.size() !=  otherGbps.size()) {
        return mGbps.size() < otherGbps.size();
    }

    for (size_t i = 0; i < mGbps.size(); i++) {
        if (mGbps[i] != otherGbps[i]) {
            return mGbps[i] < otherGbps[i];
        }
    }

    return false;
}
}; // namespace android
+11 −7
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public:
        SURFACE_TYPE_SURFACE_VIEW = 0,
        SURFACE_TYPE_SURFACE_TEXTURE = 1
    };
    sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
    const std::vector<sp<IGraphicBufferProducer>>& getGraphicBufferProducers() const;
    int                        getRotation() const;
    int                        getSurfaceSetID() const;
    int                        getSurfaceType() const;
@@ -65,19 +65,18 @@ public:
            int surfaceSetID = INVALID_SET_ID);

    bool operator == (const OutputConfiguration& other) const {
        return (mGbp == other.mGbp &&
                mRotation == other.mRotation &&
        return ( mRotation == other.mRotation &&
                mSurfaceSetID == other.mSurfaceSetID &&
                mSurfaceType == other.mSurfaceType &&
                mWidth == other.mWidth &&
                mHeight == other.mHeight);
                mHeight == other.mHeight &&
                gbpsEqual(other));
    }
    bool operator != (const OutputConfiguration& other) const {
        return !(*this == other);
    }
    bool operator < (const OutputConfiguration& other) const {
        if (*this == other) return false;
        if (mGbp != other.mGbp) return mGbp < other.mGbp;
        if (mSurfaceSetID != other.mSurfaceSetID) {
            return mSurfaceSetID < other.mSurfaceSetID;
        }
@@ -90,15 +89,20 @@ public:
        if (mHeight != other.mHeight) {
            return mHeight < other.mHeight;
        }

        if (mRotation != other.mRotation) {
            return mRotation < other.mRotation;
        }

        return gbpsLessThan(other);
    }
    bool operator > (const OutputConfiguration& other) const {
        return (*this != other && !(*this < other));
    }

    bool gbpsEqual(const OutputConfiguration& other) const;
    bool gbpsLessThan(const OutputConfiguration& other) const;
private:
    sp<IGraphicBufferProducer> mGbp;
    std::vector<sp<IGraphicBufferProducer>> mGbps;
    int                        mRotation;
    int                        mSurfaceSetID;
    int                        mSurfaceType;
+2 −0
Original line number Diff line number Diff line
@@ -48,8 +48,10 @@ LOCAL_SRC_FILES := \
    device3/Camera3OutputStream.cpp \
    device3/Camera3ZslStream.cpp \
    device3/Camera3DummyStream.cpp \
    device3/Camera3SharedOutputStream.cpp \
    device3/StatusTracker.cpp \
    device3/Camera3BufferManager.cpp \
    device3/Camera3StreamSplitter.cpp \
    gui/RingBufferConsumer.cpp \
    utils/CameraTraces.cpp \
    utils/AutoConditionLock.cpp \
+267 −139
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ binder::Status CameraDeviceClient::submitRequestList(
    }

    List<const CameraMetadata> metadataRequestList;
    std::list<const SurfaceMap> surfaceMapList;
    submitInfo->mRequestId = mRequestIdCounter;
    uint32_t loopCounter = 0;

@@ -191,11 +192,11 @@ binder::Status CameraDeviceClient::submitRequestList(
        }

        /**
         * Write in the output stream IDs which we calculate from
         * the capture request's list of surface targets
         * Write in the output stream IDs and map from stream ID to surface ID
         * which we calculate from the capture request's list of surface target
         */
        SurfaceMap surfaceMap;
        Vector<int32_t> outputStreamIds;
        outputStreamIds.setCapacity(request.mSurfaceList.size());
        for (sp<Surface> surface : request.mSurfaceList) {
            if (surface == 0) continue;

@@ -211,10 +212,16 @@ binder::Status CameraDeviceClient::submitRequestList(
                        "Request targets Surface that is not part of current capture session");
            }

            int streamId = mStreamMap.valueAt(idx);
            outputStreamIds.push_back(streamId);
            ALOGV("%s: Camera %s: Appending output stream %d to request",
                    __FUNCTION__, mCameraIdStr.string(), streamId);
            const StreamSurfaceId& streamSurfaceId = mStreamMap.valueAt(idx);
            if (surfaceMap.find(streamSurfaceId.streamId()) == surfaceMap.end()) {
                surfaceMap[streamSurfaceId.streamId()] = std::vector<size_t>();
                outputStreamIds.push_back(streamSurfaceId.streamId());
            }
            surfaceMap[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());

            ALOGV("%s: Camera %s: Appending output stream %d surface %d to request",
                    __FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
                    streamSurfaceId.surfaceId());
        }

        metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
@@ -231,11 +238,13 @@ binder::Status CameraDeviceClient::submitRequestList(
                loopCounter, requests.size());

        metadataRequestList.push_back(metadata);
        surfaceMapList.push_back(surfaceMap);
    }
    mRequestIdCounter++;

    if (streaming) {
        err = mDevice->setStreamingRequestList(metadataRequestList, &(submitInfo->mLastFrameNumber));
        err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
                &(submitInfo->mLastFrameNumber));
        if (err != OK) {
            String8 msg = String8::format(
                "Camera %s:  Got error %s (%d) after trying to set streaming request",
@@ -248,7 +257,8 @@ binder::Status CameraDeviceClient::submitRequestList(
            mStreamingRequestId = submitInfo->mRequestId;
        }
    } else {
        err = mDevice->captureList(metadataRequestList, &(submitInfo->mLastFrameNumber));
        err = mDevice->captureList(metadataRequestList, surfaceMapList,
                &(submitInfo->mLastFrameNumber));
        if (err != OK) {
            String8 msg = String8::format(
                "Camera %s: Got error %s (%d) after trying to submit capture request",
@@ -312,8 +322,9 @@ binder::Status CameraDeviceClient::beginConfigure() {
}

binder::Status CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) {
    ALOGV("%s: ending configure (%d input stream, %zu output streams)",
            __FUNCTION__, mInputStream.configured ? 1 : 0, mStreamMap.size());
    ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
            __FUNCTION__, mInputStream.configured ? 1 : 0,
            mStreamMap.size());

    binder::Status res;
    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
@@ -376,7 +387,7 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) {
    }

    bool isInput = false;
    ssize_t index = NAME_NOT_FOUND;
    std::vector<sp<IBinder>> surfaces;
    ssize_t dIndex = NAME_NOT_FOUND;

    if (mInputStream.configured && mInputStream.id == streamId) {
@@ -384,13 +395,11 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) {
    } else {
        // Guard against trying to delete non-created streams
        for (size_t i = 0; i < mStreamMap.size(); ++i) {
            if (streamId == mStreamMap.valueAt(i)) {
                index = i;
                break;
            if (streamId == mStreamMap.valueAt(i).streamId()) {
                surfaces.push_back(mStreamMap.keyAt(i));
            }
        }

        if (index == NAME_NOT_FOUND) {
        // See if this stream is one of the deferred streams.
        for (size_t i = 0; i < mDeferredStreams.size(); ++i) {
            if (streamId == mDeferredStreams[i]) {
@@ -398,14 +407,14 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) {
                break;
            }
        }
            if (dIndex == NAME_NOT_FOUND) {

        if (surfaces.empty() && dIndex == NAME_NOT_FOUND) {
            String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no such"
                    " stream created yet", mCameraIdStr.string(), streamId);
            ALOGW("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
    }
    }

    // Also returns BAD_VALUE if stream ID was not valid
    status_t err = mDevice->deleteStream(streamId);
@@ -418,12 +427,16 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) {
    } else {
        if (isInput) {
            mInputStream.configured = false;
        } else if (index != NAME_NOT_FOUND) {
            mStreamMap.removeItemsAt(index);
        } else {
            for (auto& surface : surfaces) {
                mStreamMap.removeItem(surface);
            }

            if (dIndex != NAME_NOT_FOUND) {
                mDeferredStreams.removeItemsAt(dIndex);
            }
        }
    }

    return res;
}
@@ -439,14 +452,39 @@ binder::Status CameraDeviceClient::createStream(

    Mutex::Autolock icl(mBinderSerializationLock);

    sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
    bool deferredConsumer = bufferProducer == NULL;
    const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
            outputConfiguration.getGraphicBufferProducers();
    size_t numBufferProducers = bufferProducers.size();

    if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
        ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
              __FUNCTION__, bufferProducers.size(), MAX_SURFACES_PER_STREAM);
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
    }
    if (numBufferProducers == 0) {
        ALOGE("%s: GraphicBufferProducer count 0 is not valid", __FUNCTION__);
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Malformed surface");
    }
    size_t deferredConsumerCnt = 0;
    for (auto bufferProducer : bufferProducers) {
        if (bufferProducer == nullptr) {
            deferredConsumerCnt++;
        }
    }
    if (deferredConsumerCnt > MAX_DEFERRED_SURFACES) {
        ALOGE("%s: %zu deferred consumer is not supported", __FUNCTION__, deferredConsumerCnt);
        return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                "More than %d deferred consumer", MAX_DEFERRED_SURFACES);
    }
    bool deferredConsumer = deferredConsumerCnt > 0;
    bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 1;
    int surfaceType = outputConfiguration.getSurfaceType();
    bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
            (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));

    if (deferredConsumer && !validSurfaceType) {
        ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.",
                __FUNCTION__, bufferProducer.get(), surfaceType);
                __FUNCTION__, bufferProducers[0].get(), surfaceType);
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
    }

@@ -454,16 +492,32 @@ binder::Status CameraDeviceClient::createStream(
        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
    }

    std::vector<sp<Surface>> surfaces;
    std::vector<sp<IBinder>> binders;
    int streamWidth, streamHeight, streamFormat;
    int width, height, format;
    int32_t streamConsumerUsage;
    int32_t consumerUsage;
    android_dataspace dataSpace;
    android_dataspace dataSpace, streamDataSpace;
    status_t err;

    // Create stream for deferred surface case.
    if (deferredConsumer) {
    if (deferredConsumerOnly) {
        return createDeferredSurfaceStreamLocked(outputConfiguration, newStreamId);
    }

    bool isFirstSurface = true;
    streamWidth = -1;
    streamHeight = -1;
    streamFormat = -1;
    streamDataSpace = HAL_DATASPACE_UNKNOWN;
    streamConsumerUsage = 0;

    for (auto& bufferProducer : bufferProducers) {
        if (bufferProducer == nullptr) {
            continue;
        }

        // Don't create multiple streams for the same target surface
        {
            ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
@@ -538,19 +592,65 @@ binder::Status CameraDeviceClient::createStream(
                  __FUNCTION__, mCameraIdStr.string(), format);
            format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
        }

        // Round dimensions to the nearest dimensions available for this format
        if (flexibleConsumer && isPublicFormat(format) &&
                !CameraDeviceClient::roundBufferDimensionNearest(width, height,
                format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
            String8 msg = String8::format("Camera %s: No supported stream configurations with "
                "format %#x defined, failed to create output stream", mCameraIdStr.string(), format);
                    "format %#x defined, failed to create output stream",
                    mCameraIdStr.string(), format);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        if (isFirstSurface) {
            streamWidth = width;
            streamHeight = height;
            streamFormat = format;
            streamDataSpace = dataSpace;
            streamConsumerUsage = consumerUsage;
            isFirstSurface = false;
        }
        if (width != streamWidth) {
            String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
                     mCameraIdStr.string(), width, streamWidth);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        if (height != streamHeight) {
            String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
                     mCameraIdStr.string(), height, streamHeight);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        if (format != streamFormat) {
            String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
                     mCameraIdStr.string(), format, streamFormat);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        if (dataSpace != streamDataSpace) {
            String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
                     mCameraIdStr.string(), dataSpace, streamDataSpace);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        //At the native side, there isn't a way to check whether 2 surfaces come from the same
        //surface class type. Use usage flag to approximate the comparison.
        //TODO: Support surfaces of different surface class type.
        if (consumerUsage != streamConsumerUsage) {
            String8 msg = String8::format(
                    "Camera %s:Surface usage flag doesn't match 0x%x vs 0x%x",
                    mCameraIdStr.string(), consumerUsage, streamConsumerUsage);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }

        binders.push_back(binder);
        surfaces.push_back(surface);
    }

    int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
    err = mDevice->createStream(surface, width, height, format, dataSpace,
    err = mDevice->createStream(surfaces, deferredConsumer, width, height, format, dataSpace,
            static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
            &streamId, outputConfiguration.getSurfaceSetID());

@@ -559,8 +659,12 @@ binder::Status CameraDeviceClient::createStream(
                "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
                mCameraIdStr.string(), width, height, format, dataSpace, strerror(-err), err);
    } else {
        mStreamMap.add(binder, streamId);

        int i = 0;
        for (auto& binder : binders) {
            ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d",
                    __FUNCTION__, binder.get(), streamId, i);
            mStreamMap.add(binder, StreamSurfaceId(streamId, i++));
        }
        ALOGV("%s: Camera %s: Successfully created a new stream ID %d for output surface"
                    " (%d x %d) with format 0x%x.",
                  __FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
@@ -600,7 +704,9 @@ binder::Status CameraDeviceClient::createDeferredSurfaceStreamLocked(
        consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
    }
    int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
    err = mDevice->createStream(/*surface*/nullptr, width, height, format, dataSpace,
    std::vector<sp<Surface>> noSurface;
    err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
            height, format, dataSpace,
            static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
            &streamId, outputConfiguration.getSurfaceSetID(), consumerUsage);

@@ -944,7 +1050,7 @@ binder::Status CameraDeviceClient::prepare(int streamId) {
    // Guard against trying to prepare non-created streams
    ssize_t index = NAME_NOT_FOUND;
    for (size_t i = 0; i < mStreamMap.size(); ++i) {
        if (streamId == mStreamMap.valueAt(i)) {
        if (streamId == mStreamMap.valueAt(i).streamId()) {
            index = i;
            break;
        }
@@ -984,7 +1090,7 @@ binder::Status CameraDeviceClient::prepare2(int maxCount, int streamId) {
    // Guard against trying to prepare non-created streams
    ssize_t index = NAME_NOT_FOUND;
    for (size_t i = 0; i < mStreamMap.size(); ++i) {
        if (streamId == mStreamMap.valueAt(i)) {
        if (streamId == mStreamMap.valueAt(i).streamId()) {
            index = i;
            break;
        }
@@ -1032,7 +1138,7 @@ binder::Status CameraDeviceClient::tearDown(int streamId) {
    // Guard against trying to prepare non-created streams
    ssize_t index = NAME_NOT_FOUND;
    for (size_t i = 0; i < mStreamMap.size(); ++i) {
        if (streamId == mStreamMap.valueAt(i)) {
        if (streamId == mStreamMap.valueAt(i).streamId()) {
            index = i;
            break;
        }
@@ -1070,27 +1176,43 @@ binder::Status CameraDeviceClient::setDeferredConfiguration(int32_t streamId,

    Mutex::Autolock icl(mBinderSerializationLock);

    sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
    const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
            outputConfiguration.getGraphicBufferProducers();

    // Client code should guarantee that the surface is from SurfaceView or SurfaceTexture.
    if (bufferProducer == NULL) {
        ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
    // And it's also saved in the last entry of graphicBufferProducer list
    if (bufferProducers.size() == 0) {
        ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
    }
    // Check if this stram id is one of the deferred streams

    // Right now, only first surface in the OutputConfiguration is allowed to be
    // deferred. And all other surfaces are checked to be the same (not null) at
    // the Java side.
    sp<IGraphicBufferProducer> bufferProducer = bufferProducers[0];
    if (bufferProducer == nullptr) {
        ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                "Target Surface is invalid");
    }

    // Check if this stream id is one of the deferred only streams
    ssize_t index = NAME_NOT_FOUND;
    if (bufferProducers.size() == 1) {
        for (size_t i = 0; i < mDeferredStreams.size(); i++) {
            if (streamId == mDeferredStreams[i]) {
                index = i;
                break;
            }
        }

        if (index == NAME_NOT_FOUND) {
            String8 msg = String8::format("Camera %s: deferred surface is set to a unknown stream"
                    "(ID %d)", mCameraIdStr.string(), streamId);
            ALOGW("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
    }

    if (!mDevice.get()) {
        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
@@ -1116,8 +1238,12 @@ binder::Status CameraDeviceClient::setDeferredConfiguration(int32_t streamId,
    err = mDevice->setConsumerSurface(streamId, consumerSurface);
    if (err == OK) {
        sp<IBinder> binder = IInterface::asBinder(bufferProducer);
        mStreamMap.add(binder, streamId);
        ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %zu", __FUNCTION__,
                binder.get(), streamId, bufferProducers.size()-1);
        mStreamMap.add(binder, StreamSurfaceId(streamId, bufferProducers.size()-1));
        if (index != NAME_NOT_FOUND) {
            mDeferredStreams.removeItemsAt(index);
        }
    } else if (err == NO_INIT) {
        res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                "Camera %s: Deferred surface is invalid: %s (%d)",
@@ -1152,9 +1278,11 @@ status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) {
        result.append("    No input stream configured.\n");
    }
    if (!mStreamMap.isEmpty()) {
        result.append("    Current output stream IDs:\n");
        result.append("    Current output stream/surface IDs:\n");
        for (size_t i = 0; i < mStreamMap.size(); i++) {
            result.appendFormat("      Stream %d\n", mStreamMap.valueAt(i));
            result.appendFormat("      Stream %d Surface %d\n",
                                mStreamMap.valueAt(i).streamId(),
                                mStreamMap.valueAt(i).surfaceId());
        }
    } else if (!mDeferredStreams.isEmpty()) {
        result.append("    Current deferred surface output stream IDs:\n");
+33 −2

File changed.

Preview size limit exceeded, changes collapsed.

Loading