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