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 MUTE, 37 PAUSE, 38 ATTACH_AUX_EFFECT, 39 ALLOCATE_TIMED_BUFFER, 40 QUEUE_TIMED_BUFFER, 41 SET_MEDIA_TIME_TRANSFORM, 42 }; 43 44 class BpAudioTrack : public BpInterface<IAudioTrack> 45 { 46 public: 47 BpAudioTrack(const sp<IBinder>& impl) 48 : BpInterface<IAudioTrack>(impl) 49 { 50 } 51 52 virtual sp<IMemory> getCblk() const 53 { 54 Parcel data, reply; 55 sp<IMemory> cblk; 56 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 57 status_t status = remote()->transact(GET_CBLK, data, &reply); 58 if (status == NO_ERROR) { 59 cblk = interface_cast<IMemory>(reply.readStrongBinder()); 60 } 61 return cblk; 62 } 63 64 virtual status_t start() 65 { 66 Parcel data, reply; 67 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 68 status_t status = remote()->transact(START, data, &reply); 69 if (status == NO_ERROR) { 70 status = reply.readInt32(); 71 } else { 72 ALOGW("start() error: %s", strerror(-status)); 73 } 74 return status; 75 } 76 77 virtual void stop() 78 { 79 Parcel data, reply; 80 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 81 remote()->transact(STOP, data, &reply); 82 } 83 84 virtual void flush() 85 { 86 Parcel data, reply; 87 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 88 remote()->transact(FLUSH, data, &reply); 89 } 90 91 virtual void mute(bool e) 92 { 93 Parcel data, reply; 94 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 95 data.writeInt32(e); 96 remote()->transact(MUTE, data, &reply); 97 } 98 99 virtual void pause() 100 { 101 Parcel data, reply; 102 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 103 remote()->transact(PAUSE, data, &reply); 104 } 105 106 virtual status_t attachAuxEffect(int effectId) 107 { 108 Parcel data, reply; 109 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 110 data.writeInt32(effectId); 111 status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 112 if (status == NO_ERROR) { 113 status = reply.readInt32(); 114 } else { 115 ALOGW("attachAuxEffect() error: %s", strerror(-status)); 116 } 117 return status; 118 } 119 120 virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { 121 Parcel data, reply; 122 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 123 data.writeInt32(size); 124 status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, 125 data, &reply); 126 if (status == NO_ERROR) { 127 status = reply.readInt32(); 128 if (status == NO_ERROR) { 129 *buffer = interface_cast<IMemory>(reply.readStrongBinder()); 130 } 131 } 132 return status; 133 } 134 135 virtual status_t queueTimedBuffer(const sp<IMemory>& buffer, 136 int64_t pts) { 137 Parcel data, reply; 138 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 139 data.writeStrongBinder(buffer->asBinder()); 140 data.writeInt64(pts); 141 status_t status = remote()->transact(QUEUE_TIMED_BUFFER, 142 data, &reply); 143 if (status == NO_ERROR) { 144 status = reply.readInt32(); 145 } 146 return status; 147 } 148 149 virtual status_t setMediaTimeTransform(const LinearTransform& xform, 150 int target) { 151 Parcel data, reply; 152 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 153 data.writeInt64(xform.a_zero); 154 data.writeInt64(xform.b_zero); 155 data.writeInt32(xform.a_to_b_numer); 156 data.writeInt32(xform.a_to_b_denom); 157 data.writeInt32(target); 158 status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM, 159 data, &reply); 160 if (status == NO_ERROR) { 161 status = reply.readInt32(); 162 } 163 return status; 164 } 165 }; 166 167 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); 168 169 // ---------------------------------------------------------------------- 170 171 status_t BnAudioTrack::onTransact( 172 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 173 { 174 switch (code) { 175 case GET_CBLK: { 176 CHECK_INTERFACE(IAudioTrack, data, reply); 177 reply->writeStrongBinder(getCblk()->asBinder()); 178 return NO_ERROR; 179 } break; 180 case START: { 181 CHECK_INTERFACE(IAudioTrack, data, reply); 182 reply->writeInt32(start()); 183 return NO_ERROR; 184 } break; 185 case STOP: { 186 CHECK_INTERFACE(IAudioTrack, data, reply); 187 stop(); 188 return NO_ERROR; 189 } break; 190 case FLUSH: { 191 CHECK_INTERFACE(IAudioTrack, data, reply); 192 flush(); 193 return NO_ERROR; 194 } break; 195 case MUTE: { 196 CHECK_INTERFACE(IAudioTrack, data, reply); 197 mute( data.readInt32() ); 198 return NO_ERROR; 199 } break; 200 case PAUSE: { 201 CHECK_INTERFACE(IAudioTrack, data, reply); 202 pause(); 203 return NO_ERROR; 204 } 205 case ATTACH_AUX_EFFECT: { 206 CHECK_INTERFACE(IAudioTrack, data, reply); 207 reply->writeInt32(attachAuxEffect(data.readInt32())); 208 return NO_ERROR; 209 } break; 210 case ALLOCATE_TIMED_BUFFER: { 211 CHECK_INTERFACE(IAudioTrack, data, reply); 212 sp<IMemory> buffer; 213 status_t status = allocateTimedBuffer(data.readInt32(), &buffer); 214 reply->writeInt32(status); 215 if (status == NO_ERROR) { 216 reply->writeStrongBinder(buffer->asBinder()); 217 } 218 return NO_ERROR; 219 } break; 220 case QUEUE_TIMED_BUFFER: { 221 CHECK_INTERFACE(IAudioTrack, data, reply); 222 sp<IMemory> buffer = interface_cast<IMemory>( 223 data.readStrongBinder()); 224 uint64_t pts = data.readInt64(); 225 reply->writeInt32(queueTimedBuffer(buffer, pts)); 226 return NO_ERROR; 227 } break; 228 case SET_MEDIA_TIME_TRANSFORM: { 229 CHECK_INTERFACE(IAudioTrack, data, reply); 230 LinearTransform xform; 231 xform.a_zero = data.readInt64(); 232 xform.b_zero = data.readInt64(); 233 xform.a_to_b_numer = data.readInt32(); 234 xform.a_to_b_denom = data.readInt32(); 235 int target = data.readInt32(); 236 reply->writeInt32(setMediaTimeTransform(xform, target)); 237 return NO_ERROR; 238 } break; 239 default: 240 return BBinder::onTransact(code, data, reply, flags); 241 } 242 } 243 244 }; // namespace android 245