IAAudioService.cpp revision a4eb0d86a29be2763be5fac51727858d5095794b
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        ALOGE("BpAAudioService::client openStream request dump --------------------");
49        request.dump();
50        request.writeToParcel(&data);
51        status_t err = remote()->transact(OPEN_STREAM, data, &reply);
52        if (err != NO_ERROR) {
53            return AAudioConvert_androidToAAudioResult(err);
54        }
55        // parse reply
56        aaudio_handle_t stream;
57        reply.readInt32(&stream);
58        err = configurationOutput.readFromParcel(&reply);
59        if (err != NO_ERROR) {
60            ALOGE("BpAAudioService::client openStream readFromParcel failed %d", err);
61            closeStream(stream);
62            return AAudioConvert_androidToAAudioResult(err);
63        }
64        return stream;
65    }
66
67    virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle) override {
68        Parcel data, reply;
69        // send command
70        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
71        data.writeInt32(streamHandle);
72        status_t err = remote()->transact(CLOSE_STREAM, data, &reply);
73        if (err != NO_ERROR) {
74            return AAudioConvert_androidToAAudioResult(err);
75        }
76        // parse reply
77        aaudio_result_t res;
78        reply.readInt32(&res);
79        return res;
80    }
81
82    virtual aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
83                                               aaudio::AudioEndpointParcelable &parcelable)   {
84        Parcel data, reply;
85        // send command
86        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
87        data.writeInt32(streamHandle);
88        status_t err = remote()->transact(GET_STREAM_DESCRIPTION, data, &reply);
89        if (err != NO_ERROR) {
90            ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) returns %d", err);
91            return AAudioConvert_androidToAAudioResult(err);
92        }
93        // parse reply
94        aaudio_result_t result;
95        err = reply.readInt32(&result);
96        if (err != NO_ERROR) {
97            ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) readInt %d", err);
98            return AAudioConvert_androidToAAudioResult(err);
99        } else if (result != AAUDIO_OK) {
100            ALOGE("BpAAudioService::client GET_STREAM_DESCRIPTION passed result %d", result);
101            return result;
102        }
103        err = parcelable.readFromParcel(&reply);;
104        if (err != NO_ERROR) {
105            ALOGE("BpAAudioService::client transact(GET_STREAM_DESCRIPTION) read endpoint %d", err);
106            return AAudioConvert_androidToAAudioResult(err);
107        }
108        //parcelable.dump();
109        result = parcelable.validate();
110        if (result != AAUDIO_OK) {
111            ALOGE("BpAAudioService::client GET_STREAM_DESCRIPTION validation fails %d", result);
112            return result;
113        }
114        return result;
115    }
116
117    // TODO should we wait for a reply?
118    virtual aaudio_result_t startStream(aaudio_handle_t streamHandle) override {
119        Parcel data, reply;
120        // send command
121        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
122        data.writeInt32(streamHandle);
123        status_t err = remote()->transact(START_STREAM, data, &reply);
124        if (err != NO_ERROR) {
125            return AAudioConvert_androidToAAudioResult(err);
126        }
127        // parse reply
128        aaudio_result_t res;
129        reply.readInt32(&res);
130        return res;
131    }
132
133    virtual aaudio_result_t pauseStream(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(PAUSE_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
148    virtual aaudio_result_t flushStream(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(FLUSH_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
163    virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
164                                              pid_t clientProcessId,
165                                              pid_t clientThreadId,
166                                              int64_t periodNanoseconds)
167    override {
168        Parcel data, reply;
169        // send command
170        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
171        data.writeInt32(streamHandle);
172        data.writeInt32((int32_t) clientProcessId);
173        data.writeInt32((int32_t) clientThreadId);
174        data.writeInt64(periodNanoseconds);
175        status_t err = remote()->transact(REGISTER_AUDIO_THREAD, data, &reply);
176        if (err != NO_ERROR) {
177            return AAudioConvert_androidToAAudioResult(err);
178        }
179        // parse reply
180        aaudio_result_t res;
181        reply.readInt32(&res);
182        return res;
183    }
184
185    virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
186                                                  pid_t clientProcessId,
187                                                  pid_t clientThreadId)
188    override {
189        Parcel data, reply;
190        // send command
191        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
192        data.writeInt32(streamHandle);
193        data.writeInt32((int32_t) clientProcessId);
194        data.writeInt32((int32_t) clientThreadId);
195        status_t err = remote()->transact(UNREGISTER_AUDIO_THREAD, data, &reply);
196        if (err != NO_ERROR) {
197            return AAudioConvert_androidToAAudioResult(err);
198        }
199        // parse reply
200        aaudio_result_t res;
201        reply.readInt32(&res);
202        return res;
203    }
204
205};
206
207// Implement an interface to the service.
208// This is here so that you don't have to link with libaaudio static library.
209IMPLEMENT_META_INTERFACE(AAudioService, "IAAudioService");
210
211// The order of parameters in the Parcels must match with code in BpAAudioService
212
213status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data,
214                                        Parcel* reply, uint32_t flags) {
215    aaudio_handle_t stream;
216    aaudio::AAudioStreamRequest request;
217    aaudio::AAudioStreamConfiguration configuration;
218    pid_t pid;
219    pid_t tid;
220    int64_t nanoseconds;
221    aaudio_result_t result;
222    ALOGV("BnAAudioService::onTransact(%i) %i", code, flags);
223    data.checkInterface(this);
224
225    switch(code) {
226        case OPEN_STREAM: {
227            request.readFromParcel(&data);
228
229            ALOGD("BnAAudioService::client openStream request dump --------------------");
230            request.dump();
231
232            stream = openStream(request, configuration);
233            ALOGV("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X", stream);
234            reply->writeInt32(stream);
235            configuration.writeToParcel(reply);
236            return NO_ERROR;
237        } break;
238
239        case CLOSE_STREAM: {
240            data.readInt32(&stream);
241            ALOGV("BnAAudioService::onTransact CLOSE_STREAM 0x%08X", stream);
242            result = closeStream(stream);
243            reply->writeInt32(result);
244            return NO_ERROR;
245        } break;
246
247        case GET_STREAM_DESCRIPTION: {
248            data.readInt32(&stream);
249            ALOGI("BnAAudioService::onTransact GET_STREAM_DESCRIPTION 0x%08X", stream);
250            aaudio::AudioEndpointParcelable parcelable;
251            result = getStreamDescription(stream, parcelable);
252            ALOGI("BnAAudioService::onTransact getStreamDescription() returns %d", result);
253            if (result != AAUDIO_OK) {
254                return AAudioConvert_aaudioToAndroidStatus(result);
255            }
256            result = parcelable.validate();
257            if (result != AAUDIO_OK) {
258                ALOGE("BnAAudioService::onTransact getStreamDescription() returns %d", result);
259                parcelable.dump();
260                return AAudioConvert_aaudioToAndroidStatus(result);
261            }
262            reply->writeInt32(result);
263            parcelable.writeToParcel(reply);
264            return NO_ERROR;
265        } break;
266
267        case START_STREAM: {
268            data.readInt32(&stream);
269            result = startStream(stream);
270            ALOGV("BnAAudioService::onTransact START_STREAM 0x%08X, result = %d",
271                    stream, result);
272            reply->writeInt32(result);
273            return NO_ERROR;
274        } break;
275
276        case PAUSE_STREAM: {
277            data.readInt32(&stream);
278            result = pauseStream(stream);
279            ALOGV("BnAAudioService::onTransact PAUSE_STREAM 0x%08X, result = %d",
280                    stream, result);
281            reply->writeInt32(result);
282            return NO_ERROR;
283        } break;
284
285        case FLUSH_STREAM: {
286            data.readInt32(&stream);
287            result = flushStream(stream);
288            ALOGV("BnAAudioService::onTransact FLUSH_STREAM 0x%08X, result = %d",
289                    stream, result);
290            reply->writeInt32(result);
291            return NO_ERROR;
292        } break;
293
294        case REGISTER_AUDIO_THREAD: {
295            data.readInt32(&stream);
296            data.readInt32(&pid);
297            data.readInt32(&tid);
298            data.readInt64(&nanoseconds);
299            result = registerAudioThread(stream, pid, tid, nanoseconds);
300            ALOGV("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d",
301                    stream, result);
302            reply->writeInt32(result);
303            return NO_ERROR;
304        } break;
305
306        case UNREGISTER_AUDIO_THREAD: {
307            data.readInt32(&stream);
308            data.readInt32(&pid);
309            data.readInt32(&tid);
310            result = unregisterAudioThread(stream, pid, tid);
311            ALOGV("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d",
312                    stream, result);
313            reply->writeInt32(result);
314            return NO_ERROR;
315        } break;
316
317        default:
318            // ALOGW("BnAAudioService::onTransact not handled %u", code);
319            return BBinder::onTransact(code, data, reply, flags);
320    }
321}
322
323} /* namespace android */
324