1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include <fuzzer/FuzzedDataProvider.h>
19 
20 #include "audio_hal_interface/le_audio_software.h"
21 #include "osi/include/properties.h"
22 
23 using ::bluetooth::audio::le_audio::LeAudioClientInterface;
24 
25 constexpr int32_t kRandomStringLength = 256;
26 
27 constexpr uint8_t kBitsPerSample[] = {16, 24, 32};
28 
29 constexpr uint8_t kChannelCount[] = {1, 2};
30 
31 constexpr uint32_t kSampleRates[] = {16000, 24000, 44100, 48000, 88200, 96000};
32 
33 extern "C" {
android_get_exported_namespace(const char *)34 struct android_namespace_t* android_get_exported_namespace(const char*) {
35   return nullptr;
36 }
37 }
38 
onResume(bool)39 bool onResume(bool) { return true; }
40 
onSuspend(void)41 bool onSuspend(void) { return true; }
42 
onMetadataUpdate(const source_metadata_v7_t &,bluetooth::le_audio::DsaMode)43 bool onMetadataUpdate(const source_metadata_v7_t&,
44                       bluetooth::le_audio::DsaMode) {
45   return true;
46 }
47 
onSinkMetadataUpdate(const sink_metadata_v7_t &)48 bool onSinkMetadataUpdate(const sink_metadata_v7_t&) { return true; }
49 
source_init_delayed(void)50 static void source_init_delayed(void) {}
51 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)52 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
53   FuzzedDataProvider fdp(data, size);
54   osi_property_set("persist.bluetooth.a2dp_offload.disabled",
55                    fdp.PickValueInArray({"true", "false"}));
56   std::string name = fdp.ConsumeRandomLengthString(kRandomStringLength);
57   bluetooth::common::MessageLoopThread messageLoopThread(name);
58   messageLoopThread.StartUp();
59   messageLoopThread.DoInThread(FROM_HERE, base::BindOnce(&source_init_delayed));
60 
61   LeAudioClientInterface* interface = LeAudioClientInterface::Get();
62 
63   bluetooth::audio::le_audio::StreamCallbacks streamCb = {
64       onResume, onSuspend, onMetadataUpdate, onSinkMetadataUpdate};
65 
66   if (!interface->IsSourceAcquired()) {
67     LeAudioClientInterface::Source* source =
68         interface->GetSource(streamCb, &messageLoopThread);
69     if (source != nullptr) {
70       uint16_t delay = fdp.ConsumeIntegral<uint16_t>();
71       source->SetRemoteDelay(delay);
72       LeAudioClientInterface::PcmParameters params;
73       params.data_interval_us = fdp.ConsumeIntegralInRange<uint32_t>(
74           1000, std::numeric_limits<uint32_t>::max());
75       params.sample_rate = fdp.PickValueInArray(kSampleRates);
76       params.bits_per_sample = fdp.PickValueInArray(kBitsPerSample);
77       params.channels_count = fdp.PickValueInArray(kChannelCount);
78       source->SetPcmParameters(params);
79       source->StartSession();
80       source->StopSession();
81       source->Cleanup();
82     }
83     interface->ReleaseSource(source);
84   }
85 
86   if (!interface->IsUnicastSinkAcquired()) {
87     LeAudioClientInterface::Sink* sink =
88         interface->GetSink(streamCb, &messageLoopThread, false);
89     if (sink != nullptr) {
90       uint16_t delay = fdp.ConsumeIntegral<uint16_t>();
91       sink->SetRemoteDelay(delay);
92       LeAudioClientInterface::PcmParameters params;
93       params.data_interval_us = fdp.ConsumeIntegralInRange<uint32_t>(
94           1000, std::numeric_limits<uint32_t>::max());
95       params.sample_rate = fdp.PickValueInArray(kSampleRates);
96       params.bits_per_sample = fdp.PickValueInArray(kBitsPerSample);
97       params.channels_count = fdp.PickValueInArray(kChannelCount);
98       sink->SetPcmParameters(params);
99       sink->StartSession();
100       sink->StopSession();
101       sink->Cleanup();
102     }
103     interface->ReleaseSink(sink);
104   }
105 
106   messageLoopThread.ShutDown();
107   return 0;
108 }
109