1/* 2 * Copyright (C) 2010 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//#define LOG_NDEBUG 0 18#define LOG_TAG "IStreamSource" 19#include <utils/Log.h> 20 21#include <media/IStreamSource.h> 22#include <media/stagefright/foundation/AMessage.h> 23#include <media/stagefright/foundation/MediaKeys.h> 24 25#include <binder/IMemory.h> 26#include <binder/Parcel.h> 27 28namespace android { 29 30enum { 31 // IStreamSource 32 SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, 33 SET_BUFFERS, 34 ON_BUFFER_AVAILABLE, 35 FLAGS, 36 37 // IStreamListener 38 QUEUE_BUFFER, 39 ISSUE_COMMAND, 40}; 41 42struct BpStreamSource : public BpInterface<IStreamSource> { 43 explicit BpStreamSource(const sp<IBinder> &impl) 44 : BpInterface<IStreamSource>(impl) { 45 } 46 47 virtual void setListener(const sp<IStreamListener> &listener) { 48 Parcel data, reply; 49 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 50 data.writeStrongBinder(IInterface::asBinder(listener)); 51 remote()->transact(SET_LISTENER, data, &reply); 52 } 53 54 virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { 55 Parcel data, reply; 56 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 57 data.writeInt64(static_cast<int64_t>(buffers.size())); 58 for (size_t i = 0; i < buffers.size(); ++i) { 59 data.writeStrongBinder(IInterface::asBinder(buffers.itemAt(i))); 60 } 61 remote()->transact(SET_BUFFERS, data, &reply); 62 } 63 64 virtual void onBufferAvailable(size_t index) { 65 Parcel data, reply; 66 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 67 data.writeInt64(static_cast<int64_t>(index)); 68 remote()->transact( 69 ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); 70 } 71 72 virtual uint32_t flags() const { 73 Parcel data, reply; 74 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 75 remote()->transact(FLAGS, data, &reply); 76 77 return reply.readInt32(); 78 } 79}; 80 81IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource"); 82 83status_t BnStreamSource::onTransact( 84 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 85 switch (code) { 86 case SET_LISTENER: 87 { 88 CHECK_INTERFACE(IStreamSource, data, reply); 89 setListener( 90 interface_cast<IStreamListener>(data.readStrongBinder())); 91 break; 92 } 93 94 case SET_BUFFERS: 95 { 96 CHECK_INTERFACE(IStreamSource, data, reply); 97 size_t n = static_cast<size_t>(data.readInt64()); 98 Vector<sp<IMemory> > buffers; 99 for (size_t i = 0; i < n; ++i) { 100 sp<IMemory> mem = 101 interface_cast<IMemory>(data.readStrongBinder()); 102 103 if (mem != NULL) { 104 buffers.push(mem); 105 } else if (data.dataAvail() == 0) { 106 break; 107 } 108 } 109 setBuffers(buffers); 110 break; 111 } 112 113 case ON_BUFFER_AVAILABLE: 114 { 115 CHECK_INTERFACE(IStreamSource, data, reply); 116 onBufferAvailable(static_cast<size_t>(data.readInt64())); 117 break; 118 } 119 120 case FLAGS: 121 { 122 CHECK_INTERFACE(IStreamSource, data, reply); 123 reply->writeInt32(this->flags()); 124 break; 125 } 126 127 default: 128 return BBinder::onTransact(code, data, reply, flags); 129 } 130 131 return OK; 132} 133 134//////////////////////////////////////////////////////////////////////////////// 135 136struct BpStreamListener : public BpInterface<IStreamListener> { 137 explicit BpStreamListener(const sp<IBinder> &impl) 138 : BpInterface<IStreamListener>(impl) { 139 } 140 141 virtual void queueBuffer(size_t index, size_t size) { 142 Parcel data, reply; 143 data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); 144 data.writeInt64(static_cast<int64_t>(index)); 145 data.writeInt64(static_cast<int64_t>(size)); 146 147 remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); 148 } 149 150 virtual void issueCommand( 151 Command cmd, bool synchronous, const sp<AMessage> &msg) { 152 Parcel data, reply; 153 data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); 154 data.writeInt32(static_cast<int32_t>(cmd)); 155 data.writeInt32(static_cast<int32_t>(synchronous)); 156 157 if (msg != NULL) { 158 data.writeInt32(1); 159 msg->writeToParcel(&data); 160 } else { 161 data.writeInt32(0); 162 } 163 164 remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY); 165 } 166}; 167 168IMPLEMENT_META_INTERFACE(StreamListener, "android.hardware.IStreamListener"); 169 170status_t BnStreamListener::onTransact( 171 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 172 switch (code) { 173 case QUEUE_BUFFER: 174 { 175 CHECK_INTERFACE(IStreamListener, data, reply); 176 size_t index = static_cast<size_t>(data.readInt64()); 177 size_t size = static_cast<size_t>(data.readInt64()); 178 179 queueBuffer(index, size); 180 break; 181 } 182 183 case ISSUE_COMMAND: 184 { 185 CHECK_INTERFACE(IStreamListener, data, reply); 186 Command cmd = static_cast<Command>(data.readInt32()); 187 188 bool synchronous = static_cast<bool>(data.readInt32()); 189 190 sp<AMessage> msg; 191 192 if (data.readInt32()) { 193 msg = AMessage::FromParcel(data); 194 } 195 196 issueCommand(cmd, synchronous, msg); 197 break; 198 } 199 200 default: 201 return BBinder::onTransact(code, data, reply, flags); 202 } 203 204 return OK; 205} 206 207} // namespace android 208