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

Commit afe8a015 authored by Jayant Chowdhary's avatar Jayant Chowdhary Committed by Android (Google) Code Review
Browse files

Merge "camera: Add basic fuzz test for libcameraservice camera2 implementation." into sc-dev

parents df5f49fa 32ced0e6
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ CameraService::CameraService() :

void CameraService::onFirstRef()
{

    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();
@@ -752,6 +753,10 @@ Status CameraService::getCameraVendorTagCache(
    return Status::ok();
}

void CameraService::clearCachedVariables() {
    BasicClient::BasicClient::sCameraService = nullptr;
}

int CameraService::getDeviceVersion(const String8& cameraId, int* facing, int* orientation) {
    ATRACE_CALL();

@@ -2154,10 +2159,15 @@ Status CameraService::addListener(const sp<ICameraServiceListener>& listener,
    return addListenerHelper(listener, cameraStatuses);
}

binder::Status CameraService::addListenerTest(const sp<hardware::ICameraServiceListener>& listener,
            std::vector<hardware::CameraStatus>* cameraStatuses) {
    return addListenerHelper(listener, cameraStatuses, false, true);
}

Status CameraService::addListenerHelper(const sp<ICameraServiceListener>& listener,
        /*out*/
        std::vector<hardware::CameraStatus> *cameraStatuses,
        bool isVendorListener) {
        bool isVendorListener, bool isProcessLocalTest) {

    ATRACE_CALL();

@@ -2188,7 +2198,7 @@ Status CameraService::addListenerHelper(const sp<ICameraServiceListener>& listen
        sp<ServiceListener> serviceListener =
                new ServiceListener(this, listener, clientUid, clientPid, isVendorListener,
                        openCloseCallbackAllowed);
        auto ret = serviceListener->initialize();
        auto ret = serviceListener->initialize(isProcessLocalTest);
        if (ret != NO_ERROR) {
            String8 msg = String8::format("Failed to initialize service listener: %s (%d)",
                    strerror(-ret), ret);
+20 −2
Original line number Diff line number Diff line
@@ -190,7 +190,8 @@ public:

    binder::Status      addListenerHelper(const sp<hardware::ICameraServiceListener>& listener,
            /*out*/
            std::vector<hardware::CameraStatus>* cameraStatuses, bool isVendor = false);
            std::vector<hardware::CameraStatus>* cameraStatuses, bool isVendor = false,
            bool isProcessLocalTest = false);

    // Monitored UIDs availability notification
    void                notifyMonitoredUids();
@@ -218,6 +219,19 @@ public:
    int                 getDeviceVersion(const String8& cameraId, int* facing = nullptr,
            int* orientation = nullptr);

    /////////////////////////////////////////////////////////////////////
    // Methods to be used in CameraService class tests only
    //
    // CameraService class test method only - clear static variables in the
    // cameraserver process, which otherwise might affect multiple test runs.
    void                clearCachedVariables();

    // Add test listener, linkToDeath won't be called since this is for process
    // local testing.
    binder::Status    addListenerTest(const sp<hardware::ICameraServiceListener>& listener,
            /*out*/
            std::vector<hardware::CameraStatus>* cameraStatuses);

    /////////////////////////////////////////////////////////////////////
    // Shared utilities
    static binder::Status filterGetInfoErrorCode(status_t err);
@@ -226,6 +240,7 @@ public:
    // CameraClient functionality

    class BasicClient : public virtual RefBase {
    friend class CameraService;
    public:
        virtual status_t       initialize(sp<CameraProviderManager> manager,
                const String8& monitorTags) = 0;
@@ -928,7 +943,10 @@ private:
                      mIsVendorListener(isVendorClient),
                      mOpenCloseCallbackAllowed(openCloseCallbackAllowed) { }

            status_t initialize() {
            status_t initialize(bool isProcessLocalTest) {
                if (isProcessLocalTest) {
                    return OK;
                }
                return IInterface::asBinder(mListener)->linkToDeath(this);
            }

+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ cc_fuzz {
        "libcutils",
        "libcameraservice",
        "libcamera_client",
        "liblog",
        "libui",
        "libgui",
        "android.hardware.camera.common@1.0",
+191 −26
Original line number Diff line number Diff line
@@ -18,8 +18,18 @@
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */

#define LOG_TAG "CameraServiceFuzzer"
//#define LOG_NDEBUG 0

#include <CameraService.h>
#include <device3/Camera3StreamInterface.h>
#include <android/hardware/BnCameraServiceListener.h>
#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include <camera/camera2/OutputConfiguration.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/android_filesystem_config.h>
@@ -30,6 +40,7 @@ using namespace hardware;
using namespace std;

const int32_t kPreviewThreshold = 8;
const int32_t kNumRequestsTested = 8;
const nsecs_t kPreviewTimeout = 5000000000;  // .5 [s.]
const nsecs_t kEventTimeout = 10000000000;   // 1 [s.]
const size_t kMaxNumLines = USHRT_MAX;
@@ -39,6 +50,23 @@ const int32_t kCamType[] = {hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPA
                            hardware::ICameraService::CAMERA_TYPE_ALL};
const int kCameraApiVersion[] = {android::CameraService::API_VERSION_1,
                                 android::CameraService::API_VERSION_2};
const uint8_t kSensorPixelModes[] = {ANDROID_SENSOR_PIXEL_MODE_DEFAULT,
        ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION};
const int32_t kRequestTemplates[] = {
    hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW,
    hardware::camera2::ICameraDeviceUser::TEMPLATE_STILL_CAPTURE,
    hardware::camera2::ICameraDeviceUser::TEMPLATE_RECORD,
    hardware::camera2::ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT,
    hardware::camera2::ICameraDeviceUser::TEMPLATE_MANUAL,
    hardware::camera2::ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG
};

const int32_t kRotations[] = {
    camera3::CAMERA_STREAM_ROTATION_0,
    camera3::CAMERA_STREAM_ROTATION_90,
    camera3::CAMERA_STREAM_ROTATION_270
};

const int kLayerMetadata[] = {
    0x00100000 /*GRALLOC_USAGE_RENDERSCRIPT*/, 0x00000003 /*GRALLOC_USAGE_SW_READ_OFTEN*/,
    0x00000100 /*GRALLOC_USAGE_HW_TEXTURE*/,   0x00000800 /*GRALLOC_USAGE_HW_COMPOSER*/,
@@ -69,15 +97,15 @@ const size_t kNumShellCmd = size(kShellCmd);

class CameraFuzzer : public ::android::hardware::BnCameraClient {
   public:
    CameraFuzzer() = default;
    CameraFuzzer(sp<CameraService> cs, std::shared_ptr<FuzzedDataProvider> fp) :
          mCameraService(cs), mFuzzedDataProvider(fp) {};
    ~CameraFuzzer() { deInit(); }
    bool init();
    void process(const uint8_t *data, size_t size);
    void process();
    void deInit();

   private:
    FuzzedDataProvider *mFuzzedDataProvider = nullptr;
    sp<CameraService> mCameraService = nullptr;
    std::shared_ptr<FuzzedDataProvider> mFuzzedDataProvider = nullptr;
    sp<SurfaceComposerClient> mComposerClient = nullptr;
    int32_t mNumCameras = 0;
    size_t mPreviewBufferCount = 0;
@@ -167,19 +195,7 @@ status_t CameraFuzzer::waitForEvent(Mutex &mutex, Condition &condition, bool &fl
    return rc;
}

bool CameraFuzzer::init() {
    setuid(AID_MEDIA);
    mCameraService = new CameraService();
    if (mCameraService) {
        return true;
    }
    return false;
}

void CameraFuzzer::deInit() {
    if (mCameraService) {
        mCameraService = nullptr;
    }
    if (mComposerClient) {
        mComposerClient->dispose();
    }
@@ -298,11 +314,11 @@ void CameraFuzzer::invokeCameraAPIs() {
    for (int32_t cameraId = 0; cameraId < mNumCameras; ++cameraId) {
        getCameraInformation(cameraId);

        const String16 opPackageName("com.fuzzer.poc");
        ::android::binder::Status rc;
        sp<ICamera> cameraDevice;

        rc = mCameraService->connect(this, cameraId, opPackageName, AID_MEDIA, AID_ROOT,
        rc = mCameraService->connect(this, cameraId, String16(),
                android::CameraService::USE_CALLING_UID, android::CameraService::USE_CALLING_PID,
                &cameraDevice);
        if (!rc.isOk()) {
            // camera not connected
@@ -405,8 +421,7 @@ void CameraFuzzer::invokeCameraAPIs() {
    }
}

void CameraFuzzer::process(const uint8_t *data, size_t size) {
    mFuzzedDataProvider = new FuzzedDataProvider(data, size);
void CameraFuzzer::process() {
    getNumCameras();
    invokeCameraSound();
    if (mNumCameras > 0) {
@@ -415,19 +430,169 @@ void CameraFuzzer::process(const uint8_t *data, size_t size) {
    invokeDump();
    invokeShellCommand();
    invokeNotifyCalls();
    delete mFuzzedDataProvider;
}

class TestCameraServiceListener : public hardware::BnCameraServiceListener {
public:
    virtual ~TestCameraServiceListener() {};

    virtual binder::Status onStatusChanged(int32_t , const String16&) {
        return binder::Status::ok();
    };

    virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
            const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
        // No op
        return binder::Status::ok();
    };

    virtual binder::Status onTorchStatusChanged(int32_t /*status*/, const String16& /*cameraId*/) {
        return binder::Status::ok();
    };

    virtual binder::Status onCameraAccessPrioritiesChanged() {
        // No op
        return binder::Status::ok();
    }

    virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
            const String16& /*clientPackageName*/) {
        // No op
        return binder::Status::ok();
    }

    virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
        // No op
        return binder::Status::ok();
    }
};

class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
public:
    TestCameraDeviceCallbacks() {}

    virtual ~TestCameraDeviceCallbacks() {}

    virtual binder::Status onDeviceError(int /*errorCode*/,
            const CaptureResultExtras& /*resultExtras*/) {
        return binder::Status::ok();
    }

    virtual binder::Status onDeviceIdle() {
        return binder::Status::ok();
    }

    virtual binder::Status onCaptureStarted(const CaptureResultExtras& /*resultExtras*/,
            int64_t /*timestamp*/) {
        return binder::Status::ok();
    }

    virtual binder::Status onResultReceived(const CameraMetadata& /*metadata*/,
            const CaptureResultExtras& /*resultExtras*/,
            const std::vector<PhysicalCaptureResultInfo>& /*physicalResultInfos*/) {
        return binder::Status::ok();
    }

    virtual binder::Status onPrepared(int /*streamId*/) {
        return binder::Status::ok();
    }

    virtual binder::Status onRepeatingRequestError(
            int64_t /*lastFrameNumber*/, int32_t /*stoppedSequenceId*/) {
        return binder::Status::ok();
    }

    virtual binder::Status onRequestQueueEmpty() {
        return binder::Status::ok();
    }
};

class Camera2Fuzzer {
   public:
    Camera2Fuzzer(sp<CameraService> cs, std::shared_ptr<FuzzedDataProvider> fp) :
          mCameraService(cs), mFuzzedDataProvider(fp) { };
    ~Camera2Fuzzer() {}
    void process();
   private:
    sp<CameraService> mCameraService = nullptr;
    std::shared_ptr<FuzzedDataProvider> mFuzzedDataProvider = nullptr;
};

void Camera2Fuzzer::process() {
    sp<TestCameraServiceListener> listener = new TestCameraServiceListener();
    std::vector<hardware::CameraStatus> statuses;
    mCameraService->addListenerTest(listener, &statuses);
    for (auto s : statuses) {
        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
        sp<hardware::camera2::ICameraDeviceUser> device;
        mCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
                android::CameraService::USE_CALLING_UID, &device);
        if (device == nullptr) {
            continue;
        }
        device->beginConfigure();
        sp<IGraphicBufferProducer> gbProducer;
        sp<IGraphicBufferConsumer> gbConsumer;
        BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
        sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer,
                GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/8, /*controlledByApp*/true);
        opaqueConsumer->setName(String8("Roger"));

        // Set to VGA dimension for default, as that is guaranteed to be present
        gbConsumer->setDefaultBufferSize(640, 480);
        gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);

        sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));

        String16 noPhysicalId;
        size_t rotations = sizeof(kRotations) / sizeof(int32_t) - 1;
        OutputConfiguration output(gbProducer,
                kRotations[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, rotations)],
                noPhysicalId);
        int streamId;
        device->createStream(output, &streamId);
        CameraMetadata sessionParams;
        std::vector<int> offlineStreamIds;
        device->endConfigure(/*isConstrainedHighSpeed*/ mFuzzedDataProvider->ConsumeBool(),
                sessionParams, ns2ms(systemTime()), &offlineStreamIds);

        CameraMetadata requestTemplate;
        size_t requestTemplatesSize =  sizeof(kRequestTemplates) /sizeof(int32_t)  - 1;
        device->createDefaultRequest(kRequestTemplates[
                mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, requestTemplatesSize)],
                /*out*/&requestTemplate);
        hardware::camera2::CaptureRequest request;
        request.mSurfaceList.add(surface);
        request.mIsReprocess = false;
        hardware::camera2::utils::SubmitInfo info;
        for (int i = 0; i < kNumRequestsTested; i++) {
            uint8_t sensorPixelMode =
                    kSensorPixelModes[mFuzzedDataProvider->ConsumeBool() ? 1 : 0];
            requestTemplate.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1);
            request.mPhysicalCameraSettings.clear();
            request.mPhysicalCameraSettings.push_back({s.cameraId.string(), requestTemplate});
            device->submitRequest(request, /*streaming*/false, /*out*/&info);
            ALOGV("%s : camera id %s submit request id %d",__FUNCTION__, s.cameraId.string(),
                    info.mRequestId);
        }
        device->disconnect();
    }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if (size < 1) {
        return 0;
    }
    sp<CameraFuzzer> camerafuzzer = new CameraFuzzer();
    setuid(AID_CAMERASERVER);
    std::shared_ptr<FuzzedDataProvider> fp = std::make_shared<FuzzedDataProvider>(data, size);
    sp<CameraService> cs = new CameraService();
    cs->clearCachedVariables();
    sp<CameraFuzzer> camerafuzzer = new CameraFuzzer(cs, fp);
    if (!camerafuzzer) {
        return 0;
    }
    if (camerafuzzer->init()) {
        camerafuzzer->process(data, size);
    }
    camerafuzzer->process();
    Camera2Fuzzer camera2fuzzer(cs, fp);
    camera2fuzzer.process();
    return 0;
}