1 /*
2 * Copyright (C) 2016 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 #define LOG_TAG "AAudio"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20
21 #include <aaudio/AAudio.h>
22 #include <binder/IPCThreadState.h>
23
24 #include "binding/AudioEndpointParcelable.h"
25 #include "binding/AAudioStreamRequest.h"
26 #include "binding/AAudioServiceDefinitions.h"
27 #include "binding/AAudioStreamConfiguration.h"
28 #include "binding/IAAudioService.h"
29 #include "utility/AAudioUtilities.h"
30
31 namespace android {
32
33 using aaudio::aaudio_handle_t;
34
35 /**
36 * This is used by the AAudio Client to talk to the AAudio Service.
37 *
38 * The order of parameters in the Parcels must match with code in AAudioService.cpp.
39 */
40 class BpAAudioService : public BpInterface<IAAudioService>
41 {
42 public:
BpAAudioService(const sp<IBinder> & impl)43 explicit BpAAudioService(const sp<IBinder>& impl)
44 : BpInterface<IAAudioService>(impl)
45 {
46 }
47
registerClient(const sp<IAAudioClient> & client)48 void registerClient(const sp<IAAudioClient>& client) override
49 {
50 Parcel data, reply;
51 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
52 data.writeStrongBinder(IInterface::asBinder(client));
53 remote()->transact(REGISTER_CLIENT, data, &reply);
54 }
55
openStream(const aaudio::AAudioStreamRequest & request,aaudio::AAudioStreamConfiguration & configurationOutput)56 aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
57 aaudio::AAudioStreamConfiguration &configurationOutput) override {
58 Parcel data, reply;
59 // send command
60 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
61 // request.dump();
62 request.writeToParcel(&data);
63 status_t err = remote()->transact(OPEN_STREAM, data, &reply);
64 if (err != NO_ERROR) {
65 ALOGE("BpAAudioService::client openStream transact failed %d", err);
66 return AAudioConvert_androidToAAudioResult(err);
67 }
68 // parse reply
69 aaudio_handle_t stream;
70 err = reply.readInt32(&stream);
71 if (err != NO_ERROR) {
72 ALOGE("BpAAudioService::client transact(OPEN_STREAM) readInt %d", err);
73 return AAudioConvert_androidToAAudioResult(err);
74 } else if (stream < 0) {
75 ALOGE("BpAAudioService::client OPEN_STREAM passed stream %d", stream);
76 return stream;
77 }
78 err = configurationOutput.readFromParcel(&reply);
79 if (err != NO_ERROR) {
80 ALOGE("BpAAudioService::client openStream readFromParcel failed %d", err);
81 closeStream(stream);
82 return AAudioConvert_androidToAAudioResult(err);
83 }
84 return stream;
85 }
86
closeStream(aaudio_handle_t streamHandle)87 virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle) override {
88 Parcel data, reply;
89 // send command
90 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
91 data.writeInt32(streamHandle);
92 status_t err = remote()->transact(CLOSE_STREAM, data, &reply);
93 if (err != NO_ERROR) {
94 ALOGE("BpAAudioService::client closeStream transact failed %d", err);
95 return AAudioConvert_androidToAAudioResult(err);
96 }
97 // parse reply
98 aaudio_result_t res;
99 reply.readInt32(&res);
100 return res;
101 }
102
getStreamDescription(aaudio_handle_t streamHandle,aaudio::AudioEndpointParcelable & parcelable)103 virtual aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
104 aaudio::AudioEndpointParcelable &parcelable) {
105 Parcel data, reply;
106 // send command
107 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
108 data.writeInt32(streamHandle);
109 status_t err = remote()->transact(GET_STREAM_DESCRIPTION, data, &reply);
110 if (err != NO_ERROR) {
111 ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) returns %d", err);
112 return AAudioConvert_androidToAAudioResult(err);
113 }
114 // parse reply
115 aaudio_result_t result;
116 err = reply.readInt32(&result);
117 if (err != NO_ERROR) {
118 ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) readInt %d", err);
119 return AAudioConvert_androidToAAudioResult(err);
120 } else if (result != AAUDIO_OK) {
121 ALOGE("BpAAudioService::client GET_STREAM_DESCRIPTION passed result %d", result);
122 return result;
123 }
124 err = parcelable.readFromParcel(&reply);
125 if (err != NO_ERROR) {
126 ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) read endpoint %d", err);
127 return AAudioConvert_androidToAAudioResult(err);
128 }
129 return result;
130 }
131
132 // TODO should we wait for a reply?
startStream(aaudio_handle_t streamHandle)133 virtual aaudio_result_t startStream(aaudio_handle_t streamHandle) override {
134 Parcel data, reply;
135 // send command
136 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
137 data.writeInt32(streamHandle);
138 status_t err = remote()->transact(START_STREAM, data, &reply);
139 if (err != NO_ERROR) {
140 return AAudioConvert_androidToAAudioResult(err);
141 }
142 // parse reply
143 aaudio_result_t res;
144 reply.readInt32(&res);
145 return res;
146 }
147
pauseStream(aaudio_handle_t streamHandle)148 virtual aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override {
149 Parcel data, reply;
150 // send command
151 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
152 data.writeInt32(streamHandle);
153 status_t err = remote()->transact(PAUSE_STREAM, data, &reply);
154 if (err != NO_ERROR) {
155 return AAudioConvert_androidToAAudioResult(err);
156 }
157 // parse reply
158 aaudio_result_t res;
159 reply.readInt32(&res);
160 return res;
161 }
162
stopStream(aaudio_handle_t streamHandle)163 virtual aaudio_result_t stopStream(aaudio_handle_t streamHandle) override {
164 Parcel data, reply;
165 // send command
166 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
167 data.writeInt32(streamHandle);
168 status_t err = remote()->transact(STOP_STREAM, data, &reply);
169 if (err != NO_ERROR) {
170 return AAudioConvert_androidToAAudioResult(err);
171 }
172 // parse reply
173 aaudio_result_t res;
174 reply.readInt32(&res);
175 return res;
176 }
177
flushStream(aaudio_handle_t streamHandle)178 virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle) override {
179 Parcel data, reply;
180 // send command
181 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
182 data.writeInt32(streamHandle);
183 status_t err = remote()->transact(FLUSH_STREAM, data, &reply);
184 if (err != NO_ERROR) {
185 return AAudioConvert_androidToAAudioResult(err);
186 }
187 // parse reply
188 aaudio_result_t res;
189 reply.readInt32(&res);
190 return res;
191 }
192
registerAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId,int64_t periodNanoseconds)193 virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
194 pid_t clientThreadId,
195 int64_t periodNanoseconds)
196 override {
197 Parcel data, reply;
198 // send command
199 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
200 data.writeInt32(streamHandle);
201 data.writeInt32((int32_t) clientThreadId);
202 data.writeInt64(periodNanoseconds);
203 status_t err = remote()->transact(REGISTER_AUDIO_THREAD, data, &reply);
204 if (err != NO_ERROR) {
205 return AAudioConvert_androidToAAudioResult(err);
206 }
207 // parse reply
208 aaudio_result_t res;
209 reply.readInt32(&res);
210 return res;
211 }
212
unregisterAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId)213 virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
214 pid_t clientThreadId)
215 override {
216 Parcel data, reply;
217 // send command
218 data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
219 data.writeInt32(streamHandle);
220 data.writeInt32((int32_t) clientThreadId);
221 status_t err = remote()->transact(UNREGISTER_AUDIO_THREAD, data, &reply);
222 if (err != NO_ERROR) {
223 return AAudioConvert_androidToAAudioResult(err);
224 }
225 // parse reply
226 aaudio_result_t res;
227 reply.readInt32(&res);
228 return res;
229 }
230
231 };
232
233 // Implement an interface to the service.
234 // This is here so that you don't have to link with libaaudio static library.
235 IMPLEMENT_META_INTERFACE(AAudioService, "IAAudioService");
236
237 // The order of parameters in the Parcels must match with code in BpAAudioService
238
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)239 status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data,
240 Parcel* reply, uint32_t flags) {
241 aaudio_handle_t streamHandle;
242 aaudio::AAudioStreamRequest request;
243 aaudio::AAudioStreamConfiguration configuration;
244 pid_t tid;
245 int64_t nanoseconds;
246 aaudio_result_t result;
247 status_t status = NO_ERROR;
248 ALOGV("BnAAudioService::onTransact(%i) %i", code, flags);
249
250 switch(code) {
251 case REGISTER_CLIENT: {
252 CHECK_INTERFACE(IAAudioService, data, reply);
253 sp<IAAudioClient> client = interface_cast<IAAudioClient>(
254 data.readStrongBinder());
255 registerClient(client);
256 return NO_ERROR;
257 } break;
258
259 case OPEN_STREAM: {
260 CHECK_INTERFACE(IAAudioService, data, reply);
261 request.readFromParcel(&data);
262 result = request.validate();
263 if (result != AAUDIO_OK) {
264 streamHandle = result;
265 } else {
266 //ALOGD("BnAAudioService::client openStream request dump --------------------");
267 //request.dump();
268 // Override the uid and pid from the client in case they are incorrect.
269 request.setUserId(IPCThreadState::self()->getCallingUid());
270 request.setProcessId(IPCThreadState::self()->getCallingPid());
271 streamHandle = openStream(request, configuration);
272 //ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X",
273 // streamHandle);
274 }
275 reply->writeInt32(streamHandle);
276 configuration.writeToParcel(reply);
277 return NO_ERROR;
278 } break;
279
280 case CLOSE_STREAM: {
281 CHECK_INTERFACE(IAAudioService, data, reply);
282 data.readInt32(&streamHandle);
283 result = closeStream(streamHandle);
284 //ALOGD("BnAAudioService::onTransact CLOSE_STREAM 0x%08X, result = %d",
285 // streamHandle, result);
286 reply->writeInt32(result);
287 return NO_ERROR;
288 } break;
289
290 case GET_STREAM_DESCRIPTION: {
291 CHECK_INTERFACE(IAAudioService, data, reply);
292 status = data.readInt32(&streamHandle);
293 if (status != NO_ERROR) {
294 return status;
295 }
296 aaudio::AudioEndpointParcelable parcelable;
297 result = getStreamDescription(streamHandle, parcelable);
298 if (result != AAUDIO_OK) {
299 return AAudioConvert_aaudioToAndroidStatus(result);
300 }
301 status = reply->writeInt32(result);
302 if (status != NO_ERROR) {
303 return status;
304 }
305 return parcelable.writeToParcel(reply);
306 } break;
307
308 case START_STREAM: {
309 CHECK_INTERFACE(IAAudioService, data, reply);
310 data.readInt32(&streamHandle);
311 result = startStream(streamHandle);
312 ALOGV("BnAAudioService::onTransact START_STREAM 0x%08X, result = %d",
313 streamHandle, result);
314 reply->writeInt32(result);
315 return NO_ERROR;
316 } break;
317
318 case PAUSE_STREAM: {
319 CHECK_INTERFACE(IAAudioService, data, reply);
320 data.readInt32(&streamHandle);
321 result = pauseStream(streamHandle);
322 ALOGV("BnAAudioService::onTransact PAUSE_STREAM 0x%08X, result = %d",
323 streamHandle, result);
324 reply->writeInt32(result);
325 return NO_ERROR;
326 } break;
327
328 case STOP_STREAM: {
329 CHECK_INTERFACE(IAAudioService, data, reply);
330 data.readInt32(&streamHandle);
331 result = stopStream(streamHandle);
332 ALOGV("BnAAudioService::onTransact STOP_STREAM 0x%08X, result = %d",
333 streamHandle, result);
334 reply->writeInt32(result);
335 return NO_ERROR;
336 } break;
337
338 case FLUSH_STREAM: {
339 CHECK_INTERFACE(IAAudioService, data, reply);
340 data.readInt32(&streamHandle);
341 result = flushStream(streamHandle);
342 ALOGV("BnAAudioService::onTransact FLUSH_STREAM 0x%08X, result = %d",
343 streamHandle, result);
344 reply->writeInt32(result);
345 return NO_ERROR;
346 } break;
347
348 case REGISTER_AUDIO_THREAD: {
349 CHECK_INTERFACE(IAAudioService, data, reply);
350 data.readInt32(&streamHandle);
351 data.readInt32(&tid);
352 data.readInt64(&nanoseconds);
353 result = registerAudioThread(streamHandle, tid, nanoseconds);
354 ALOGV("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d",
355 streamHandle, result);
356 reply->writeInt32(result);
357 return NO_ERROR;
358 } break;
359
360 case UNREGISTER_AUDIO_THREAD: {
361 CHECK_INTERFACE(IAAudioService, data, reply);
362 data.readInt32(&streamHandle);
363 data.readInt32(&tid);
364 result = unregisterAudioThread(streamHandle, tid);
365 ALOGV("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d",
366 streamHandle, result);
367 reply->writeInt32(result);
368 return NO_ERROR;
369 } break;
370
371 default:
372 // ALOGW("BnAAudioService::onTransact not handled %u", code);
373 return BBinder::onTransact(code, data, reply, flags);
374 }
375 }
376
377 } /* namespace android */
378