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 } 64 return cblk; 65 } 66 67 virtual status_t start() 68 { 69 Parcel data, reply; 70 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 71 status_t status = remote()->transact(START, data, &reply); 72 if (status == NO_ERROR) { 73 status = reply.readInt32(); 74 } else { 75 ALOGW("start() error: %s", strerror(-status)); 76 } 77 return status; 78 } 79 80 virtual void stop() 81 { 82 Parcel data, reply; 83 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 84 remote()->transact(STOP, data, &reply); 85 } 86 87 virtual void flush() 88 { 89 Parcel data, reply; 90 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 91 remote()->transact(FLUSH, data, &reply); 92 } 93 94 virtual void pause() 95 { 96 Parcel data, reply; 97 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 98 remote()->transact(PAUSE, data, &reply); 99 } 100 101 virtual status_t attachAuxEffect(int effectId) 102 { 103 Parcel data, reply; 104 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 105 data.writeInt32(effectId); 106 status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 107 if (status == NO_ERROR) { 108 status = reply.readInt32(); 109 } else { 110 ALOGW("attachAuxEffect() error: %s", strerror(-status)); 111 } 112 return status; 113 } 114 115 virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { 116 Parcel data, reply; 117 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 118 data.writeInt32(size); 119 status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, 120 data, &reply); 121 if (status == NO_ERROR) { 122 status = reply.readInt32(); 123 if (status == NO_ERROR) { 124 *buffer = interface_cast<IMemory>(reply.readStrongBinder()); 125 } 126 } 127 return status; 128 } 129 130 virtual status_t queueTimedBuffer(const sp<IMemory>& buffer, 131 int64_t pts) { 132 Parcel data, reply; 133 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 134 data.writeStrongBinder(buffer->asBinder()); 135 data.writeInt64(pts); 136 status_t status = remote()->transact(QUEUE_TIMED_BUFFER, 137 data, &reply); 138 if (status == NO_ERROR) { 139 status = reply.readInt32(); 140 } 141 return status; 142 } 143 144 virtual status_t setMediaTimeTransform(const LinearTransform& xform, 145 int target) { 146 Parcel data, reply; 147 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 148 data.writeInt64(xform.a_zero); 149 data.writeInt64(xform.b_zero); 150 data.writeInt32(xform.a_to_b_numer); 151 data.writeInt32(xform.a_to_b_denom); 152 data.writeInt32(target); 153 status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM, 154 data, &reply); 155 if (status == NO_ERROR) { 156 status = reply.readInt32(); 157 } 158 return status; 159 } 160 161 virtual status_t setParameters(const String8& keyValuePairs) { 162 Parcel data, reply; 163 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 164 data.writeString8(keyValuePairs); 165 status_t status = remote()->transact(SET_PARAMETERS, data, &reply); 166 if (status == NO_ERROR) { 167 status = reply.readInt32(); 168 } 169 return status; 170 } 171 172 virtual status_t getTimestamp(AudioTimestamp& timestamp) { 173 Parcel data, reply; 174 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 175 status_t status = remote()->transact(GET_TIMESTAMP, data, &reply); 176 if (status == NO_ERROR) { 177 status = reply.readInt32(); 178 if (status == NO_ERROR) { 179 timestamp.mPosition = reply.readInt32(); 180 timestamp.mTime.tv_sec = reply.readInt32(); 181 timestamp.mTime.tv_nsec = reply.readInt32(); 182 } 183 } 184 return status; 185 } 186 187 virtual void signal() { 188 Parcel data, reply; 189 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 190 remote()->transact(SIGNAL, data, &reply); 191 } 192 }; 193 194 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); 195 196 // ---------------------------------------------------------------------- 197 198 status_t BnAudioTrack::onTransact( 199 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 200 { 201 switch (code) { 202 case GET_CBLK: { 203 CHECK_INTERFACE(IAudioTrack, data, reply); 204 reply->writeStrongBinder(getCblk()->asBinder()); 205 return NO_ERROR; 206 } break; 207 case START: { 208 CHECK_INTERFACE(IAudioTrack, data, reply); 209 reply->writeInt32(start()); 210 return NO_ERROR; 211 } break; 212 case STOP: { 213 CHECK_INTERFACE(IAudioTrack, data, reply); 214 stop(); 215 return NO_ERROR; 216 } break; 217 case FLUSH: { 218 CHECK_INTERFACE(IAudioTrack, data, reply); 219 flush(); 220 return NO_ERROR; 221 } break; 222 case PAUSE: { 223 CHECK_INTERFACE(IAudioTrack, data, reply); 224 pause(); 225 return NO_ERROR; 226 } 227 case ATTACH_AUX_EFFECT: { 228 CHECK_INTERFACE(IAudioTrack, data, reply); 229 reply->writeInt32(attachAuxEffect(data.readInt32())); 230 return NO_ERROR; 231 } break; 232 case ALLOCATE_TIMED_BUFFER: { 233 CHECK_INTERFACE(IAudioTrack, data, reply); 234 sp<IMemory> buffer; 235 status_t status = allocateTimedBuffer(data.readInt32(), &buffer); 236 reply->writeInt32(status); 237 if (status == NO_ERROR) { 238 reply->writeStrongBinder(buffer->asBinder()); 239 } 240 return NO_ERROR; 241 } break; 242 case QUEUE_TIMED_BUFFER: { 243 CHECK_INTERFACE(IAudioTrack, data, reply); 244 sp<IMemory> buffer = interface_cast<IMemory>( 245 data.readStrongBinder()); 246 uint64_t pts = data.readInt64(); 247 reply->writeInt32(queueTimedBuffer(buffer, pts)); 248 return NO_ERROR; 249 } break; 250 case SET_MEDIA_TIME_TRANSFORM: { 251 CHECK_INTERFACE(IAudioTrack, data, reply); 252 LinearTransform xform; 253 xform.a_zero = data.readInt64(); 254 xform.b_zero = data.readInt64(); 255 xform.a_to_b_numer = data.readInt32(); 256 xform.a_to_b_denom = data.readInt32(); 257 int target = data.readInt32(); 258 reply->writeInt32(setMediaTimeTransform(xform, target)); 259 return NO_ERROR; 260 } break; 261 case SET_PARAMETERS: { 262 CHECK_INTERFACE(IAudioTrack, data, reply); 263 String8 keyValuePairs(data.readString8()); 264 reply->writeInt32(setParameters(keyValuePairs)); 265 return NO_ERROR; 266 } break; 267 case GET_TIMESTAMP: { 268 CHECK_INTERFACE(IAudioTrack, data, reply); 269 AudioTimestamp timestamp; 270 status_t status = getTimestamp(timestamp); 271 reply->writeInt32(status); 272 if (status == NO_ERROR) { 273 reply->writeInt32(timestamp.mPosition); 274 reply->writeInt32(timestamp.mTime.tv_sec); 275 reply->writeInt32(timestamp.mTime.tv_nsec); 276 } 277 return NO_ERROR; 278 } break; 279 case SIGNAL: { 280 CHECK_INTERFACE(IAudioTrack, data, reply); 281 signal(); 282 return NO_ERROR; 283 } break; 284 default: 285 return BBinder::onTransact(code, data, reply, flags); 286 } 287 } 288 289 }; // namespace android 290