/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "IMediaHTTPConnection" #include #include #include #include #include #include #include namespace android { enum { CONNECT = IBinder::FIRST_CALL_TRANSACTION, DISCONNECT, READ_AT, GET_SIZE, GET_MIME_TYPE, GET_URI }; struct BpMediaHTTPConnection : public BpInterface { explicit BpMediaHTTPConnection(const sp &impl) : BpInterface(impl) { } virtual bool connect( const char *uri, const KeyedVector *headers) { Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); String16 tmp(uri); data.writeString16(tmp); tmp = String16(""); if (headers != NULL) { for (size_t i = 0; i < headers->size(); ++i) { String16 key(headers->keyAt(i).string()); String16 val(headers->valueAt(i).string()); tmp.append(key); tmp.append(String16(": ")); tmp.append(val); tmp.append(String16("\r\n")); } } data.writeString16(tmp); remote()->transact(CONNECT, data, &reply); int32_t exceptionCode = reply.readExceptionCode(); if (exceptionCode) { return false; } sp binder = reply.readStrongBinder(); mMemory = interface_cast(binder); return mMemory != NULL; } virtual void disconnect() { Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); remote()->transact(DISCONNECT, data, &reply); } virtual ssize_t readAt(off64_t offset, void *buffer, size_t size) { Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); data.writeInt64(offset); data.writeInt32(size); status_t err = remote()->transact(READ_AT, data, &reply); if (err != OK) { ALOGE("remote readAt failed"); return UNKNOWN_ERROR; } int32_t exceptionCode = reply.readExceptionCode(); if (exceptionCode) { return UNKNOWN_ERROR; } int32_t lenOrErrorCode = reply.readInt32(); // Negative values are error codes if (lenOrErrorCode < 0) { return lenOrErrorCode; } size_t len = lenOrErrorCode; if (len > size) { ALOGE("requested %zu, got %zu", size, len); return ERROR_OUT_OF_RANGE; } if (len > mMemory->size()) { ALOGE("got %zu, but memory has %zu", len, mMemory->size()); return ERROR_OUT_OF_RANGE; } if(buffer == NULL) { ALOGE("readAt got a NULL buffer"); return UNKNOWN_ERROR; } if (mMemory->unsecurePointer() == NULL) { ALOGE("readAt got a NULL mMemory->unsecurePointer()"); return UNKNOWN_ERROR; } memcpy(buffer, mMemory->unsecurePointer(), len); return len; } virtual off64_t getSize() { Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); remote()->transact(GET_SIZE, data, &reply); int32_t exceptionCode = reply.readExceptionCode(); if (exceptionCode) { return UNKNOWN_ERROR; } return reply.readInt64(); } virtual status_t getMIMEType(String8 *mimeType) { *mimeType = String8(""); Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); remote()->transact(GET_MIME_TYPE, data, &reply); int32_t exceptionCode = reply.readExceptionCode(); if (exceptionCode) { return UNKNOWN_ERROR; } *mimeType = String8(reply.readString16()); return OK; } virtual status_t getUri(String8 *uri) { *uri = String8(""); Parcel data, reply; data.writeInterfaceToken( IMediaHTTPConnection::getInterfaceDescriptor()); remote()->transact(GET_URI, data, &reply); int32_t exceptionCode = reply.readExceptionCode(); if (exceptionCode) { return UNKNOWN_ERROR; } *uri = String8(reply.readString16()); return OK; } private: sp mMemory; }; IMPLEMENT_META_INTERFACE( MediaHTTPConnection, "android.media.IMediaHTTPConnection"); } // namespace android