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 SET_PARAMETERS, 40 GET_TIMESTAMP, 41 SIGNAL, 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 if (cblk != 0 && cblk->pointer() == NULL) { 61 cblk.clear(); 62 } 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 setParameters(const String8& keyValuePairs) { 116 Parcel data, reply; 117 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 118 data.writeString8(keyValuePairs); 119 status_t status = remote()->transact(SET_PARAMETERS, data, &reply); 120 if (status == NO_ERROR) { 121 status = reply.readInt32(); 122 } 123 return status; 124 } 125 126 virtual status_t getTimestamp(AudioTimestamp& timestamp) { 127 Parcel data, reply; 128 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 129 status_t status = remote()->transact(GET_TIMESTAMP, data, &reply); 130 if (status == NO_ERROR) { 131 status = reply.readInt32(); 132 if (status == NO_ERROR) { 133 timestamp.mPosition = reply.readInt32(); 134 timestamp.mTime.tv_sec = reply.readInt32(); 135 timestamp.mTime.tv_nsec = reply.readInt32(); 136 } 137 } 138 return status; 139 } 140 141 virtual void signal() { 142 Parcel data, reply; 143 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); 144 remote()->transact(SIGNAL, data, &reply); 145 } 146 }; 147 148 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); 149 150 // ---------------------------------------------------------------------- 151 152 status_t BnAudioTrack::onTransact( 153 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 154 { 155 switch (code) { 156 case GET_CBLK: { 157 CHECK_INTERFACE(IAudioTrack, data, reply); 158 reply->writeStrongBinder(IInterface::asBinder(getCblk())); 159 return NO_ERROR; 160 } break; 161 case START: { 162 CHECK_INTERFACE(IAudioTrack, data, reply); 163 reply->writeInt32(start()); 164 return NO_ERROR; 165 } break; 166 case STOP: { 167 CHECK_INTERFACE(IAudioTrack, data, reply); 168 stop(); 169 return NO_ERROR; 170 } break; 171 case FLUSH: { 172 CHECK_INTERFACE(IAudioTrack, data, reply); 173 flush(); 174 return NO_ERROR; 175 } break; 176 case PAUSE: { 177 CHECK_INTERFACE(IAudioTrack, data, reply); 178 pause(); 179 return NO_ERROR; 180 } 181 case ATTACH_AUX_EFFECT: { 182 CHECK_INTERFACE(IAudioTrack, data, reply); 183 reply->writeInt32(attachAuxEffect(data.readInt32())); 184 return NO_ERROR; 185 } break; 186 case SET_PARAMETERS: { 187 CHECK_INTERFACE(IAudioTrack, data, reply); 188 String8 keyValuePairs(data.readString8()); 189 reply->writeInt32(setParameters(keyValuePairs)); 190 return NO_ERROR; 191 } break; 192 case GET_TIMESTAMP: { 193 CHECK_INTERFACE(IAudioTrack, data, reply); 194 AudioTimestamp timestamp; 195 status_t status = getTimestamp(timestamp); 196 reply->writeInt32(status); 197 if (status == NO_ERROR) { 198 reply->writeInt32(timestamp.mPosition); 199 reply->writeInt32(timestamp.mTime.tv_sec); 200 reply->writeInt32(timestamp.mTime.tv_nsec); 201 } 202 return NO_ERROR; 203 } break; 204 case SIGNAL: { 205 CHECK_INTERFACE(IAudioTrack, data, reply); 206 signal(); 207 return NO_ERROR; 208 } break; 209 default: 210 return BBinder::onTransact(code, data, reply, flags); 211 } 212 } 213 214 } // namespace android 215