/****************************************************************************** * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace android; namespace xsd { using namespace ::android::audio::policy::configuration::V7_0; } using content::AttributionSourceState; static const std::vector kAudioFormats = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_format_t audioFormatHal; std::string audioFormat = toString(enumVal); if (audio_format_from_string(audioFormat.c_str(), &audioFormatHal)) { result.push_back(audioFormatHal); } } return result; }(); static const std::vector kAudioChannelOutMasks = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_channel_mask_t audioChannelMaskHal; std::string audioChannelMask = toString(enumVal); if (enumVal != xsd::AudioChannelMask::AUDIO_CHANNEL_NONE && audioChannelMask.find("_IN_") == std::string::npos && audio_channel_mask_from_string(audioChannelMask.c_str(), &audioChannelMaskHal)) { result.push_back(audioChannelMaskHal); } } return result; }(); static const std::vector kAudioChannelInMasks = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_channel_mask_t audioChannelMaskHal; std::string audioChannelMask = toString(enumVal); if (enumVal != xsd::AudioChannelMask::AUDIO_CHANNEL_NONE && audioChannelMask.find("_OUT_") == std::string::npos && audio_channel_mask_from_string(audioChannelMask.c_str(), &audioChannelMaskHal)) { result.push_back(audioChannelMaskHal); } } return result; }(); static const std::vector kAudioOutputFlags = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_output_flags_t audioOutputFlagHal; std::string audioOutputFlag = toString(enumVal); if (audioOutputFlag.find("_OUTPUT_") != std::string::npos && audio_output_flag_from_string(audioOutputFlag.c_str(), &audioOutputFlagHal)) { result.push_back(audioOutputFlagHal); } } return result; }(); static const std::vector kAudioDevices = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_devices_t audioDeviceHal; std::string audioDevice = toString(enumVal); if (audio_device_from_string(audioDevice.c_str(), &audioDeviceHal)) { result.push_back(audioDeviceHal); } } return result; }(); static const std::vector kAudioUsages = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_usage_t audioUsageHal; std::string audioUsage = toString(enumVal); if (audio_usage_from_string(audioUsage.c_str(), &audioUsageHal)) { result.push_back(audioUsageHal); } } return result; }(); static const std::vector kAudioSources = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_source_t audioSourceHal; std::string audioSource = toString(enumVal); if (audio_source_from_string(audioSource.c_str(), &audioSourceHal)) { result.push_back(audioSourceHal); } } return result; }(); static const std::vector kAudioContentTypes = [] { std::vector result; for (const auto enumVal : xsdc_enum_range{}) { audio_content_type_t audioContentTypeHal; std::string audioContentType = toString(enumVal); if (audio_content_type_from_string(audioContentType.c_str(), &audioContentTypeHal)) { result.push_back(audioContentTypeHal); } } return result; }(); std::vector kMixTypes = {MIX_TYPE_PLAYERS, MIX_TYPE_RECORDERS}; std::vector kMixRouteFlags = {MIX_ROUTE_FLAG_RENDER, MIX_ROUTE_FLAG_LOOP_BACK, MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER, MIX_ROUTE_FLAG_ALL}; std::vector kAudioFlagMasks = { AUDIO_FLAG_NONE, AUDIO_FLAG_AUDIBILITY_ENFORCED, AUDIO_FLAG_SECURE, AUDIO_FLAG_SCO, AUDIO_FLAG_BEACON, AUDIO_FLAG_HW_AV_SYNC, AUDIO_FLAG_HW_HOTWORD, AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY, AUDIO_FLAG_BYPASS_MUTE, AUDIO_FLAG_LOW_LATENCY, AUDIO_FLAG_DEEP_BUFFER, AUDIO_FLAG_NO_MEDIA_PROJECTION, AUDIO_FLAG_MUTE_HAPTIC, AUDIO_FLAG_NO_SYSTEM_CAPTURE, AUDIO_FLAG_CAPTURE_PRIVATE}; std::vector kAudioPolicyDeviceStates = { AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_POLICY_DEVICE_STATE_CNT, }; std::vector kSamplingRates = {8000, 16000, 44100, 48000, 88200, 96000}; template T getValueFromVector(FuzzedDataProvider *fdp, std::vector arr) { if (fdp->ConsumeBool()) { return arr[fdp->ConsumeIntegralInRange(0, arr.size() - 1)]; } else { return (T)fdp->ConsumeIntegral(); } } class AudioPolicyManagerFuzzer { public: explicit AudioPolicyManagerFuzzer(FuzzedDataProvider *fdp); virtual ~AudioPolicyManagerFuzzer() = default; virtual bool initialize(); virtual void SetUpManagerConfig(); bool getOutputForAttr(audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, audio_io_handle_t *output = nullptr, audio_port_handle_t *portId = nullptr, audio_attributes_t attr = {}); bool getInputForAttr(const audio_attributes_t &attr, audio_unique_id_t riid, audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, audio_port_handle_t *portId = nullptr); bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort); static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch *patch); audio_patch createFuzzedPatch(); void fuzzPatchCreation(); virtual void process(); protected: std::unique_ptr mClient{new AudioPolicyManagerTestClient}; std::unique_ptr mManager{new AudioPolicyTestManager(mClient.get())}; FuzzedDataProvider *mFdp; }; AudioPolicyManagerFuzzer::AudioPolicyManagerFuzzer(FuzzedDataProvider *fdp) : mFdp(fdp) {} bool AudioPolicyManagerFuzzer::initialize() { if (mFdp->remaining_bytes() < 1) { return false; } // init code SetUpManagerConfig(); if (mManager->initialize() != NO_ERROR) { return false; } if (mManager->initCheck() != NO_ERROR) { return false; } return true; } void AudioPolicyManagerFuzzer::SetUpManagerConfig() { mManager->getConfig().setDefault(); } bool AudioPolicyManagerFuzzer::getOutputForAttr( audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_output_flags_t flags, audio_io_handle_t *output, audio_port_handle_t *portId, audio_attributes_t attr) { audio_io_handle_t localOutput; if (!output) output = &localOutput; *output = AUDIO_IO_HANDLE_NONE; audio_stream_type_t stream = AUDIO_STREAM_DEFAULT; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = sampleRate; config.channel_mask = channelMask; config.format = format; audio_port_handle_t localPortId; if (!portId) portId = &localPortId; *portId = AUDIO_PORT_HANDLE_NONE; AudioPolicyInterface::output_type_t outputType; // TODO b/182392769: use attribution source util AttributionSourceState attributionSource; attributionSource.uid = 0; attributionSource.token = sp::make(); if (mManager->getOutputForAttr(&attr, output, AUDIO_SESSION_NONE, &stream, attributionSource, &config, &flags, selectedDeviceId, portId, {}, &outputType) != OK) { return false; } if (*output == AUDIO_IO_HANDLE_NONE || *portId == AUDIO_PORT_HANDLE_NONE) { return false; } return true; } bool AudioPolicyManagerFuzzer::getInputForAttr( const audio_attributes_t &attr, audio_unique_id_t riid, audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_input_flags_t flags, audio_port_handle_t *portId) { audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER; config.sample_rate = sampleRate; config.channel_mask = channelMask; config.format = format; audio_port_handle_t localPortId; if (!portId) portId = &localPortId; *portId = AUDIO_PORT_HANDLE_NONE; AudioPolicyInterface::input_type_t inputType; AttributionSourceState attributionSource; attributionSource.uid = 0; attributionSource.token = sp::make(); if (mManager->getInputForAttr(&attr, &input, riid, AUDIO_SESSION_NONE, attributionSource, &config, flags, selectedDeviceId, &inputType, portId) != OK) { return false; } if (*portId == AUDIO_PORT_HANDLE_NONE || input == AUDIO_IO_HANDLE_NONE) { return false; } return true; } bool AudioPolicyManagerFuzzer::findDevicePort(audio_port_role_t role, audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort) { uint32_t numPorts = 0; uint32_t generation1; status_t ret; ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1); if (ret != NO_ERROR) { return false; } uint32_t generation2; struct audio_port_v7 ports[numPorts]; ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2); if (ret != NO_ERROR) { return false; } for (const auto &port : ports) { if (port.role == role && port.ext.device.type == deviceType && (strncmp(port.ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) { if (foundPort) *foundPort = port; return true; } } return false; } audio_port_handle_t AudioPolicyManagerFuzzer::getDeviceIdFromPatch( const struct audio_patch *patch) { if (patch->num_sources != 0 && patch->num_sinks != 0) { if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { return patch->sinks[0].id; } else { return patch->sources[0].id; } } return AUDIO_PORT_HANDLE_NONE; } audio_patch AudioPolicyManagerFuzzer::createFuzzedPatch() { audio_patch patch{}; patch.id = mFdp->ConsumeIntegral(); patch.num_sources = mFdp->ConsumeIntegralInRange(0, AUDIO_PATCH_PORTS_MAX); for (int i = 0; i < patch.num_sources; ++i) { audio_port_config config{}; std::vector bytes = mFdp->ConsumeBytes(sizeof(config)); memcpy(reinterpret_cast(&config), &bytes[0], bytes.size()); patch.sources[i] = config; } patch.num_sinks = mFdp->ConsumeIntegralInRange(0, AUDIO_PATCH_PORTS_MAX); for (int i = 0; i < patch.num_sinks; ++i) { audio_port_config config{}; std::vector bytes = mFdp->ConsumeBytes(sizeof(config)); memcpy(reinterpret_cast(&config), &bytes[0], bytes.size()); patch.sinks[i] = config; } return patch; } void AudioPolicyManagerFuzzer::fuzzPatchCreation() { if (mFdp->remaining_bytes()) { audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE; uid_t uid = mFdp->ConsumeIntegral(); // create a fuzzed patch handle = AUDIO_PATCH_HANDLE_NONE; audio_patch patch = createFuzzedPatch(); uid = mFdp->ConsumeIntegral(); if (mManager->createAudioPatch(&patch, &handle, uid) == NO_ERROR) { mManager->releaseAudioPatch(handle, uid); } } } void AudioPolicyManagerFuzzer::process() { if (initialize()) { fuzzPatchCreation(); } } class AudioPolicyManagerFuzzerWithConfigurationFile : public AudioPolicyManagerFuzzer { public: explicit AudioPolicyManagerFuzzerWithConfigurationFile(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzer(fdp){}; protected: void SetUpManagerConfig() override; virtual std::string getConfigFile(); void traverseAndFuzzXML(xmlDocPtr pDoc, xmlNodePtr curr); std::string fuzzXML(std::string xmlPath); static inline const std::string sExecutableDir = base::GetExecutableDirectory() + "/"; static inline const std::string sDefaultConfig = sExecutableDir + "data/test_audio_policy_configuration.xml"; static inline const std::string sFuzzedConfig = sExecutableDir + "fuzzed.xml";; }; std::string AudioPolicyManagerFuzzerWithConfigurationFile::getConfigFile() { return fuzzXML(sDefaultConfig); } void AudioPolicyManagerFuzzerWithConfigurationFile::SetUpManagerConfig() { deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig()); } void AudioPolicyManagerFuzzerWithConfigurationFile::traverseAndFuzzXML(xmlDocPtr pDoc, xmlNodePtr curr) { if (curr == nullptr) { return; } xmlAttr *attribute = curr->properties; while (attribute) { if (!xmlStrcmp(attribute->name, reinterpret_cast("format"))) { const char *newFormat = audio_format_to_string(getValueFromVector(mFdp, kAudioFormats)); xmlSetProp(curr, attribute->name, reinterpret_cast(newFormat)); } if (!xmlStrcmp(attribute->name, reinterpret_cast("flags"))) { std::string newFlag = ""; uint16_t numFlags = std::max((uint16_t)1, mFdp->ConsumeIntegral()); for (uint16_t i = 0; i < numFlags; ++i) { newFlag += std::string(audio_output_flag_to_string( getValueFromVector(mFdp, kAudioOutputFlags))); if (i != (numFlags - 1)) { newFlag += std::string("|"); } } xmlSetProp(curr, attribute->name, reinterpret_cast(newFlag.c_str())); } if (!xmlStrcmp(attribute->name, reinterpret_cast("samplingRates"))) { std::string newRate = ""; uint16_t numRates = std::max((uint16_t)1, mFdp->ConsumeIntegral()); for (uint16_t i = 0; i < numRates; ++i) { newRate += std::to_string(getValueFromVector(mFdp, kSamplingRates)); if (i != (numRates - 1)) { newRate += std::string(","); } } xmlSetProp(curr, attribute->name, reinterpret_cast(newRate.c_str())); } if (!xmlStrcmp(attribute->name, reinterpret_cast("channelMasks"))) { int isOutMask = -1; char *value = reinterpret_cast(xmlNodeListGetString(pDoc, attribute->children, 1)); if (std::string(value).find(std::string("_OUT_")) != std::string::npos) { // OUT mask isOutMask = 1; } else if (std::string(value).find(std::string("_IN_")) != std::string::npos) { // IN mask isOutMask = 0; } if (isOutMask != -1) { std::string newMask = ""; uint16_t numMasks = std::max((uint16_t)1, mFdp->ConsumeIntegral()); for (uint16_t i = 0; i < numMasks; ++i) { if (isOutMask) { newMask += std::string(audio_channel_out_mask_to_string( getValueFromVector(mFdp, kAudioChannelOutMasks))); } else { newMask += std::string(audio_channel_in_mask_to_string( getValueFromVector(mFdp, kAudioChannelInMasks))); } if (i != (numMasks - 1)) { newMask += std::string(","); } } xmlSetProp(curr, attribute->name, reinterpret_cast(newMask.c_str())); } xmlFree(value); } attribute = attribute->next; } curr = curr->xmlChildrenNode; while (curr != nullptr) { traverseAndFuzzXML(pDoc, curr); curr = curr->next; } } std::string AudioPolicyManagerFuzzerWithConfigurationFile::fuzzXML(std::string xmlPath) { std::string outPath = sFuzzedConfig; // Load in the xml file from disk xmlDocPtr pDoc = xmlParseFile(xmlPath.c_str()); xmlNodePtr root = xmlDocGetRootElement(pDoc); traverseAndFuzzXML(pDoc, root); // Save the document back out to disk. xmlSaveFileEnc(outPath.c_str(), pDoc, "UTF-8"); xmlFreeDoc(pDoc); return outPath; } class AudioPolicyManagerFuzzerMsd : public AudioPolicyManagerFuzzerWithConfigurationFile { public: explicit AudioPolicyManagerFuzzerMsd(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerWithConfigurationFile(fdp) {} protected: std::string getConfigFile() override; static inline const std::string sMsdConfig = sExecutableDir + "data/test_audio_policy_msd_configuration.xml"; }; std::string AudioPolicyManagerFuzzerMsd::getConfigFile() { return fuzzXML(sMsdConfig); } using PolicyMixTuple = std::tuple; class AudioPolicyManagerFuzzerDynamicPolicy : public AudioPolicyManagerFuzzerWithConfigurationFile { public: explicit AudioPolicyManagerFuzzerDynamicPolicy(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerWithConfigurationFile(fdp){}; ~AudioPolicyManagerFuzzerDynamicPolicy() override; void process() override; protected: status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress, const audio_config_t &audioConfig, const std::vector &rules); void clearPolicyMix(); void registerPolicyMixes(); void unregisterPolicyMixes(); Vector mAudioMixes; const std::string mMixAddress = "remote_submix_media"; }; AudioPolicyManagerFuzzerDynamicPolicy::~AudioPolicyManagerFuzzerDynamicPolicy() { clearPolicyMix(); } status_t AudioPolicyManagerFuzzerDynamicPolicy::addPolicyMix( int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress, const audio_config_t &audioConfig, const std::vector &rules) { Vector myMixMatchCriteria; for (const auto &rule : rules) { myMixMatchCriteria.add( AudioMixMatchCriterion(std::get<0>(rule), std::get<1>(rule), std::get<2>(rule))); } AudioMix myAudioMix(myMixMatchCriteria, mixType, audioConfig, mixFlag, String8(mixAddress.c_str()), 0); myAudioMix.mDeviceType = deviceType; // Clear mAudioMix before add new one to make sure we don't add already existing mixes. mAudioMixes.clear(); mAudioMixes.add(myAudioMix); // As the policy mixes registration may fail at some case, // caller need to check the returned status. status_t ret = mManager->registerPolicyMixes(mAudioMixes); return ret; } void AudioPolicyManagerFuzzerDynamicPolicy::clearPolicyMix() { if (mManager != nullptr) { mManager->unregisterPolicyMixes(mAudioMixes); } mAudioMixes.clear(); } void AudioPolicyManagerFuzzerDynamicPolicy::registerPolicyMixes() { const uint32_t numPolicies = mFdp->ConsumeIntegralInRange(1, MAX_MIXES_PER_POLICY); for (int i = 0; i < numPolicies; ++i) { audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER; audioConfig.channel_mask = getValueFromVector( mFdp, mFdp->ConsumeBool() ? kAudioChannelInMasks : kAudioChannelOutMasks); audioConfig.format = getValueFromVector(mFdp, kAudioFormats); audioConfig.sample_rate = getValueFromVector(mFdp, kSamplingRates); addPolicyMix(getValueFromVector(mFdp, kMixTypes), getValueFromVector(mFdp, kMixRouteFlags), getValueFromVector(mFdp, kAudioDevices), "", audioConfig, std::vector()); } } void AudioPolicyManagerFuzzerDynamicPolicy::unregisterPolicyMixes() { mManager->unregisterPolicyMixes(mAudioMixes); } void AudioPolicyManagerFuzzerDynamicPolicy::process() { if (initialize()) { registerPolicyMixes(); fuzzPatchCreation(); unregisterPolicyMixes(); } } class AudioPolicyManagerFuzzerDPNoRemoteSubmixModule : public AudioPolicyManagerFuzzerDynamicPolicy { public: explicit AudioPolicyManagerFuzzerDPNoRemoteSubmixModule(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerDynamicPolicy(fdp){}; protected: std::string getConfigFile() override; static inline const std::string sPrimaryOnlyConfig = sExecutableDir + "data/test_audio_policy_primary_only_configuration.xml"; }; std::string AudioPolicyManagerFuzzerDPNoRemoteSubmixModule::getConfigFile() { return fuzzXML(sPrimaryOnlyConfig); } class AudioPolicyManagerFuzzerDPPlaybackReRouting : public AudioPolicyManagerFuzzerDynamicPolicy { public: explicit AudioPolicyManagerFuzzerDPPlaybackReRouting(FuzzedDataProvider *fdp); ~AudioPolicyManagerFuzzerDPPlaybackReRouting() override; void process() override; protected: bool initialize() override; void playBackReRouting(); std::unique_ptr mTracker; std::vector mUsageRules = { {AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}, {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}}; struct audio_port_v7 mInjectionPort; audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE; audio_config_t mAudioConfig; }; AudioPolicyManagerFuzzerDPPlaybackReRouting::AudioPolicyManagerFuzzerDPPlaybackReRouting( FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerDynamicPolicy(fdp) { const uint32_t numRules = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numRules; ++i) { PolicyMixTuple rule = {getValueFromVector(mFdp, kAudioUsages), getValueFromVector(mFdp, kAudioSources), RULE_MATCH_ATTRIBUTE_USAGE}; mUsageRules.push_back(rule); } } AudioPolicyManagerFuzzerDPPlaybackReRouting::~AudioPolicyManagerFuzzerDPPlaybackReRouting() { mManager->stopInput(mPortId); } bool AudioPolicyManagerFuzzerDPPlaybackReRouting::initialize() { if (!AudioPolicyManagerFuzzerDynamicPolicy::initialize()) { return false; } mTracker.reset(new RecordingActivityTracker()); mAudioConfig = AUDIO_CONFIG_INITIALIZER; mAudioConfig.channel_mask = getValueFromVector(mFdp, kAudioChannelOutMasks); mAudioConfig.format = getValueFromVector(mFdp, kAudioFormats); mAudioConfig.sample_rate = getValueFromVector(mFdp, kSamplingRates); status_t ret = addPolicyMix(getValueFromVector(mFdp, kMixTypes), getValueFromVector(mFdp, kMixRouteFlags), getValueFromVector(mFdp, kAudioDevices), mMixAddress, mAudioConfig, mUsageRules); if (ret != NO_ERROR) { return false; } struct audio_port_v7 extractionPort; findDevicePort(AUDIO_PORT_ROLE_SOURCE, getValueFromVector(mFdp, kAudioDevices), mMixAddress, &extractionPort); audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_source_t source = getValueFromVector(mFdp, kAudioSources); audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""}; std::string tags = "addr=" + mMixAddress; strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, mAudioConfig.format, mAudioConfig.channel_mask, mAudioConfig.sample_rate, AUDIO_INPUT_FLAG_NONE, &mPortId); ret = mManager->startInput(mPortId); if (ret != NO_ERROR) { return false; } if (!findDevicePort(AUDIO_PORT_ROLE_SINK, getValueFromVector(mFdp, kAudioDevices), mMixAddress, &mInjectionPort)) { return false; } return true; } void AudioPolicyManagerFuzzerDPPlaybackReRouting::playBackReRouting() { const uint32_t numTestCases = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numTestCases; ++i) { audio_attributes_t attr; attr.content_type = getValueFromVector(mFdp, kAudioContentTypes); attr.usage = getValueFromVector(mFdp, kAudioUsages); attr.source = getValueFromVector(mFdp, kAudioSources); attr.flags = getValueFromVector(mFdp, kAudioFlagMasks); std::string tags(mFdp->ConsumeBool() ? "" : "addr=remote_submix_media"); strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); audio_port_handle_t playbackRoutedPortId = AUDIO_PORT_HANDLE_NONE; getOutputForAttr(&playbackRoutedPortId, mAudioConfig.format, mAudioConfig.channel_mask, mAudioConfig.sample_rate, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, nullptr /*portId*/, attr); } } void AudioPolicyManagerFuzzerDPPlaybackReRouting::process() { if (initialize()) { playBackReRouting(); registerPolicyMixes(); fuzzPatchCreation(); unregisterPolicyMixes(); } } class AudioPolicyManagerFuzzerDPMixRecordInjection : public AudioPolicyManagerFuzzerDynamicPolicy { public: explicit AudioPolicyManagerFuzzerDPMixRecordInjection(FuzzedDataProvider *fdp); ~AudioPolicyManagerFuzzerDPMixRecordInjection() override; void process() override; protected: bool initialize() override; void recordingInjection(); std::unique_ptr mTracker; std::vector mSourceRules = { {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_CAMCORDER, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}, {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_MIC, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}, {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}}; struct audio_port_v7 mExtractionPort; audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE; audio_config_t mAudioConfig; }; AudioPolicyManagerFuzzerDPMixRecordInjection::AudioPolicyManagerFuzzerDPMixRecordInjection( FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerDynamicPolicy(fdp) { const uint32_t numRules = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numRules; ++i) { PolicyMixTuple rule = {getValueFromVector(mFdp, kAudioUsages), getValueFromVector(mFdp, kAudioSources), RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}; mSourceRules.push_back(rule); } } AudioPolicyManagerFuzzerDPMixRecordInjection::~AudioPolicyManagerFuzzerDPMixRecordInjection() { mManager->stopOutput(mPortId); } bool AudioPolicyManagerFuzzerDPMixRecordInjection::initialize() { if (!AudioPolicyManagerFuzzerDynamicPolicy::initialize()) { return false; } mTracker.reset(new RecordingActivityTracker()); mAudioConfig = AUDIO_CONFIG_INITIALIZER; mAudioConfig.channel_mask = getValueFromVector(mFdp, kAudioChannelInMasks); mAudioConfig.format = getValueFromVector(mFdp, kAudioFormats); mAudioConfig.sample_rate = getValueFromVector(mFdp, kSamplingRates); status_t ret = addPolicyMix(getValueFromVector(mFdp, kMixTypes), getValueFromVector(mFdp, kMixRouteFlags), getValueFromVector(mFdp, kAudioDevices), mMixAddress, mAudioConfig, mSourceRules); if (ret != NO_ERROR) { return false; } struct audio_port_v7 injectionPort; findDevicePort(AUDIO_PORT_ROLE_SINK, getValueFromVector(mFdp, kAudioDevices), mMixAddress, &injectionPort); audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_usage_t usage = getValueFromVector(mFdp, kAudioUsages); audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}; std::string tags = std::string("addr=") + mMixAddress; strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); getOutputForAttr(&selectedDeviceId, mAudioConfig.format, mAudioConfig.channel_mask, mAudioConfig.sample_rate /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, &mPortId, attr); ret = mManager->startOutput(mPortId); if (ret != NO_ERROR) { return false; } getDeviceIdFromPatch(mClient->getLastAddedPatch()); if (!findDevicePort(AUDIO_PORT_ROLE_SOURCE, getValueFromVector(mFdp, kAudioDevices), mMixAddress, &mExtractionPort)) { return false; } return true; } void AudioPolicyManagerFuzzerDPMixRecordInjection::recordingInjection() { const uint32_t numTestCases = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numTestCases; ++i) { audio_attributes_t attr; attr.content_type = getValueFromVector(mFdp, kAudioContentTypes); attr.usage = getValueFromVector(mFdp, kAudioUsages); attr.source = getValueFromVector(mFdp, kAudioSources); attr.flags = getValueFromVector(mFdp, kAudioFlagMasks); std::string tags(mFdp->ConsumeBool() ? "" : "addr=remote_submix_media"); strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE; audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE; getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, mAudioConfig.format, mAudioConfig.channel_mask, mAudioConfig.sample_rate, AUDIO_INPUT_FLAG_NONE, &portId); } } void AudioPolicyManagerFuzzerDPMixRecordInjection::process() { if (initialize()) { recordingInjection(); registerPolicyMixes(); fuzzPatchCreation(); unregisterPolicyMixes(); } } using DeviceConnectionTestParams = std::tuple; class AudioPolicyManagerFuzzerDeviceConnection : public AudioPolicyManagerFuzzerWithConfigurationFile { public: explicit AudioPolicyManagerFuzzerDeviceConnection(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerWithConfigurationFile(fdp){}; void process() override; protected: void setDeviceConnectionState(); void explicitlyRoutingAfterConnection(); }; void AudioPolicyManagerFuzzerDeviceConnection::setDeviceConnectionState() { const uint32_t numTestCases = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numTestCases; ++i) { const audio_devices_t type = getValueFromVector(mFdp, kAudioDevices); const std::string name = mFdp->ConsumeRandomLengthString(); const std::string address = mFdp->ConsumeRandomLengthString(); mManager->setDeviceConnectionState( type, getValueFromVector(mFdp, kAudioPolicyDeviceStates), address.c_str(), name.c_str(), getValueFromVector(mFdp, kAudioFormats)); } } void AudioPolicyManagerFuzzerDeviceConnection::explicitlyRoutingAfterConnection() { const uint32_t numTestCases = mFdp->ConsumeIntegralInRange(1, 10); for (int i = 0; i < numTestCases; ++i) { const audio_devices_t type = getValueFromVector(mFdp, kAudioDevices); const std::string name = mFdp->ConsumeRandomLengthString(); const std::string address = mFdp->ConsumeRandomLengthString(); mManager->setDeviceConnectionState( type, getValueFromVector(mFdp, kAudioPolicyDeviceStates), address.c_str(), name.c_str(), getValueFromVector(mFdp, kAudioFormats)); audio_port_v7 devicePort; const audio_port_role_t role = audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE; findDevicePort(role, type, address, &devicePort); audio_port_handle_t routedPortId = devicePort.id; // Try start input or output according to the device type if (audio_is_output_devices(type)) { getOutputForAttr(&routedPortId, getValueFromVector(mFdp, kAudioFormats), getValueFromVector(mFdp, kAudioChannelOutMasks), getValueFromVector(mFdp, kSamplingRates), AUDIO_OUTPUT_FLAG_NONE); } else if (audio_is_input_device(type)) { RecordingActivityTracker tracker; getInputForAttr({}, tracker.getRiid(), &routedPortId, getValueFromVector(mFdp, kAudioFormats), getValueFromVector(mFdp, kAudioChannelInMasks), getValueFromVector(mFdp, kSamplingRates), AUDIO_INPUT_FLAG_NONE); } } } void AudioPolicyManagerFuzzerDeviceConnection::process() { if (initialize()) { setDeviceConnectionState(); explicitlyRoutingAfterConnection(); fuzzPatchCreation(); } } class AudioPolicyManagerTVFuzzer : public AudioPolicyManagerFuzzerWithConfigurationFile { public: explicit AudioPolicyManagerTVFuzzer(FuzzedDataProvider *fdp) : AudioPolicyManagerFuzzerWithConfigurationFile(fdp){}; void process() override; protected: std::string getConfigFile(); void testHDMIPortSelection(audio_output_flags_t flags); static inline const std::string sTvConfig = AudioPolicyManagerTVFuzzer::sExecutableDir + "data/test_tv_apm_configuration.xml"; }; std::string AudioPolicyManagerTVFuzzer::getConfigFile() { return fuzzXML(sTvConfig); } void AudioPolicyManagerTVFuzzer::testHDMIPortSelection(audio_output_flags_t flags) { audio_devices_t audioDevice = getValueFromVector(mFdp, kAudioDevices); audio_format_t audioFormat = getValueFromVector(mFdp, kAudioFormats); status_t ret = mManager->setDeviceConnectionState( audioDevice, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "" /*address*/, "" /*name*/, audioFormat); if (ret != NO_ERROR) { return; } audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t output; audio_port_handle_t portId; getOutputForAttr(&selectedDeviceId, getValueFromVector(mFdp, kAudioFormats), getValueFromVector(mFdp, kAudioChannelOutMasks), getValueFromVector(mFdp, kSamplingRates), flags, &output, &portId); sp outDesc = mManager->getOutputs().valueFor(output); if (outDesc.get() == nullptr) { return; } audio_port_v7 port = {}; outDesc->toAudioPort(&port); mManager->releaseOutput(portId); mManager->setDeviceConnectionState(audioDevice, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "" /*address*/, "" /*name*/, audioFormat); } void AudioPolicyManagerTVFuzzer::process() { if (initialize()) { testHDMIPortSelection(getValueFromVector(mFdp, kAudioOutputFlags)); fuzzPatchCreation(); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 1) { return 0; } FuzzedDataProvider fdp = FuzzedDataProvider(data, size); while (fdp.remaining_bytes() > 0) { AudioPolicyManagerFuzzer audioPolicyManagerFuzzer(&fdp); audioPolicyManagerFuzzer.process(); AudioPolicyManagerFuzzerMsd audioPolicyManagerFuzzerMsd(&fdp); audioPolicyManagerFuzzerMsd.process(); AudioPolicyManagerFuzzerWithConfigurationFile audioPolicyManagerFuzzerWithConfigurationFile( &fdp); audioPolicyManagerFuzzerWithConfigurationFile.process(); AudioPolicyManagerFuzzerDynamicPolicy audioPolicyManagerFuzzerDynamicPolicy(&fdp); audioPolicyManagerFuzzerDynamicPolicy.process(); AudioPolicyManagerFuzzerDPNoRemoteSubmixModule audioPolicyManagerFuzzerDPNoRemoteSubmixModule(&fdp); audioPolicyManagerFuzzerDPNoRemoteSubmixModule.process(); AudioPolicyManagerFuzzerDPPlaybackReRouting audioPolicyManagerFuzzerDPPlaybackReRouting( &fdp); audioPolicyManagerFuzzerDPPlaybackReRouting.process(); AudioPolicyManagerFuzzerDPMixRecordInjection audioPolicyManagerFuzzerDPMixRecordInjection( &fdp); audioPolicyManagerFuzzerDPMixRecordInjection.process(); AudioPolicyManagerFuzzerDeviceConnection audioPolicyManagerFuzzerDeviceConnection(&fdp); audioPolicyManagerFuzzerDeviceConnection.process(); AudioPolicyManagerTVFuzzer audioPolicyManagerTVFuzzer(&fdp); audioPolicyManagerTVFuzzer.process(); } return 0; }