blob: c2a7549871dd0cfe0b8c5ce52a1873c9f120ba2c [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#include <Camera.h>
#include <CameraParameters.h>
#include <binder/MemoryDealer.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include "camera2common.h"
using namespace std;
using namespace android;
using namespace android::hardware;
constexpr int32_t kFrameRateMin = 1;
constexpr int32_t kFrameRateMax = 1000;
constexpr int32_t kNumMin = 0;
constexpr int32_t kNumMax = 1024;
constexpr int32_t kMemoryDealerSize = 1000;
constexpr int8_t kMinElements = 1;
constexpr int8_t kMaxElements = 10;
constexpr int32_t kValidCMD[] = {CAMERA_CMD_START_SMOOTH_ZOOM,
CAMERA_CMD_STOP_SMOOTH_ZOOM,
CAMERA_CMD_SET_DISPLAY_ORIENTATION,
CAMERA_CMD_ENABLE_SHUTTER_SOUND,
CAMERA_CMD_PLAY_RECORDING_SOUND,
CAMERA_CMD_START_FACE_DETECTION,
CAMERA_CMD_STOP_FACE_DETECTION,
CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG,
CAMERA_CMD_PING,
CAMERA_CMD_SET_VIDEO_BUFFER_COUNT,
CAMERA_CMD_SET_VIDEO_FORMAT};
constexpr int32_t kValidVideoBufferMode[] = {ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV,
ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA,
ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE};
constexpr int32_t kValidPreviewCallbackFlag[] = {
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK, CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK,
CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK, CAMERA_FRAME_CALLBACK_FLAG_NOOP,
CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER, CAMERA_FRAME_CALLBACK_FLAG_CAMERA,
CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER};
class TestCameraListener : public CameraListener {
public:
virtual ~TestCameraListener() = default;
void notify(int32_t /*msgType*/, int32_t /*ext1*/, int32_t /*ext2*/) override { return; };
void postData(int32_t /*msgType*/, const sp<IMemory>& /*dataPtr*/,
camera_frame_metadata_t* /*metadata*/) override {
return;
};
void postDataTimestamp(nsecs_t /*timestamp*/, int32_t /*msgType*/,
const sp<IMemory>& /*dataPtr*/) override {
return;
};
void postRecordingFrameHandleTimestamp(nsecs_t /*timestamp*/,
native_handle_t* /*handle*/) override {
return;
};
void postRecordingFrameHandleTimestampBatch(
const std::vector<nsecs_t>& /*timestamps*/,
const std::vector<native_handle_t*>& /*handles*/) override {
return;
};
};
class CameraFuzzer : public ::android::hardware::BnCameraClient {
public:
void process(const uint8_t* data, size_t size);
private:
bool initCamera();
void invokeCamera();
void invokeSetParameters();
sp<Camera> mCamera = nullptr;
FuzzedDataProvider* mFDP = nullptr;
// CameraClient interface
void notifyCallback(int32_t, int32_t, int32_t) override { return; };
void dataCallback(int32_t, const sp<IMemory>&, camera_frame_metadata_t*) override { return; };
void dataCallbackTimestamp(nsecs_t, int32_t, const sp<IMemory>&) override { return; };
void recordingFrameHandleCallbackTimestamp(nsecs_t, native_handle_t*) override { return; };
void recordingFrameHandleCallbackTimestampBatch(const std::vector<nsecs_t>&,
const std::vector<native_handle_t*>&) override {
return;
};
};
bool CameraFuzzer::initCamera() {
ProcessState::self()->startThreadPool();
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.camera"));
sp<ICameraService> cameraService = nullptr;
cameraService = interface_cast<ICameraService>(binder);
sp<ICamera> cameraDevice = nullptr;
if (mFDP->ConsumeBool()) {
cameraService->connect(this, mFDP->ConsumeIntegral<int32_t>() /* cameraId */, "CAMERAFUZZ",
hardware::ICameraService::USE_CALLING_UID,
hardware::ICameraService::USE_CALLING_PID,
/*targetSdkVersion*/ __ANDROID_API_FUTURE__,
/*overrideToPortrait*/ false, /*forceSlowJpegMode*/ false,
&cameraDevice);
} else {
cameraService->connect(this, mFDP->ConsumeIntegral<int32_t>() /* cameraId */,
mFDP->ConsumeRandomLengthString(kMaxBytes).c_str(),
mFDP->ConsumeIntegral<int8_t>() /* clientUid */,
mFDP->ConsumeIntegral<int8_t>() /* clientPid */,
/*targetSdkVersion*/ mFDP->ConsumeIntegral<int32_t>(),
/*overrideToPortrait*/ mFDP->ConsumeBool(),
/*forceSlowJpegMode*/ mFDP->ConsumeBool(), &cameraDevice);
}
mCamera = Camera::create(cameraDevice);
if (!mCamera) {
return false;
}
return true;
}
void CameraFuzzer::invokeSetParameters() {
String8 s = mCamera->getParameters();
CameraParameters params(s);
int32_t width = mFDP->ConsumeIntegral<int32_t>();
int32_t height = mFDP->ConsumeIntegral<int32_t>();
params.setVideoSize(width, height);
int32_t frameRate = mFDP->ConsumeIntegralInRange<int32_t>(kFrameRateMin, kFrameRateMax);
params.setPreviewFrameRate(frameRate);
mCamera->setParameters(params.flatten());
}
void CameraFuzzer::invokeCamera() {
if (!initCamera()) {
return;
}
int32_t cameraId = mFDP->ConsumeIntegral<int32_t>();
Camera::getNumberOfCameras();
CameraInfo cameraInfo;
cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing)
: mFDP->ConsumeIntegral<int32_t>();
cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation)
: mFDP->ConsumeIntegral<int32_t>();
Camera::getCameraInfo(cameraId, /*overrideToPortrait*/false, &cameraInfo);
mCamera->reconnect();
sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
sp<SurfaceControl> surfaceControl = nullptr;
if (mFDP->ConsumeBool()) {
surfaceControl = composerClient->createSurface(String8("FUZZSURFACE"), 1280, 800,
HAL_PIXEL_FORMAT_YV12);
} else {
surfaceControl = composerClient->createSurface(
static_cast<String8>(mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()) /* name */,
mFDP->ConsumeIntegral<uint32_t>() /* width */,
mFDP->ConsumeIntegral<uint32_t>() /* height */,
mFDP->ConsumeIntegral<int32_t>() /* format */,
mFDP->ConsumeIntegral<int32_t>() /* flags */);
}
if (mFDP->ConsumeBool()) {
invokeSetParameters();
}
sp<Surface> surface = nullptr;
if (surfaceControl) {
surface = surfaceControl->getSurface();
}
sp<MemoryDealer> memoryDealer = nullptr;
sp<IMemory> iMem = nullptr;
sp<CameraListener> cameraListener = nullptr;
while (mFDP->remaining_bytes()) {
auto callCameraAPIs = mFDP->PickValueInArray<const std::function<void()>>({
[&]() {
if (surfaceControl) {
mCamera->setPreviewTarget(surface->getIGraphicBufferProducer());
}
},
[&]() {
if (surfaceControl) {
mCamera->startPreview();
}
},
[&]() {
if (surfaceControl) {
mCamera->stopPreview();
}
},
[&]() {
if (surfaceControl) {
mCamera->stopPreview();
}
},
[&]() {
if (surfaceControl) {
mCamera->previewEnabled();
}
},
[&]() {
if (surfaceControl) {
mCamera->startRecording();
}
},
[&]() {
if (surfaceControl) {
mCamera->stopRecording();
}
},
[&]() { mCamera->lock(); },
[&]() { mCamera->unlock(); },
[&]() { mCamera->autoFocus(); },
[&]() { mCamera->cancelAutoFocus(); },
[&]() {
int32_t msgType = mFDP->ConsumeIntegral<int32_t>();
mCamera->takePicture(msgType);
},
[&]() {
int32_t cmd;
cmd = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidCMD)
: mFDP->ConsumeIntegral<int32_t>();
int32_t arg1 = mFDP->ConsumeIntegral<int32_t>();
int32_t arg2 = mFDP->ConsumeIntegral<int32_t>();
mCamera->sendCommand(cmd, arg1, arg2);
},
[&]() {
int32_t videoBufferMode =
mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidVideoBufferMode)
: mFDP->ConsumeIntegral<int32_t>();
mCamera->setVideoBufferMode(videoBufferMode);
},
[&]() {
if (surfaceControl) {
mCamera->setVideoTarget(surface->getIGraphicBufferProducer());
}
},
[&]() {
cameraListener = sp<TestCameraListener>::make();
mCamera->setListener(cameraListener);
},
[&]() {
int32_t previewCallbackFlag;
previewCallbackFlag =
mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidPreviewCallbackFlag)
: mFDP->ConsumeIntegral<int32_t>();
mCamera->setPreviewCallbackFlags(previewCallbackFlag);
},
[&]() {
if (surfaceControl) {
mCamera->setPreviewCallbackTarget(surface->getIGraphicBufferProducer());
}
},
[&]() { mCamera->getRecordingProxy(); },
[&]() {
int32_t mode = mFDP->ConsumeIntegral<int32_t>();
mCamera->setAudioRestriction(mode);
},
[&]() { mCamera->getGlobalAudioRestriction(); },
[&]() { mCamera->recordingEnabled(); },
[&]() {
memoryDealer = new MemoryDealer(kMemoryDealerSize);
iMem = memoryDealer->allocate(kMemoryDealerSize);
},
[&]() {
int32_t msgTypeNC = mFDP->ConsumeIntegral<int32_t>();
int32_t ext = mFDP->ConsumeIntegral<int32_t>();
int32_t ext2 = mFDP->ConsumeIntegral<int32_t>();
mCamera->notifyCallback(msgTypeNC, ext, ext2);
},
[&]() {
int32_t msgTypeNC = mFDP->ConsumeIntegral<int32_t>();
int64_t timestamp = mFDP->ConsumeIntegral<int64_t>();
mCamera->dataCallbackTimestamp(timestamp, msgTypeNC, iMem);
},
[&]() {
int64_t timestamp = mFDP->ConsumeIntegral<int64_t>();
int32_t numFds = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
int32_t numInts = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
native_handle_t* handle = native_handle_create(numFds, numInts);
mCamera->recordingFrameHandleCallbackTimestamp(timestamp, handle);
},
[&]() {
int32_t numFds = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
int32_t numInts = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
native_handle_t* handle = native_handle_create(numFds, numInts);
mCamera->releaseRecordingFrameHandle(handle);
},
[&]() { mCamera->releaseRecordingFrame(iMem); },
[&]() {
std::vector<native_handle_t*> handles;
for (int8_t i = 0;
i < mFDP->ConsumeIntegralInRange<int8_t>(kMinElements, kMaxElements);
++i) {
int32_t numFds = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
int32_t numInts = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
native_handle_t* handle = native_handle_create(numFds, numInts);
handles.push_back(handle);
}
mCamera->releaseRecordingFrameHandleBatch(handles);
},
[&]() {
std::vector<native_handle_t*> handles;
for (int8_t i = 0;
i < mFDP->ConsumeIntegralInRange<int8_t>(kMinElements, kMaxElements);
++i) {
int32_t numFds = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
int32_t numInts = mFDP->ConsumeIntegralInRange<int32_t>(kNumMin, kNumMax);
native_handle_t* handle = native_handle_create(numFds, numInts);
handles.push_back(handle);
}
std::vector<nsecs_t> timestamps;
for (int8_t i = 0;
i < mFDP->ConsumeIntegralInRange<int8_t>(kMinElements, kMaxElements);
++i) {
timestamps.push_back(mFDP->ConsumeIntegral<int64_t>());
}
mCamera->recordingFrameHandleCallbackTimestampBatch(timestamps, handles);
},
});
callCameraAPIs();
}
}
void CameraFuzzer::process(const uint8_t* data, size_t size) {
mFDP = new FuzzedDataProvider(data, size);
invokeCamera();
delete mFDP;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
sp<CameraFuzzer> cameraFuzzer = new CameraFuzzer();
cameraFuzzer->process(data, size);
cameraFuzzer.clear();
return 0;
}