blob: 163eae8e262da95e58173ac7bff3133cde54add1 [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"
26
27#define UNUSED_PARAM __attribute__((unused))
28
29using namespace android;
30using namespace aaudio;
31
32aaudio_format_t kAAudioFormats[] = {
33 AAUDIO_FORMAT_UNSPECIFIED,
34 AAUDIO_FORMAT_PCM_I16,
35 AAUDIO_FORMAT_PCM_FLOAT,
36};
37
38aaudio_usage_t kAAudioUsages[] = {
39 AAUDIO_USAGE_MEDIA,
40 AAUDIO_USAGE_VOICE_COMMUNICATION,
41 AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
42 AAUDIO_USAGE_ALARM,
43 AAUDIO_USAGE_NOTIFICATION,
44 AAUDIO_USAGE_NOTIFICATION_RINGTONE,
45 AAUDIO_USAGE_NOTIFICATION_EVENT,
46 AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
47 AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
48 AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
49 AAUDIO_USAGE_GAME,
50 AAUDIO_USAGE_ASSISTANT,
51 AAUDIO_SYSTEM_USAGE_EMERGENCY,
52 AAUDIO_SYSTEM_USAGE_SAFETY,
53 AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
54 AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
55};
56
57aaudio_content_type_t kAAudioContentTypes[] = {
58 AAUDIO_CONTENT_TYPE_SPEECH,
59 AAUDIO_CONTENT_TYPE_MUSIC,
60 AAUDIO_CONTENT_TYPE_MOVIE,
61 AAUDIO_CONTENT_TYPE_SONIFICATION,
62};
63
64aaudio_input_preset_t kAAudioInputPresets[] = {
65 AAUDIO_INPUT_PRESET_GENERIC, AAUDIO_INPUT_PRESET_CAMCORDER,
66 AAUDIO_INPUT_PRESET_VOICE_RECOGNITION, AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
67 AAUDIO_INPUT_PRESET_UNPROCESSED, AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
68};
69
70const size_t kNumAAudioFormats = std::size(kAAudioFormats);
71const size_t kNumAAudioUsages = std::size(kAAudioUsages);
72const size_t kNumAAudioContentTypes = std::size(kAAudioContentTypes);
73const size_t kNumAAudioInputPresets = std::size(kAAudioInputPresets);
74
75class FuzzAAudioClient : public virtual RefBase, public AAudioServiceInterface {
76 public:
77 FuzzAAudioClient(sp<AAudioService> service);
78
79 virtual ~FuzzAAudioClient();
80
81 AAudioServiceInterface *getAAudioService();
82
83 void dropAAudioService();
84
85 void registerClient(const sp<IAAudioClient> &client UNUSED_PARAM) override {}
86
87 aaudio_handle_t openStream(const AAudioStreamRequest &request,
88 AAudioStreamConfiguration &configurationOutput) override;
89
90 aaudio_result_t closeStream(aaudio_handle_t streamHandle) override;
91
92 aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
93 AudioEndpointParcelable &parcelable) override;
94
95 aaudio_result_t startStream(aaudio_handle_t streamHandle) override;
96
97 aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override;
98
99 aaudio_result_t stopStream(aaudio_handle_t streamHandle) override;
100
101 aaudio_result_t flushStream(aaudio_handle_t streamHandle) override;
102
103 aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId,
104 int64_t periodNanoseconds) override;
105
106 aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
107 pid_t clientThreadId) override;
108
109 aaudio_result_t startClient(aaudio_handle_t streamHandle UNUSED_PARAM,
110 const AudioClient &client UNUSED_PARAM,
111 const audio_attributes_t *attr UNUSED_PARAM,
112 audio_port_handle_t *clientHandle UNUSED_PARAM) override {
113 return AAUDIO_ERROR_UNAVAILABLE;
114 }
115
116 aaudio_result_t stopClient(aaudio_handle_t streamHandle UNUSED_PARAM,
117 audio_port_handle_t clientHandle UNUSED_PARAM) override {
118 return AAUDIO_ERROR_UNAVAILABLE;
119 }
120
121 void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {}
122
123 int getDeathCount() { return mDeathCount; }
124
125 void incDeathCount() { ++mDeathCount; }
126
127 class AAudioClient : public IBinder::DeathRecipient, public BnAAudioClient {
128 public:
129 AAudioClient(wp<FuzzAAudioClient> fuzzAAudioClient) : mBinderClient(fuzzAAudioClient) {}
130
131 virtual void binderDied(const wp<IBinder> &who UNUSED_PARAM) {
132 sp<FuzzAAudioClient> client = mBinderClient.promote();
133 if (client.get()) {
134 client->dropAAudioService();
135 client->incDeathCount();
136 }
137 }
138
139 android::binder::Status onStreamChange(int32_t handle, int32_t opcode, int32_t value) {
140 static_assert(std::is_same_v<aaudio_handle_t, int32_t>);
141 android::sp<FuzzAAudioClient> client = mBinderClient.promote();
142 if (client.get() != nullptr) {
143 client->onStreamChange(handle, opcode, value);
144 }
145 return android::binder::Status::ok();
146 }
147
148 private:
149 wp<FuzzAAudioClient> mBinderClient;
150 };
151
152 private:
153 sp<AAudioService> mAAudioService;
154 sp<AAudioClient> mAAudioClient;
155 AAudioServiceInterface *mAAudioServiceInterface;
156 int mDeathCount;
157};
158
159FuzzAAudioClient::FuzzAAudioClient(sp<AAudioService> service) : AAudioServiceInterface() {
160 mAAudioService = service;
161 mAAudioServiceInterface = &service->asAAudioServiceInterface();
162 mAAudioClient = new AAudioClient(this);
163 mDeathCount = 0;
164 if (mAAudioClient.get() && mAAudioService.get()) {
165 mAAudioService->linkToDeath(mAAudioClient);
166 mAAudioService->registerClient(mAAudioClient);
167 }
168}
169
170FuzzAAudioClient::~FuzzAAudioClient() { dropAAudioService(); }
171
172AAudioServiceInterface *FuzzAAudioClient::getAAudioService() {
173 if (!mAAudioServiceInterface && mAAudioService.get()) {
174 mAAudioServiceInterface = &mAAudioService->asAAudioServiceInterface();
175 }
176 return mAAudioServiceInterface;
177}
178
179void FuzzAAudioClient::dropAAudioService() {
180 mAAudioService.clear();
181}
182
183aaudio_handle_t FuzzAAudioClient::openStream(const AAudioStreamRequest &request,
184 AAudioStreamConfiguration &configurationOutput) {
185 aaudio_handle_t stream;
186 for (int i = 0; i < 2; ++i) {
187 AAudioServiceInterface *service = getAAudioService();
188 if (!service) {
189 return AAUDIO_ERROR_NO_SERVICE;
190 }
191
192 stream = service->openStream(request, configurationOutput);
193
194 if (stream == AAUDIO_ERROR_NO_SERVICE) {
195 dropAAudioService();
196 } else {
197 break;
198 }
199 }
200 return stream;
201}
202
203aaudio_result_t FuzzAAudioClient::closeStream(aaudio_handle_t streamHandle) {
204 AAudioServiceInterface *service = getAAudioService();
205 if (!service) {
206 return AAUDIO_ERROR_NO_SERVICE;
207 }
208 return service->closeStream(streamHandle);
209}
210
211aaudio_result_t FuzzAAudioClient::getStreamDescription(aaudio_handle_t streamHandle,
212 AudioEndpointParcelable &parcelable) {
213 AAudioServiceInterface *service = getAAudioService();
214 if (!service) {
215 return AAUDIO_ERROR_NO_SERVICE;
216 }
217 return service->getStreamDescription(streamHandle, parcelable);
218}
219
220aaudio_result_t FuzzAAudioClient::startStream(aaudio_handle_t streamHandle) {
221 AAudioServiceInterface *service = getAAudioService();
222 if (!service) {
223 return AAUDIO_ERROR_NO_SERVICE;
224 }
225 return service->startStream(streamHandle);
226}
227
228aaudio_result_t FuzzAAudioClient::pauseStream(aaudio_handle_t streamHandle) {
229 AAudioServiceInterface *service = getAAudioService();
230 if (!service) {
231 return AAUDIO_ERROR_NO_SERVICE;
232 }
233 return service->pauseStream(streamHandle);
234}
235
236aaudio_result_t FuzzAAudioClient::stopStream(aaudio_handle_t streamHandle) {
237 AAudioServiceInterface *service = getAAudioService();
238 if (!service) {
239 return AAUDIO_ERROR_NO_SERVICE;
240 }
241 return service->stopStream(streamHandle);
242}
243
244aaudio_result_t FuzzAAudioClient::flushStream(aaudio_handle_t streamHandle) {
245 AAudioServiceInterface *service = getAAudioService();
246 if (!service) {
247 return AAUDIO_ERROR_NO_SERVICE;
248 }
249 return service->flushStream(streamHandle);
250}
251
252aaudio_result_t FuzzAAudioClient::registerAudioThread(aaudio_handle_t streamHandle,
253 pid_t clientThreadId,
254 int64_t periodNanoseconds) {
255 AAudioServiceInterface *service = getAAudioService();
256 if (!service) {
257 return AAUDIO_ERROR_NO_SERVICE;
258 }
259 return service->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds);
260}
261
262aaudio_result_t FuzzAAudioClient::unregisterAudioThread(aaudio_handle_t streamHandle,
263 pid_t clientThreadId) {
264 AAudioServiceInterface *service = getAAudioService();
265 if (!service) {
266 return AAUDIO_ERROR_NO_SERVICE;
267 }
268 return service->unregisterAudioThread(streamHandle, clientThreadId);
269}
270
271class OboeserviceFuzzer {
272 public:
273 OboeserviceFuzzer();
274 ~OboeserviceFuzzer() = default;
275 void process(const uint8_t *data, size_t size);
276
277 private:
278 sp<FuzzAAudioClient> mClient;
279};
280
281OboeserviceFuzzer::OboeserviceFuzzer() {
282 sp<AAudioService> service = new AAudioService();
283 mClient = new FuzzAAudioClient(service);
284}
285
286void OboeserviceFuzzer::process(const uint8_t *data, size_t size) {
287 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
288 AAudioStreamRequest request;
289 AAudioStreamConfiguration configurationOutput;
290
291 // Initialize stream request
292 request.getConfiguration().setFormat((audio_format_t)(
293 fdp.ConsumeBool()
294 ? fdp.ConsumeIntegral<int32_t>()
295 : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
296
297 request.setUserId(getuid());
298 request.setProcessId(getpid());
299 request.setInService(fdp.ConsumeBool());
300
301 request.getConfiguration().setDeviceId(fdp.ConsumeIntegral<int32_t>());
302 request.getConfiguration().setSampleRate(fdp.ConsumeIntegral<int32_t>());
303 request.getConfiguration().setSamplesPerFrame(fdp.ConsumeIntegral<int32_t>());
304 request.getConfiguration().setDirection(
305 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
306 : (fdp.ConsumeBool() ? AAUDIO_DIRECTION_OUTPUT : AAUDIO_DIRECTION_INPUT));
307 request.getConfiguration().setSharingMode(
308 fdp.ConsumeBool()
309 ? fdp.ConsumeIntegral<int32_t>()
310 : (fdp.ConsumeBool() ? AAUDIO_SHARING_MODE_EXCLUSIVE : AAUDIO_SHARING_MODE_SHARED));
311
312 request.getConfiguration().setUsage(
313 fdp.ConsumeBool()
314 ? fdp.ConsumeIntegral<int32_t>()
315 : kAAudioUsages[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioUsages - 1)]);
316 request.getConfiguration().setContentType(
317 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
318 : kAAudioContentTypes[fdp.ConsumeIntegralInRange<int32_t>(
319 0, kNumAAudioContentTypes - 1)]);
320 request.getConfiguration().setInputPreset(
321 fdp.ConsumeBool() ? fdp.ConsumeIntegral<int32_t>()
322 : kAAudioInputPresets[fdp.ConsumeIntegralInRange<int32_t>(
323 0, kNumAAudioInputPresets - 1)]);
324 request.getConfiguration().setPrivacySensitive(fdp.ConsumeBool());
325
326 request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
327
328 aaudio_handle_t stream = mClient->openStream(request, configurationOutput);
329 if (stream < 0) {
330 // invalid request, stream not opened.
331 return;
332 }
333 while (fdp.remaining_bytes()) {
334 AudioEndpointParcelable audioEndpointParcelable;
335 int action = fdp.ConsumeIntegralInRange<int32_t>(0, 4);
336 switch (action) {
337 case 0:
338 mClient->getStreamDescription(stream, audioEndpointParcelable);
339 break;
340 case 1:
341 mClient->startStream(stream);
342 break;
343 case 2:
344 mClient->pauseStream(stream);
345 break;
346 case 3:
347 mClient->stopStream(stream);
348 break;
349 case 4:
350 mClient->flushStream(stream);
351 break;
352 }
353 }
354 mClient->closeStream(stream);
355 assert(mClient->getDeathCount() == 0);
356}
357
358extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
359 if (size < 1) {
360 return 0;
361 }
362 OboeserviceFuzzer oboeserviceFuzzer;
363 oboeserviceFuzzer.process(data, size);
364 return 0;
365}