blob: d09a6dd0320d360ccfe61b36f31ee84a61d4695c [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 <CameraBase.h>
#include <CameraMetadata.h>
#include <CameraParameters.h>
#include <CameraUtils.h>
#include <VendorTagDescriptor.h>
#include <binder/IMemory.h>
#include <binder/MemoryDealer.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <utils/Log.h>
#include "camera2common.h"
#include <android/hardware/ICameraService.h>
using namespace std;
using namespace android;
using namespace android::hardware;
constexpr int32_t kFrameRateMin = 1;
constexpr int32_t kFrameRateMax = 120;
constexpr int32_t kCamIdMin = 0;
constexpr int32_t kCamIdMax = 1;
constexpr int32_t kNumMin = 0;
constexpr int32_t kNumMax = 1024;
constexpr int32_t kMemoryDealerSize = 1000;
constexpr int32_t kRangeMin = 0;
constexpr int32_t kRangeMax = 1000;
constexpr int32_t kSizeMin = 0;
constexpr int32_t kSizeMax = 1000;
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};
constexpr int32_t kValidFacing[] = {android::hardware::CAMERA_FACING_BACK,
android::hardware::CAMERA_FACING_FRONT};
constexpr int32_t kValidOrientation[] = {0, 90, 180, 270};
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);
~CameraFuzzer() {
delete mCameraMetadata;
mComposerClient.clear();
mSurfaceControl.clear();
mSurface.clear();
mCamera.clear();
mMemoryDealer.clear();
mIMem.clear();
mCameraListener.clear();
mCameraService.clear();
}
private:
bool initCamera();
void initCameraMetadata();
void invokeCamera();
void invokeCameraUtils();
void invokeCameraBase();
void invokeCameraMetadata();
void invokeSetParameters();
sp<Camera> mCamera = nullptr;
CameraMetadata* mCameraMetadata = nullptr;
sp<SurfaceComposerClient> mComposerClient = nullptr;
sp<SurfaceControl> mSurfaceControl = nullptr;
sp<Surface> mSurface = nullptr;
sp<MemoryDealer> mMemoryDealer = nullptr;
sp<IMemory> mIMem = nullptr;
sp<TestCameraListener> mCameraListener = nullptr;
sp<ICameraService> mCameraService = nullptr;
sp<ICamera> cameraDevice = 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"));
mCameraService = interface_cast<ICameraService>(binder);
mCameraService->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);
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->ConsumeIntegralInRange<int32_t>(kCamIdMin, kCamIdMax);
Camera::getNumberOfCameras();
CameraInfo cameraInfo;
cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing)
: mFDP->ConsumeIntegral<int>();
cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation)
: mFDP->ConsumeIntegral<int>();
Camera::getCameraInfo(cameraId, /*overrideToPortrait*/false, &cameraInfo);
mCamera->reconnect();
mComposerClient = new SurfaceComposerClient;
mSurfaceControl = mComposerClient->createSurface(
static_cast<String8>(mFDP->ConsumeRandomLengthString().c_str()) /* name */,
mFDP->ConsumeIntegral<uint32_t>() /* width */,
mFDP->ConsumeIntegral<uint32_t>() /* height */,
mFDP->ConsumeIntegral<int32_t>() /* format */,
mFDP->ConsumeIntegral<int32_t>() /* flags */);
if (mSurfaceControl) {
mSurface = mSurfaceControl->getSurface();
mCamera->setPreviewTarget(mSurface->getIGraphicBufferProducer());
mCamera->startPreview();
mCamera->stopPreview();
mCamera->previewEnabled();
mCamera->startRecording();
mCamera->stopRecording();
}
mCamera->lock();
mCamera->unlock();
mCamera->autoFocus();
mCamera->cancelAutoFocus();
int32_t msgType = mFDP->ConsumeIntegral<int32_t>();
mCamera->takePicture(msgType);
invokeSetParameters();
int32_t cmd;
if (mFDP->ConsumeBool()) {
cmd = mFDP->PickValueInArray(kValidCMD);
} else {
cmd = 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->PickValueInArray(kValidVideoBufferMode);
mCamera->setVideoBufferMode(videoBufferMode);
if (mSurfaceControl) {
mSurface = mSurfaceControl->getSurface();
mCamera->setVideoTarget(mSurface->getIGraphicBufferProducer());
}
mCameraListener = sp<TestCameraListener>::make();
mCamera->setListener(mCameraListener);
int32_t previewCallbackFlag;
if (mFDP->ConsumeBool()) {
previewCallbackFlag = mFDP->PickValueInArray(kValidPreviewCallbackFlag);
} else {
previewCallbackFlag = mFDP->ConsumeIntegral<int32_t>();
}
mCamera->setPreviewCallbackFlags(previewCallbackFlag);
if (mSurfaceControl) {
mSurface = mSurfaceControl->getSurface();
mCamera->setPreviewCallbackTarget(mSurface->getIGraphicBufferProducer());
}
mCamera->getRecordingProxy();
int32_t mode = mFDP->ConsumeIntegral<int32_t>();
mCamera->setAudioRestriction(mode);
mCamera->getGlobalAudioRestriction();
mCamera->recordingEnabled();
mMemoryDealer = new MemoryDealer(kMemoryDealerSize);
mIMem = mMemoryDealer->allocate(kMemoryDealerSize);
mCamera->releaseRecordingFrame(mIMem);
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);
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);
int64_t timestamp = mFDP->ConsumeIntegral<int64_t>();
mCamera->dataCallbackTimestamp(timestamp, msgTypeNC, mIMem);
mCamera->recordingFrameHandleCallbackTimestamp(timestamp, handle);
}
void CameraFuzzer::invokeCameraUtils() {
CameraMetadata staticMetadata;
int32_t orientVal = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation)
: mFDP->ConsumeIntegral<int32_t>();
uint8_t facingVal = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing)
: mFDP->ConsumeIntegral<uint8_t>();
staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
int32_t transform = 0;
CameraUtils::getRotationTransform(
staticMetadata, mFDP->ConsumeIntegral<int32_t>() /* mirrorMode */, &transform /*out*/);
CameraUtils::isCameraServiceDisabled();
}
void CameraFuzzer::invokeCameraBase() {
CameraInfo cameraInfo;
cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing)
: mFDP->ConsumeIntegral<int>();
cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation)
: mFDP->ConsumeIntegral<int>();
invokeReadWriteParcel<CameraInfo>(&cameraInfo);
CameraStatus* cameraStatus = nullptr;
if (mFDP->ConsumeBool()) {
cameraStatus = new CameraStatus();
} else {
string cid = mFDP->ConsumeRandomLengthString();
int32_t status = mFDP->ConsumeIntegral<int32_t>();
size_t unavailSubIdsSize = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
vector<std::string> unavailSubIds;
for (size_t idx = 0; idx < unavailSubIdsSize; ++idx) {
string subId = mFDP->ConsumeRandomLengthString();
unavailSubIds.push_back(subId);
}
string clientPackage = mFDP->ConsumeRandomLengthString();
cameraStatus = new CameraStatus(cid, status, unavailSubIds, clientPackage);
}
invokeReadWriteParcel<CameraStatus>(cameraStatus);
delete cameraStatus;
}
void CameraFuzzer::initCameraMetadata() {
if (mFDP->ConsumeBool()) {
mCameraMetadata = new CameraMetadata();
} else {
size_t entryCapacity = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
size_t dataCapacity = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
mCameraMetadata = new CameraMetadata(entryCapacity, dataCapacity);
}
}
void CameraFuzzer::invokeCameraMetadata() {
initCameraMetadata();
const camera_metadata_t* metadataBuffer = nullptr;
if (mFDP->ConsumeBool()) {
metadataBuffer = mCameraMetadata->getAndLock();
}
mCameraMetadata->entryCount();
mCameraMetadata->isEmpty();
mCameraMetadata->bufferSize();
mCameraMetadata->sort();
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
uint8_t dataUint8 = mFDP->ConsumeIntegral<uint8_t>();
int32_t dataInt32 = mFDP->ConsumeIntegral<int32_t>();
int64_t dataInt64 = mFDP->ConsumeIntegral<int64_t>();
float dataFloat = mFDP->ConsumeFloatingPoint<float>();
double dataDouble = mFDP->ConsumeFloatingPoint<double>();
camera_metadata_rational dataRational;
dataRational.numerator = mFDP->ConsumeIntegral<int32_t>();
dataRational.denominator = mFDP->ConsumeIntegral<int32_t>();
string dataStr = mFDP->ConsumeRandomLengthString();
String8 dataString(dataStr.c_str());
size_t data_count = 1;
mCameraMetadata->update(tag, &dataUint8, data_count);
mCameraMetadata->update(tag, &dataInt32, data_count);
mCameraMetadata->update(tag, &dataFloat, data_count);
mCameraMetadata->update(tag, &dataInt64, data_count);
mCameraMetadata->update(tag, &dataRational, data_count);
mCameraMetadata->update(tag, &dataDouble, data_count);
mCameraMetadata->update(tag, dataString);
uint32_t tagExists = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->exists(tagExists);
uint32_t tagFind = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->find(tagFind);
uint32_t tagErase = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->erase(tagErase);
mCameraMetadata->unlock(metadataBuffer);
std::vector<int32_t> tagsRemoved;
uint64_t vendorId = mFDP->ConsumeIntegral<uint64_t>();
mCameraMetadata->removePermissionEntries(vendorId, &tagsRemoved);
string name = mFDP->ConsumeRandomLengthString();
VendorTagDescriptor vTags;
uint32_t tagName = mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->getTagFromName(name.c_str(), &vTags, &tagName);
invokeReadWriteNullParcel<CameraMetadata>(mCameraMetadata);
invokeReadWriteParcel<CameraMetadata>(mCameraMetadata);
int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
int32_t verbosity = mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
int32_t indentation = mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
mCameraMetadata->dump(fd, verbosity, indentation);
CameraMetadata metadataCopy(mCameraMetadata->release());
CameraMetadata otherCameraMetadata;
mCameraMetadata->swap(otherCameraMetadata);
close(fd);
}
void CameraFuzzer::process(const uint8_t* data, size_t size) {
mFDP = new FuzzedDataProvider(data, size);
invokeCamera();
invokeCameraUtils();
invokeCameraBase();
invokeCameraMetadata();
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;
}