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 26 namespace android { 27 28 using 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 */ 35 class BpAAudioService : public BpInterface<IAAudioService> 36 { 37 public: 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. 234 IMPLEMENT_META_INTERFACE(AAudioService, "IAAudioService"); 235 236 // The order of parameters in the Parcels must match with code in BpAAudioService 237 238 status_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