blob: 4bc661c52a62a980c06646c3dded43f5bab3394b [file] [log] [blame]
Mufaddal Chakera3fde8702020-11-18 14:08:12 +05301/******************************************************************************
2 *
3 * Copyright (C) 2020 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20#include <fuzzer/FuzzedDataProvider.h>
21#include <stdio.h>
22
23#include <AAudioService.h>
24#include <aaudio/AAudio.h>
25#include "aaudio/BnAAudioClient.h"
Svet Ganov33761132021-05-13 22:51:08 +000026#include <android/content/AttributionSourceState.h>
Mufaddal Chakera3fde8702020-11-18 14:08:12 +053027
28#define UNUSED_PARAM __attribute__((unused))
29
30using namespace android;
31using namespace aaudio;
32
33aaudio_format_t kAAudioFormats[] = {
34 AAUDIO_FORMAT_UNSPECIFIED,
35 AAUDIO_FORMAT_PCM_I16,
36 AAUDIO_FORMAT_PCM_FLOAT,
37};
38
39aaudio_usage_t kAAudioUsages[] = {
40 AAUDIO_USAGE_MEDIA,
41 AAUDIO_USAGE_VOICE_COMMUNICATION,
42 AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
43 AAUDIO_USAGE_ALARM,
44 AAUDIO_USAGE_NOTIFICATION,
45 AAUDIO_USAGE_NOTIFICATION_RINGTONE,
46 AAUDIO_USAGE_NOTIFICATION_EVENT,
47 AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
48 AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
49 AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
50 AAUDIO_USAGE_GAME,
51 AAUDIO_USAGE_ASSISTANT,
52 AAUDIO_SYSTEM_USAGE_EMERGENCY,
53 AAUDIO_SYSTEM_USAGE_SAFETY,
54 AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
55 AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
56};
57
58aaudio_content_type_t kAAudioContentTypes[] = {
59 AAUDIO_CONTENT_TYPE_SPEECH,
60 AAUDIO_CONTENT_TYPE_MUSIC,
61 AAUDIO_CONTENT_TYPE_MOVIE,
62 AAUDIO_CONTENT_TYPE_SONIFICATION,
63};
64
65aaudio_input_preset_t kAAudioInputPresets[] = {
66 AAUDIO_INPUT_PRESET_GENERIC, AAUDIO_INPUT_PRESET_CAMCORDER,
67 AAUDIO_INPUT_PRESET_VOICE_RECOGNITION, AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
68 AAUDIO_INPUT_PRESET_UNPROCESSED, AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
69};
70
71const size_t kNumAAudioFormats = std::size(kAAudioFormats);
72const size_t kNumAAudioUsages = std::size(kAAudioUsages);
73const size_t kNumAAudioContentTypes = std::size(kAAudioContentTypes);
74const size_t kNumAAudioInputPresets = std::size(kAAudioInputPresets);
75
76class FuzzAAudioClient : public virtual RefBase, public AAudioServiceInterface {
77 public:
78 FuzzAAudioClient(sp<AAudioService> service);
79
80 virtual ~FuzzAAudioClient();
81
82 AAudioServiceInterface *getAAudioService();
83
84 void dropAAudioService();
85
86 void registerClient(const sp<IAAudioClient> &client UNUSED_PARAM) override {}
87
88 aaudio_handle_t openStream(const AAudioStreamRequest &request,
89 AAudioStreamConfiguration &configurationOutput) override;
90
91 aaudio_result_t closeStream(aaudio_handle_t streamHandle) override;
92
93 aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
94 AudioEndpointParcelable &parcelable) override;
95
96 aaudio_result_t startStream(aaudio_handle_t streamHandle) override;
97
98 aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override;
99
100 aaudio_result_t stopStream(aaudio_handle_t streamHandle) override;
101
102 aaudio_result_t flushStream(aaudio_handle_t streamHandle) override;
103
104 aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId,
105 int64_t periodNanoseconds) override;
106
107 aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
108 pid_t clientThreadId) override;
109
110 aaudio_result_t startClient(aaudio_handle_t streamHandle UNUSED_PARAM,
111 const AudioClient &client UNUSED_PARAM,
112 const audio_attributes_t *attr UNUSED_PARAM,
113 audio_port_handle_t *clientHandle UNUSED_PARAM) override {
114 return AAUDIO_ERROR_UNAVAILABLE;
115 }
116
117 aaudio_result_t stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,
118 audio_port_handle_t clientHandle UNUSED_PARAM) override {
119 return AAUDIO_ERROR_UNAVAILABLE;
120 }
121
122 void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {}
123
124 int getDeathCount() { return mDeathCount; }
125
126 void incDeathCount() { ++mDeathCount; }
127
128 class AAudioClient : public IBinder::DeathRecipient, public BnAAudioClient {
129 public:
130 AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient) : mBinderClient(fuzzAAudioClient) {}
131
132 virtual void binderDied(const wp<IBinder> &who UNUSED_PARAM) {
133 sp<FuzzAAudioClient> client = mBinderClient.promote();
134 if (client.get()) {
135 client->dropAAudioService();
136 client->incDeathCount();
137 }
138 }
139
140 android::binder::Status onStreamChange(int32_t handle, int32_t opcode, int32_t value) {
141 static_assert(std::is_same_v<aaudio_handle_t, int32_t>);
142 android::sp<FuzzAAudioClient> client = mBinderClient.promote();
143 if (client.get() != nullptr) {
144 client->onStreamChange(handle, opcode, value);
145 }
146 return android::binder::Status::ok();
147 }
148
149 private:
150 wp<FuzzAAudioClient> mBinderClient;
151 };
152
153 private:
154 sp<AAudioService> mAAudioService;
155 sp<AAudioClient> mAAudioClient;
156 AAudioServiceInterface *mAAudioServiceInterface;
157 int mDeathCount;
158};
159
160FuzzAAudioClient::FuzzAAudioClient(sp<AAudioService> service) : AAudioServiceInterface() {
161 mAAudioService = service;
162 mAAudioServiceInterface = &service->asAAudioServiceInterface();
163 mAAudioClient = new AAudioClient(this);
164 mDeathCount = 0;
165 if (mAAudioClient.get() && mAAudioService.get()) {
166 mAAudioService->linkToDeath(mAAudioClient);
167 mAAudioService->registerClient(mAAudioClient);
168 }
169}
170
171FuzzAAudioClient::~FuzzAAudioClient() { dropAAudioService(); }
172
173AAudioServiceInterface *FuzzAAudioClient::getAAudioService() {
174 if (!mAAudioServiceInterface && mAAudioService.get()) {
175 mAAudioServiceInterface = &mAAudioService->asAAudioServiceInterface();
176 }
177 return mAAudioServiceInterface;
178}
179
180void FuzzAAudioClient::dropAAudioService() {
181 mAAudioService.clear();
182}
183
184aaudio_handle_t FuzzAAudioClient::openStream(const AAudioStreamRequest &request,
185 AAudioStreamConfiguration &configurationOutput) {
186 aaudio_handle_t stream;
187 for (int i = 0; i < 2; ++i) {
188 AAudioServiceInterface *service = getAAudioService();
189 if (!service) {
190 return AAUDIO_ERROR_NO_SERVICE;
191 }
192
193 stream = service->openStream(request, configurationOutput);
194
195 if (stream == AAUDIO_ERROR_NO_SERVICE) {
196 dropAAudioService();
197 } else {
198 break;
199 }
200 }
201 return stream;
202}
203
204aaudio_result_t FuzzAAudioClient::closeStream(aaudio_handle_t streamHandle) {
205 AAudioServiceInterface *service = getAAudioService();
206 if (!service) {
207 return AAUDIO_ERROR_NO_SERVICE;
208 }
209 return service->closeStream(streamHandle);
210}
211
212aaudio_result_t FuzzAAudioClient::getStreamDescription(aaudio_handle_t streamHandle,
213 AudioEndpointParcelable &parcelable) {
214 AAudioServiceInterface *service = getAAudioService();
215 if (!service) {
216 return AAUDIO_ERROR_NO_SERVICE;
217 }
218 return service->getStreamDescription(streamHandle, parcelable);
219}
220
221aaudio_result_t FuzzAAudioClient::startStream(aaudio_handle_t streamHandle) {
222 AAudioServiceInterface *service = getAAudioService();
223 if (!service) {
224 return AAUDIO_ERROR_NO_SERVICE;
225 }
226 return service->startStream(streamHandle);
227}
228
229aaudio_result_t FuzzAAudioClient::pauseStream(aaudio_handle_t streamHandle) {
230 AAudioServiceInterface *service = getAAudioService();
231 if (!service) {
232 return AAUDIO_ERROR_NO_SERVICE;
233 }
234 return service->pauseStream(streamHandle);
235}
236
237aaudio_result_t FuzzAAudioClient::stopStream(aaudio_handle_t streamHandle) {
238 AAudioServiceInterface *service = getAAudioService();
239 if (!service) {
240 return AAUDIO_ERROR_NO_SERVICE;
241 }
242 return service->stopStream(streamHandle);
243}
244
245aaudio_result_t FuzzAAudioClient::flushStream(aaudio_handle_t streamHandle) {
246 AAudioServiceInterface *service = getAAudioService();
247 if (!service) {
248 return AAUDIO_ERROR_NO_SERVICE;
249 }
250 return service->flushStream(streamHandle);
251}
252
253aaudio_result_t FuzzAAudioClient::registerAudioThread(aaudio_handle_t streamHandle,
254 pid_t clientThreadId,
255 int64_t periodNanoseconds) {
256 AAudioServiceInterface *service = getAAudioService();
257 if (!service) {
258 return AAUDIO_ERROR_NO_SERVICE;
259 }
260 return service->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds);
261}
262
263aaudio_result_t FuzzAAudioClient::unregisterAudioThread(aaudio_handle_t streamHandle,
264 pid_t clientThreadId) {
265 AAudioServiceInterface *service = getAAudioService();
266 if (!service) {
267 return AAUDIO_ERROR_NO_SERVICE;
268 }
269 return service->unregisterAudioThread(streamHandle, clientThreadId);
270}
271
272class OboeserviceFuzzer {
273 public:
274 OboeserviceFuzzer();
275 ~OboeserviceFuzzer() = default;
276 void process(const uint8_t *data, size_t size);
277
278 private:
279 sp<FuzzAAudioClient> mClient;
280};
281
282OboeserviceFuzzer::OboeserviceFuzzer() {
283 sp<AAudioService> service = new AAudioService();
284 mClient = new FuzzAAudioClient(service);
285}
286
287void OboeserviceFuzzer::process(const uint8_t *data, size_t size) {
288 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
289 AAudioStreamRequest request;
290 AAudioStreamConfiguration configurationOutput;
291
292 // Initialize stream request
293 request.getConfiguration().setFormat((audio_format_t)(
294 fdp.ConsumeBool()
295 ? fdp.ConsumeIntegral<int32_t>()
296 : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
297
Svet Ganov33761132021-05-13 22:51:08 +0000298 // TODO b/182392769: use attribution source util
299 android::content::AttributionSourceState attributionSource;
300 attributionSource.uid = getuid();
301 attributionSource.pid = getpid();
302 attributionSource.token = sp<BBinder>::make();
303 request.setAttributionSource(attributionSource);
Mufaddal Chakera3fde8702020-11-18 14:08:12 +0530304 request.setInService(fdp.ConsumeBool());
305
306 request.getConfiguration().setDeviceId(fdp.ConsumeIntegral<int32_t>());
307 request.getConfiguration().setSampleRate(fdp.ConsumeIntegral<int32_t>());
308 request.getConfiguration().setSamplesPerFrame(fdp.ConsumeIntegral<int32_t>());
309 request.getConfiguration().setDirection(
310 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
311 : (fdp.ConsumeBool() ? AAUDIO_DIRECTION_OUTPUT : AAUDIO_DIRECTION_INPUT));
312 request.getConfiguration().setSharingMode(
313 fdp.ConsumeBool()
314 ? fdp.ConsumeIntegral<int32_t>()
315 : (fdp.ConsumeBool() ? AAUDIO_SHARING_MODE_EXCLUSIVE : AAUDIO_SHARING_MODE_SHARED));
316
317 request.getConfiguration().setUsage(
318 fdp.ConsumeBool()
319 ? fdp.ConsumeIntegral<int32_t>()
320 : kAAudioUsages[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioUsages - 1)]);
321 request.getConfiguration().setContentType(
322 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
323 : kAAudioContentTypes[fdp.ConsumeIntegralInRange<int32_t>(
324 0, kNumAAudioContentTypes - 1)]);
325 request.getConfiguration().setInputPreset(
326 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
327 : kAAudioInputPresets[fdp.ConsumeIntegralInRange<int32_t>(
328 0, kNumAAudioInputPresets - 1)]);
329 request.getConfiguration().setPrivacySensitive(fdp.ConsumeBool());
330
331 request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
332
333 aaudio_handle_t stream = mClient->openStream(request, configurationOutput);
334 if (stream < 0) {
335 // invalid request, stream not opened.
336 return;
337 }
338 while (fdp.remaining_bytes()) {
339 AudioEndpointParcelable audioEndpointParcelable;
340 int action = fdp.ConsumeIntegralInRange<int32_t>(0, 4);
341 switch (action) {
342 case 0:
343 mClient->getStreamDescription(stream, audioEndpointParcelable);
344 break;
345 case 1:
346 mClient->startStream(stream);
347 break;
348 case 2:
349 mClient->pauseStream(stream);
350 break;
351 case 3:
352 mClient->stopStream(stream);
353 break;
354 case 4:
355 mClient->flushStream(stream);
356 break;
357 }
358 }
359 mClient->closeStream(stream);
360 assert(mClient->getDeathCount() == 0);
361}
362
363extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
364 if (size < 1) {
365 return 0;
366 }
367 OboeserviceFuzzer oboeserviceFuzzer;
368 oboeserviceFuzzer.process(data, size);
369 return 0;
370}