1 /* 2 ** 3 ** Copyright 2007, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "IAudioTrack" 19 //#define LOG_NDEBUG 0 20 #include <utils/Log.h> 21 22 #include <stdint.h> 23 #include <sys/types.h> 24 25 #include <binder/Parcel.h> 26 27 #include <media/IAudioTrack.h> 28 29 namespace android { 30 31 enum { 32 GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, 33 START, 34 STOP, 35 FLUSH, 36 RESERVED, // was MUTE 37 PAUSE, 38 ATTACH_AUX_EFFECT, 39 ALLOCATE_TIMED_BUFFER, 40 QUEUE_TIMED_BUFFER, 41 SET_MEDIA_TIME_TRANSFORM, 42 SET_PARAMETERS, 43 GET_TIMESTAMP, 44 SIGNAL, 45 }; 46 47 class BpAudioTrack : public BpInterface<IAudioTrack> 48 { 49 public: 50 BpAudioTrack(const sp<IBinder>& impl) 51 : BpInterface<IAudioTrack>(impl) 52 { 53 } 54 55 virtual sp<IMemory> getCblk() const 56 { 57 Parcel data, reply; 58 sp<IMemory> cblk; 59 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 60 status_t status = remote()->transact(GET_CBLK, data, &reply); 61 if (status == NO_ERROR) { 62 cblk = interface_cast<IMemory>(reply.readStrongBinder()); 63 if (cblk != 0 && cblk->pointer() == NULL) { 64 cblk.clear(); 65 } 66 } 67 return cblk; 68 } 69 70 virtual status_t start() 71 { 72 Parcel data, reply; 73 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 74 status_t status = remote()->transact(START, data, &reply); 75 if (status == NO_ERROR) { 76 status = reply.readInt32(); 77 } else { 78 ALOGW("start() error: %s", strerror(-status)); 79 } 80 return status; 81 } 82 83 virtual void stop() 84 { 85 Parcel data, reply; 86 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 87 remote()->transact(STOP, data, &reply); 88 } 89 90 virtual void flush() 91 { 92 Parcel data, reply; 93 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 94 remote()->transact(FLUSH, data, &reply); 95 } 96 97 virtual void pause() 98 { 99 Parcel data, reply; 100 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 101 remote()->transact(PAUSE, data, &reply); 102 } 103 104 virtual status_t attachAuxEffect(int effectId) 105 { 106 Parcel data, reply; 107 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 108 data.writeInt32(effectId); 109 status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 110 if (status == NO_ERROR) { 111 status = reply.readInt32(); 112 } else { 113 ALOGW("attachAuxEffect() error: %s", strerror(-status)); 114 } 115 return status; 116 } 117 118 virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { 119 Parcel data, reply; 120 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 121 data.writeInt64(size); 122 status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, 123 data, &reply); 124 if (status == NO_ERROR) { 125 status = reply.readInt32(); 126 if (status == NO_ERROR) { 127 *buffer = interface_cast<IMemory>(reply.readStrongBinder()); 128 if (*buffer != 0 && (*buffer)->pointer() == NULL) { 129 (*buffer).clear(); 130 } 131 } 132 } 133 return status; 134 } 135 136 virtual status_t queueTimedBuffer(const sp<IMemory>& buffer, 137 int64_t pts) { 138 Parcel data, reply; 139 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 140 data.writeStrongBinder(buffer->asBinder()); 141 data.writeInt64(pts); 142 status_t status = remote()->transact(QUEUE_TIMED_BUFFER, 143 data, &reply); 144 if (status == NO_ERROR) { 145 status = reply.readInt32(); 146 } 147 return status; 148 } 149 150 virtual status_t setMediaTimeTransform(const LinearTransform& xform, 151 int target) { 152 Parcel data, reply; 153 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 154 data.writeInt64(xform.a_zero); 155 data.writeInt64(xform.b_zero); 156 data.writeInt32(xform.a_to_b_numer); 157 data.writeInt32(xform.a_to_b_denom); 158 data.writeInt32(target); 159 status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM, 160 data, &reply); 161 if (status == NO_ERROR) { 162 status = reply.readInt32(); 163 } 164 return status; 165 } 166 167 virtual status_t setParameters(const String8& keyValuePairs) { 168 Parcel data, reply; 169 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 170 data.writeString8(keyValuePairs); 171 status_t status = remote()->transact(SET_PARAMETERS, data, &reply); 172 if (status == NO_ERROR) { 173 status = reply.readInt32(); 174 } 175 return status; 176 } 177 178 virtual status_t getTimestamp(AudioTimestamp& timestamp) { 179 Parcel data, reply; 180 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 181 status_t status = remote()->transact(GET_TIMESTAMP, data, &reply); 182 if (status == NO_ERROR) { 183 status = reply.readInt32(); 184 if (status == NO_ERROR) { 185 timestamp.mPosition = reply.readInt32(); 186 timestamp.mTime.tv_sec = reply.readInt32(); 187 timestamp.mTime.tv_nsec = reply.readInt32(); 188 } 189 } 190 return status; 191 } 192 193 virtual void signal() { 194 Parcel data, reply; 195 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 196 remote()->transact(SIGNAL, data, &reply); 197 } 198 }; 199 200 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); 201 202 // ---------------------------------------------------------------------- 203 204 status_t BnAudioTrack::onTransact( 205 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 206 { 207 switch (code) { 208 case GET_CBLK: { 209 CHECK_INTERFACE(IAudioTrack, data, reply); 210 reply->writeStrongBinder(getCblk()->asBinder()); 211 return NO_ERROR; 212 } break; 213 case START: { 214 CHECK_INTERFACE(IAudioTrack, data, reply); 215 reply->writeInt32(start()); 216 return NO_ERROR; 217 } break; 218 case STOP: { 219 CHECK_INTERFACE(IAudioTrack, data, reply); 220 stop(); 221 return NO_ERROR; 222 } break; 223 case FLUSH: { 224 CHECK_INTERFACE(IAudioTrack, data, reply); 225 flush(); 226 return NO_ERROR; 227 } break; 228 case PAUSE: { 229 CHECK_INTERFACE(IAudioTrack, data, reply); 230 pause(); 231 return NO_ERROR; 232 } 233 case ATTACH_AUX_EFFECT: { 234 CHECK_INTERFACE(IAudioTrack, data, reply); 235 reply->writeInt32(attachAuxEffect(data.readInt32())); 236 return NO_ERROR; 237 } break; 238 case ALLOCATE_TIMED_BUFFER: { 239 CHECK_INTERFACE(IAudioTrack, data, reply); 240 sp<IMemory> buffer; 241 status_t status = allocateTimedBuffer(data.readInt64(), &buffer); 242 reply->writeInt32(status); 243 if (status == NO_ERROR) { 244 reply->writeStrongBinder(buffer->asBinder()); 245 } 246 return NO_ERROR; 247 } break; 248 case QUEUE_TIMED_BUFFER: { 249 CHECK_INTERFACE(IAudioTrack, data, reply); 250 sp<IMemory> buffer = interface_cast<IMemory>( 251 data.readStrongBinder()); 252 uint64_t pts = data.readInt64(); 253 reply->writeInt32(queueTimedBuffer(buffer, pts)); 254 return NO_ERROR; 255 } break; 256 case SET_MEDIA_TIME_TRANSFORM: { 257 CHECK_INTERFACE(IAudioTrack, data, reply); 258 LinearTransform xform; 259 xform.a_zero = data.readInt64(); 260 xform.b_zero = data.readInt64(); 261 xform.a_to_b_numer = data.readInt32(); 262 xform.a_to_b_denom = data.readInt32(); 263 int target = data.readInt32(); 264 reply->writeInt32(setMediaTimeTransform(xform, target)); 265 return NO_ERROR; 266 } break; 267 case SET_PARAMETERS: { 268 CHECK_INTERFACE(IAudioTrack, data, reply); 269 String8 keyValuePairs(data.readString8()); 270 reply->writeInt32(setParameters(keyValuePairs)); 271 return NO_ERROR; 272 } break; 273 case GET_TIMESTAMP: { 274 CHECK_INTERFACE(IAudioTrack, data, reply); 275 AudioTimestamp timestamp; 276 status_t status = getTimestamp(timestamp); 277 reply->writeInt32(status); 278 if (status == NO_ERROR) { 279 reply->writeInt32(timestamp.mPosition); 280 reply->writeInt32(timestamp.mTime.tv_sec); 281 reply->writeInt32(timestamp.mTime.tv_nsec); 282 } 283 return NO_ERROR; 284 } break; 285 case SIGNAL: { 286 CHECK_INTERFACE(IAudioTrack, data, reply); 287 signal(); 288 return NO_ERROR; 289 } break; 290 default: 291 return BBinder::onTransact(code, data, reply, flags); 292 } 293 } 294 295 }; // namespace android 296