IAAudioService.cpp revision f53e613b3dedab3ecada2c93d8846233c442d129
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/AAudioDefinitions.h>
18
19#include "binding/AudioEndpointParcelable.h"
20#include "binding/AAudioStreamRequest.h"
21#include "binding/AAudioStreamConfiguration.h"
22#include "binding/IAAudioService.h"
23#include "utility/AAudioUtilities.h"
24
25namespace android {
26
27/**
28 * This is used by the AAudio Client to talk to the AAudio Service.
29 *
30 * The order of parameters in the Parcels must match with code in AAudioService.cpp.
31 */
32class BpAAudioService : public BpInterface<IAAudioService>
33{
34public:
35    explicit BpAAudioService(const sp<IBinder>& impl)
36        : BpInterface<IAAudioService>(impl)
37    {
38    }
39
40    virtual aaudio_handle_t openStream(aaudio::AAudioStreamRequest &request,
41                                     aaudio::AAudioStreamConfiguration &configuration) override {
42        Parcel data, reply;
43        // send command
44        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
45        request.writeToParcel(&data);
46        status_t err = remote()->transact(OPEN_STREAM, data, &reply);
47        if (err != NO_ERROR) {
48            return AAudioConvert_androidToAAudioResult(err);
49        }
50        // parse reply
51        aaudio_handle_t stream;
52        reply.readInt32(&stream);
53        configuration.readFromParcel(&reply);
54        return stream;
55    }
56
57    virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle) override {
58        Parcel data, reply;
59        // send command
60        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
61        data.writeInt32(streamHandle);
62        status_t err = remote()->transact(CLOSE_STREAM, data, &reply);
63        if (err != NO_ERROR) {
64            return AAudioConvert_androidToAAudioResult(err);
65        }
66        // parse reply
67        aaudio_result_t res;
68        reply.readInt32(&res);
69        return res;
70    }
71
72    virtual aaudio_result_t getStreamDescription(aaudio_handle_t streamHandle,
73                                               aaudio::AudioEndpointParcelable &parcelable)   {
74        Parcel data, reply;
75        // send command
76        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
77        data.writeInt32(streamHandle);
78        status_t err = remote()->transact(GET_STREAM_DESCRIPTION, data, &reply);
79        if (err != NO_ERROR) {
80            return AAudioConvert_androidToAAudioResult(err);
81        }
82        // parse reply
83        parcelable.readFromParcel(&reply);
84        parcelable.dump();
85        aaudio_result_t result = parcelable.validate();
86        if (result != AAUDIO_OK) {
87            return result;
88        }
89        reply.readInt32(&result);
90        return result;
91    }
92
93    // TODO should we wait for a reply?
94    virtual aaudio_result_t startStream(aaudio_handle_t streamHandle) override {
95        Parcel data, reply;
96        // send command
97        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
98        data.writeInt32(streamHandle);
99        status_t err = remote()->transact(START_STREAM, data, &reply);
100        if (err != NO_ERROR) {
101            return AAudioConvert_androidToAAudioResult(err);
102        }
103        // parse reply
104        aaudio_result_t res;
105        reply.readInt32(&res);
106        return res;
107    }
108
109    virtual aaudio_result_t pauseStream(aaudio_handle_t streamHandle) override {
110        Parcel data, reply;
111        // send command
112        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
113        data.writeInt32(streamHandle);
114        status_t err = remote()->transact(PAUSE_STREAM, data, &reply);
115        if (err != NO_ERROR) {
116            return AAudioConvert_androidToAAudioResult(err);
117        }
118        // parse reply
119        aaudio_result_t res;
120        reply.readInt32(&res);
121        return res;
122    }
123
124    virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle) override {
125        Parcel data, reply;
126        // send command
127        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
128        data.writeInt32(streamHandle);
129        status_t err = remote()->transact(FLUSH_STREAM, data, &reply);
130        if (err != NO_ERROR) {
131            return AAudioConvert_androidToAAudioResult(err);
132        }
133        // parse reply
134        aaudio_result_t res;
135        reply.readInt32(&res);
136        return res;
137    }
138
139    virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId,
140                                              aaudio_nanoseconds_t periodNanoseconds)
141    override {
142        Parcel data, reply;
143        // send command
144        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
145        data.writeInt32(streamHandle);
146        data.writeInt32((int32_t) clientThreadId);
147        data.writeInt64(periodNanoseconds);
148        status_t err = remote()->transact(REGISTER_AUDIO_THREAD, 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 unregisterAudioThread(aaudio_handle_t streamHandle, pid_t clientThreadId)
159    override {
160        Parcel data, reply;
161        // send command
162        data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
163        data.writeInt32(streamHandle);
164        data.writeInt32((int32_t) clientThreadId);
165        status_t err = remote()->transact(UNREGISTER_AUDIO_THREAD, data, &reply);
166        if (err != NO_ERROR) {
167            return AAudioConvert_androidToAAudioResult(err);
168        }
169        // parse reply
170        aaudio_result_t res;
171        reply.readInt32(&res);
172        return res;
173    }
174
175};
176
177// Implement an interface to the service.
178// This is here so that you don't have to link with liboboe static library.
179IMPLEMENT_META_INTERFACE(AAudioService, "IAAudioService");
180
181// The order of parameters in the Parcels must match with code in BpAAudioService
182
183status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data,
184                                        Parcel* reply, uint32_t flags) {
185    AAudioStream stream;
186    aaudio::AAudioStreamRequest request;
187    aaudio::AAudioStreamConfiguration configuration;
188    pid_t pid;
189    aaudio_nanoseconds_t nanoseconds;
190    aaudio_result_t result;
191    ALOGV("BnAAudioService::onTransact(%i) %i", code, flags);
192    data.checkInterface(this);
193
194    switch(code) {
195        case OPEN_STREAM: {
196            request.readFromParcel(&data);
197            stream = openStream(request, configuration);
198            ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X", stream);
199            reply->writeInt32(stream);
200            configuration.writeToParcel(reply);
201            return NO_ERROR;
202        } break;
203
204        case CLOSE_STREAM: {
205            data.readInt32(&stream);
206            ALOGD("BnAAudioService::onTransact CLOSE_STREAM 0x%08X", stream);
207            result = closeStream(stream);
208            reply->writeInt32(result);
209            return NO_ERROR;
210        } break;
211
212        case GET_STREAM_DESCRIPTION: {
213            data.readInt32(&stream);
214            ALOGD("BnAAudioService::onTransact GET_STREAM_DESCRIPTION 0x%08X", stream);
215            aaudio::AudioEndpointParcelable parcelable;
216            result = getStreamDescription(stream, parcelable);
217            if (result != AAUDIO_OK) {
218                return AAudioConvert_aaudioToAndroidStatus(result);
219            }
220            parcelable.dump();
221            result = parcelable.validate();
222            if (result != AAUDIO_OK) {
223                return AAudioConvert_aaudioToAndroidStatus(result);
224            }
225            parcelable.writeToParcel(reply);
226            reply->writeInt32(result);
227            return NO_ERROR;
228        } break;
229
230        case START_STREAM: {
231            data.readInt32(&stream);
232            result = startStream(stream);
233            ALOGD("BnAAudioService::onTransact START_STREAM 0x%08X, result = %d",
234                    stream, result);
235            reply->writeInt32(result);
236            return NO_ERROR;
237        } break;
238
239        case PAUSE_STREAM: {
240            data.readInt32(&stream);
241            result = pauseStream(stream);
242            ALOGD("BnAAudioService::onTransact PAUSE_STREAM 0x%08X, result = %d",
243                    stream, result);
244            reply->writeInt32(result);
245            return NO_ERROR;
246        } break;
247
248        case FLUSH_STREAM: {
249            data.readInt32(&stream);
250            result = flushStream(stream);
251            ALOGD("BnAAudioService::onTransact FLUSH_STREAM 0x%08X, result = %d",
252                    stream, result);
253            reply->writeInt32(result);
254            return NO_ERROR;
255        } break;
256
257        case REGISTER_AUDIO_THREAD: {
258            data.readInt32(&stream);
259            data.readInt32(&pid);
260            data.readInt64(&nanoseconds);
261            result = registerAudioThread(stream, pid, nanoseconds);
262            ALOGD("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d",
263                    stream, result);
264            reply->writeInt32(result);
265            return NO_ERROR;
266        } break;
267
268        case UNREGISTER_AUDIO_THREAD: {
269            data.readInt32(&stream);
270            data.readInt32(&pid);
271            result = unregisterAudioThread(stream, pid);
272            ALOGD("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d",
273                    stream, result);
274            reply->writeInt32(result);
275            return NO_ERROR;
276        } break;
277
278        default:
279            // ALOGW("BnAAudioService::onTransact not handled %u", code);
280            return BBinder::onTransact(code, data, reply, flags);
281    }
282}
283
284} /* namespace android */
285