Home | History | Annotate | Download | only in libmedia
      1 /*
      2  * Copyright (C) 2013 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 "IMediaHTTPConnection"
     19 #include <utils/Log.h>
     20 
     21 #include <media/IMediaHTTPConnection.h>
     22 
     23 #include <binder/IMemory.h>
     24 #include <binder/Parcel.h>
     25 #include <utils/String8.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 
     29 namespace android {
     30 
     31 enum {
     32     CONNECT = IBinder::FIRST_CALL_TRANSACTION,
     33     DISCONNECT,
     34     READ_AT,
     35     GET_SIZE,
     36     GET_MIME_TYPE,
     37     GET_URI
     38 };
     39 
     40 struct BpMediaHTTPConnection : public BpInterface<IMediaHTTPConnection> {
     41     explicit BpMediaHTTPConnection(const sp<IBinder> &impl)
     42         : BpInterface<IMediaHTTPConnection>(impl) {
     43     }
     44 
     45     virtual bool connect(
     46             const char *uri, const KeyedVector<String8, String8> *headers) {
     47         Parcel data, reply;
     48         data.writeInterfaceToken(
     49                 IMediaHTTPConnection::getInterfaceDescriptor());
     50 
     51         String16 tmp(uri);
     52         data.writeString16(tmp);
     53 
     54         tmp = String16("");
     55         if (headers != NULL) {
     56             for (size_t i = 0; i < headers->size(); ++i) {
     57                 String16 key(headers->keyAt(i).string());
     58                 String16 val(headers->valueAt(i).string());
     59 
     60                 tmp.append(key);
     61                 tmp.append(String16(": "));
     62                 tmp.append(val);
     63                 tmp.append(String16("\r\n"));
     64             }
     65         }
     66         data.writeString16(tmp);
     67 
     68         remote()->transact(CONNECT, data, &reply);
     69 
     70         int32_t exceptionCode = reply.readExceptionCode();
     71 
     72         if (exceptionCode) {
     73             return false;
     74         }
     75 
     76         sp<IBinder> binder = reply.readStrongBinder();
     77         mMemory = interface_cast<IMemory>(binder);
     78 
     79         return mMemory != NULL;
     80     }
     81 
     82     virtual void disconnect() {
     83         Parcel data, reply;
     84         data.writeInterfaceToken(
     85                 IMediaHTTPConnection::getInterfaceDescriptor());
     86 
     87         remote()->transact(DISCONNECT, data, &reply);
     88     }
     89 
     90     virtual ssize_t readAt(off64_t offset, void *buffer, size_t size) {
     91         Parcel data, reply;
     92         data.writeInterfaceToken(
     93                 IMediaHTTPConnection::getInterfaceDescriptor());
     94 
     95         data.writeInt64(offset);
     96         data.writeInt32(size);
     97 
     98         status_t err = remote()->transact(READ_AT, data, &reply);
     99         if (err != OK) {
    100             ALOGE("remote readAt failed");
    101             return UNKNOWN_ERROR;
    102         }
    103 
    104         int32_t exceptionCode = reply.readExceptionCode();
    105 
    106         if (exceptionCode) {
    107             return UNKNOWN_ERROR;
    108         }
    109 
    110         int32_t lenOrErrorCode = reply.readInt32();
    111 
    112         // Negative values are error codes
    113         if (lenOrErrorCode < 0) {
    114             return lenOrErrorCode;
    115         }
    116 
    117         size_t len = lenOrErrorCode;
    118 
    119         if (len > size) {
    120             ALOGE("requested %zu, got %zu", size, len);
    121             return ERROR_OUT_OF_RANGE;
    122         }
    123         if (len > mMemory->size()) {
    124             ALOGE("got %zu, but memory has %zu", len, mMemory->size());
    125             return ERROR_OUT_OF_RANGE;
    126         }
    127         if(buffer == NULL) {
    128            ALOGE("readAt got a NULL buffer");
    129            return UNKNOWN_ERROR;
    130         }
    131         if (mMemory->pointer() == NULL) {
    132            ALOGE("readAt got a NULL mMemory->pointer()");
    133            return UNKNOWN_ERROR;
    134         }
    135 
    136         memcpy(buffer, mMemory->pointer(), len);
    137 
    138         return len;
    139     }
    140 
    141     virtual off64_t getSize() {
    142         Parcel data, reply;
    143         data.writeInterfaceToken(
    144                 IMediaHTTPConnection::getInterfaceDescriptor());
    145 
    146         remote()->transact(GET_SIZE, data, &reply);
    147 
    148         int32_t exceptionCode = reply.readExceptionCode();
    149 
    150         if (exceptionCode) {
    151             return UNKNOWN_ERROR;
    152         }
    153 
    154         return reply.readInt64();
    155     }
    156 
    157     virtual status_t getMIMEType(String8 *mimeType) {
    158         *mimeType = String8("");
    159 
    160         Parcel data, reply;
    161         data.writeInterfaceToken(
    162                 IMediaHTTPConnection::getInterfaceDescriptor());
    163 
    164         remote()->transact(GET_MIME_TYPE, data, &reply);
    165 
    166         int32_t exceptionCode = reply.readExceptionCode();
    167 
    168         if (exceptionCode) {
    169             return UNKNOWN_ERROR;
    170         }
    171 
    172         *mimeType = String8(reply.readString16());
    173 
    174         return OK;
    175     }
    176 
    177     virtual status_t getUri(String8 *uri) {
    178         *uri = String8("");
    179 
    180         Parcel data, reply;
    181         data.writeInterfaceToken(
    182                 IMediaHTTPConnection::getInterfaceDescriptor());
    183 
    184         remote()->transact(GET_URI, data, &reply);
    185 
    186         int32_t exceptionCode = reply.readExceptionCode();
    187 
    188         if (exceptionCode) {
    189             return UNKNOWN_ERROR;
    190         }
    191 
    192         *uri = String8(reply.readString16());
    193 
    194         return OK;
    195     }
    196 
    197 private:
    198     sp<IMemory> mMemory;
    199 };
    200 
    201 IMPLEMENT_META_INTERFACE(
    202         MediaHTTPConnection, "android.media.IMediaHTTPConnection");
    203 
    204 } // namespace android
    205