blob: 1b06ea725b48914a887e4ec891c658d99f5dcfdd [file] [log] [blame]
/*
* Copyright (C) 2021 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 "aaudio/AAudio.h"
#include "aaudio/AAudioTesting.h"
#include <fuzzer/FuzzedDataProvider.h>
#include <functional>
constexpr int32_t kRandomStringLength = 256;
constexpr int32_t kMaxRuns = 100;
constexpr int64_t kNanosPerMillisecond = 1000 * 1000;
constexpr aaudio_direction_t kDirections[] = {
AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT, AAUDIO_UNSPECIFIED};
constexpr aaudio_performance_mode_t kPerformanceModes[] = {
AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_UNSPECIFIED};
constexpr aaudio_format_t kFormats[] = {
AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_UNSPECIFIED,
AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
AAUDIO_FORMAT_PCM_I24_PACKED, AAUDIO_FORMAT_PCM_I32};
constexpr aaudio_sharing_mode_t kSharingModes[] = {
AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_SHARING_MODE_SHARED};
constexpr int32_t kSampleRates[] = {AAUDIO_UNSPECIFIED,
8000,
11025,
16000,
22050,
32000,
44100,
48000,
88200,
96000};
constexpr aaudio_usage_t kUsages[] = {
AAUDIO_USAGE_MEDIA,
AAUDIO_USAGE_VOICE_COMMUNICATION,
AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
AAUDIO_USAGE_ALARM,
AAUDIO_USAGE_NOTIFICATION,
AAUDIO_USAGE_NOTIFICATION_RINGTONE,
AAUDIO_USAGE_NOTIFICATION_EVENT,
AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
AAUDIO_USAGE_GAME,
AAUDIO_USAGE_ASSISTANT,
AAUDIO_SYSTEM_USAGE_EMERGENCY,
AAUDIO_SYSTEM_USAGE_SAFETY,
AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
AAUDIO_UNSPECIFIED};
constexpr aaudio_content_type_t kContentTypes[] = {
AAUDIO_CONTENT_TYPE_SPEECH, AAUDIO_CONTENT_TYPE_MUSIC,
AAUDIO_CONTENT_TYPE_MOVIE, AAUDIO_CONTENT_TYPE_SONIFICATION,
AAUDIO_UNSPECIFIED};
constexpr aaudio_input_preset_t kInputPresets[] = {
AAUDIO_INPUT_PRESET_GENERIC,
AAUDIO_INPUT_PRESET_CAMCORDER,
AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
AAUDIO_INPUT_PRESET_UNPROCESSED,
AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
AAUDIO_UNSPECIFIED};
constexpr aaudio_allowed_capture_policy_t kAllowedCapturePolicies[] = {
AAUDIO_ALLOW_CAPTURE_BY_ALL, AAUDIO_ALLOW_CAPTURE_BY_SYSTEM,
AAUDIO_ALLOW_CAPTURE_BY_NONE, AAUDIO_UNSPECIFIED};
constexpr aaudio_session_id_t kSessionIds[] = {
AAUDIO_SESSION_ID_NONE, AAUDIO_SESSION_ID_ALLOCATE, AAUDIO_UNSPECIFIED};
constexpr aaudio_policy_t kPolicies[] = {
AAUDIO_POLICY_NEVER, AAUDIO_POLICY_AUTO, AAUDIO_POLICY_ALWAYS,
AAUDIO_UNSPECIFIED};
class LibAaudioFuzzer {
public:
~LibAaudioFuzzer() { deInit(); }
bool init();
void invokeAAudioSetAPIs(FuzzedDataProvider &fdp);
void process(const uint8_t *data, size_t size);
void deInit();
private:
AAudioStreamBuilder *mAaudioBuilder = nullptr;
AAudioStream *mAaudioStream = nullptr;
};
bool LibAaudioFuzzer::init() {
aaudio_result_t result = AAudio_createStreamBuilder(&mAaudioBuilder);
if ((result != AAUDIO_OK) || (!mAaudioBuilder)) {
return false;
}
return true;
}
void LibAaudioFuzzer::invokeAAudioSetAPIs(FuzzedDataProvider &fdp){
aaudio_performance_mode_t mode = fdp.PickValueInArray(
{fdp.PickValueInArray(kPerformanceModes), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setPerformanceMode(mAaudioBuilder, mode);
int32_t deviceId = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setDeviceId(mAaudioBuilder, deviceId);
std::string packageName =
fdp.PickValueInArray<std::string>({"android.nativemedia.aaudio", "android.app.appops.cts",
fdp.ConsumeRandomLengthString(kRandomStringLength)});
AAudioStreamBuilder_setPackageName(mAaudioBuilder, packageName.c_str());
std::string attributionTag = fdp.ConsumeRandomLengthString(kRandomStringLength);
AAudioStreamBuilder_setAttributionTag(mAaudioBuilder, attributionTag.c_str());
int32_t sampleRate = fdp.PickValueInArray(kSampleRates);
AAudioStreamBuilder_setSampleRate(mAaudioBuilder, sampleRate);
int32_t channelCount = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setChannelCount(mAaudioBuilder, channelCount);
aaudio_direction_t direction =
fdp.PickValueInArray({fdp.PickValueInArray(kDirections), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setDirection(mAaudioBuilder, direction);
aaudio_format_t format =
fdp.PickValueInArray({fdp.PickValueInArray(kFormats), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setFormat(mAaudioBuilder, format);
aaudio_sharing_mode_t sharingMode = fdp.PickValueInArray(
{fdp.PickValueInArray(kSharingModes), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setSharingMode(mAaudioBuilder, sharingMode);
aaudio_usage_t usage =
fdp.PickValueInArray({fdp.PickValueInArray(kUsages), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setUsage(mAaudioBuilder, usage);
aaudio_content_type_t contentType = fdp.PickValueInArray(
{fdp.PickValueInArray(kContentTypes), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setContentType(mAaudioBuilder, contentType);
aaudio_input_preset_t inputPreset = fdp.PickValueInArray(
{fdp.PickValueInArray(kInputPresets), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setInputPreset(mAaudioBuilder, inputPreset);
bool privacySensitive = fdp.ConsumeBool();
AAudioStreamBuilder_setPrivacySensitive(mAaudioBuilder, privacySensitive);
int32_t frames = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setBufferCapacityInFrames(mAaudioBuilder, frames);
aaudio_allowed_capture_policy_t allowedCapturePolicy = fdp.PickValueInArray(
{fdp.PickValueInArray(kAllowedCapturePolicies), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setAllowedCapturePolicy(mAaudioBuilder, allowedCapturePolicy);
aaudio_session_id_t sessionId =
fdp.PickValueInArray({fdp.PickValueInArray(kSessionIds), fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setSessionId(mAaudioBuilder, sessionId);
AAudioStreamBuilder_setDataCallback(mAaudioBuilder, nullptr, nullptr);
AAudioStreamBuilder_setErrorCallback(mAaudioBuilder, nullptr, nullptr);
int32_t framesPerDataCallback =
fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
AAudioStreamBuilder_setFramesPerDataCallback(mAaudioBuilder, framesPerDataCallback);
aaudio_policy_t policy =
fdp.PickValueInArray({fdp.PickValueInArray(kPolicies), fdp.ConsumeIntegral<int32_t>()});
AAudio_setMMapPolicy(policy);
}
void LibAaudioFuzzer::process(const uint8_t *data, size_t size) {
FuzzedDataProvider fdp(data, size);
int32_t maxFrames = 0;
int32_t count = 0;
aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
invokeAAudioSetAPIs(fdp);
aaudio_result_t result = AAudioStreamBuilder_openStream(mAaudioBuilder, &mAaudioStream);
if ((result != AAUDIO_OK) || (!mAaudioStream)) {
return;
}
/* The 'runs' variable serves to set an upper limit on the loop iterations, preventing excessive
* execution.
*/
int32_t runs = kMaxRuns;
while (fdp.remaining_bytes() > 0 && --runs) {
auto AAudioapi = fdp.PickValueInArray<const std::function<void()>>({
[&]() { (void)AAudio_getMMapPolicy(); },
[&]() {
int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mAaudioStream);
uint8_t numberOfBursts = fdp.ConsumeIntegral<uint8_t>();
maxFrames = numberOfBursts * framesPerBurst;
int32_t requestedBufferSize = fdp.ConsumeIntegral<uint16_t>() * framesPerBurst;
AAudioStream_setBufferSizeInFrames(mAaudioStream, requestedBufferSize);
},
[&]() {
int64_t position = 0, nanoseconds = 0;
AAudioStream_getTimestamp(mAaudioStream, CLOCK_MONOTONIC, &position, &nanoseconds);
},
[&]() {
AAudioStream_requestStart(mAaudioStream);
},
[&]() {
AAudioStream_requestPause(mAaudioStream);
},
[&]() {
AAudioStream_requestFlush(mAaudioStream);
},
[&]() {
AAudioStream_requestStop(mAaudioStream);
},
[&]() {
aaudio_format_t actualFormat = AAudioStream_getFormat(mAaudioStream);
int32_t actualChannelCount = AAudioStream_getChannelCount(mAaudioStream);
count = fdp.ConsumeIntegral<int32_t>();
aaudio_direction_t direction = AAudioStream_getDirection(mAaudioStream);
if (actualFormat == AAUDIO_FORMAT_PCM_I16) {
std::vector<int16_t> inputShortData(maxFrames * actualChannelCount, 0x0);
if (direction == AAUDIO_DIRECTION_INPUT) {
AAudioStream_read(mAaudioStream, inputShortData.data(), maxFrames,
count * kNanosPerMillisecond);
} else if (direction == AAUDIO_DIRECTION_OUTPUT) {
AAudioStream_write(mAaudioStream, inputShortData.data(), maxFrames,
count * kNanosPerMillisecond);
}
} else if (actualFormat == AAUDIO_FORMAT_PCM_FLOAT) {
std::vector<float> inputFloatData(maxFrames * actualChannelCount, 0x0);
if (direction == AAUDIO_DIRECTION_INPUT) {
AAudioStream_read(mAaudioStream, inputFloatData.data(), maxFrames,
count * kNanosPerMillisecond);
} else if (direction == AAUDIO_DIRECTION_OUTPUT) {
AAudioStream_write(mAaudioStream, inputFloatData.data(), maxFrames,
count * kNanosPerMillisecond);
}
}
},
[&]() {
AAudioStream_waitForStateChange(mAaudioStream, AAUDIO_STREAM_STATE_UNKNOWN, &state,
count * kNanosPerMillisecond);
},
[&]() { (void)AAudio_convertStreamStateToText(state); },
[&]() {
(void)AAudioStream_getState(mAaudioStream);
},
[&]() {
(void)AAudioStream_getUsage(mAaudioStream);
},
[&]() {
(void)AAudioStream_getSamplesPerFrame(mAaudioStream);
},
[&]() {
(void)AAudioStream_getContentType(mAaudioStream);
},
[&]() {
(void)AAudioStream_getInputPreset(mAaudioStream);
},
[&]() {
(void)AAudioStream_isPrivacySensitive(mAaudioStream);
},
[&]() {
(void)AAudioStream_getAllowedCapturePolicy(mAaudioStream);
},
[&]() {
(void)AAudioStream_getPerformanceMode(mAaudioStream);
},
[&]() {
(void)AAudioStream_getDeviceId(mAaudioStream);
},
[&]() {
(void)AAudioStream_getSharingMode(mAaudioStream);
},
[&]() {
(void)AAudioStream_getSessionId(mAaudioStream);
},
[&]() {
(void)AAudioStream_getFramesRead(mAaudioStream);
},
[&]() {
(void)AAudioStream_getXRunCount(mAaudioStream);
},
[&]() {
(void)AAudioStream_getFramesWritten(mAaudioStream);
},
[&]() {
(void)AAudioStream_getBufferCapacityInFrames(mAaudioStream);
},
[&]() {
(void)AAudioStream_getBufferSizeInFrames(mAaudioStream);
},
[&]() {
(void)AAudioStream_isMMapUsed(mAaudioStream);
},
});
AAudioapi();
}
AAudioStream_release(mAaudioStream);
}
void LibAaudioFuzzer::deInit() {
if (mAaudioBuilder) {
AAudioStreamBuilder_delete(mAaudioBuilder);
}
if (mAaudioStream) {
AAudioStream_close(mAaudioStream);
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
LibAaudioFuzzer libAaudioFuzzer;
if (libAaudioFuzzer.init()) {
libAaudioFuzzer.process(data, size);
}
return 0;
}