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