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