Home | History | Annotate | Download | only in libmedia
      1 /*
      2  * Copyright (C) 2012 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 "IHDCP"
     19 #include <utils/Log.h>
     20 
     21 #include <binder/Parcel.h>
     22 #include <media/IHDCP.h>
     23 #include <media/stagefright/MediaErrors.h>
     24 #include <media/stagefright/foundation/ADebug.h>
     25 
     26 namespace android {
     27 
     28 enum {
     29     OBSERVER_NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
     30     HDCP_SET_OBSERVER,
     31     HDCP_INIT_ASYNC,
     32     HDCP_SHUTDOWN_ASYNC,
     33     HDCP_ENCRYPT,
     34     HDCP_DECRYPT,
     35 };
     36 
     37 struct BpHDCPObserver : public BpInterface<IHDCPObserver> {
     38     BpHDCPObserver(const sp<IBinder> &impl)
     39         : BpInterface<IHDCPObserver>(impl) {
     40     }
     41 
     42     virtual void notify(
     43             int msg, int ext1, int ext2, const Parcel *obj) {
     44         Parcel data, reply;
     45         data.writeInterfaceToken(IHDCPObserver::getInterfaceDescriptor());
     46         data.writeInt32(msg);
     47         data.writeInt32(ext1);
     48         data.writeInt32(ext2);
     49         if (obj && obj->dataSize() > 0) {
     50             data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
     51         }
     52         remote()->transact(OBSERVER_NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
     53     }
     54 };
     55 
     56 IMPLEMENT_META_INTERFACE(HDCPObserver, "android.hardware.IHDCPObserver");
     57 
     58 struct BpHDCP : public BpInterface<IHDCP> {
     59     BpHDCP(const sp<IBinder> &impl)
     60         : BpInterface<IHDCP>(impl) {
     61     }
     62 
     63     virtual status_t setObserver(const sp<IHDCPObserver> &observer) {
     64         Parcel data, reply;
     65         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
     66         data.writeStrongBinder(observer->asBinder());
     67         remote()->transact(HDCP_SET_OBSERVER, data, &reply);
     68         return reply.readInt32();
     69     }
     70 
     71     virtual status_t initAsync(const char *host, unsigned port) {
     72         Parcel data, reply;
     73         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
     74         data.writeCString(host);
     75         data.writeInt32(port);
     76         remote()->transact(HDCP_INIT_ASYNC, data, &reply);
     77         return reply.readInt32();
     78     }
     79 
     80     virtual status_t shutdownAsync() {
     81         Parcel data, reply;
     82         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
     83         remote()->transact(HDCP_SHUTDOWN_ASYNC, data, &reply);
     84         return reply.readInt32();
     85     }
     86 
     87     virtual status_t encrypt(
     88             const void *inData, size_t size, uint32_t streamCTR,
     89             uint64_t *outInputCTR, void *outData) {
     90         Parcel data, reply;
     91         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
     92         data.writeInt32(size);
     93         data.write(inData, size);
     94         data.writeInt32(streamCTR);
     95         remote()->transact(HDCP_ENCRYPT, data, &reply);
     96 
     97         status_t err = reply.readInt32();
     98 
     99         if (err != OK) {
    100             *outInputCTR = 0;
    101 
    102             return err;
    103         }
    104 
    105         *outInputCTR = reply.readInt64();
    106         reply.read(outData, size);
    107 
    108         return err;
    109     }
    110 
    111     virtual status_t decrypt(
    112             const void *inData, size_t size,
    113             uint32_t streamCTR, uint64_t inputCTR,
    114             void *outData) {
    115         Parcel data, reply;
    116         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
    117         data.writeInt32(size);
    118         data.write(inData, size);
    119         data.writeInt32(streamCTR);
    120         data.writeInt64(inputCTR);
    121         remote()->transact(HDCP_DECRYPT, data, &reply);
    122 
    123         status_t err = reply.readInt32();
    124 
    125         if (err != OK) {
    126             return err;
    127         }
    128 
    129         reply.read(outData, size);
    130 
    131         return err;
    132     }
    133 };
    134 
    135 IMPLEMENT_META_INTERFACE(HDCP, "android.hardware.IHDCP");
    136 
    137 status_t BnHDCPObserver::onTransact(
    138         uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    139     switch (code) {
    140         case OBSERVER_NOTIFY:
    141         {
    142             CHECK_INTERFACE(IHDCPObserver, data, reply);
    143 
    144             int msg = data.readInt32();
    145             int ext1 = data.readInt32();
    146             int ext2 = data.readInt32();
    147 
    148             Parcel obj;
    149             if (data.dataAvail() > 0) {
    150                 obj.appendFrom(
    151                         const_cast<Parcel *>(&data),
    152                         data.dataPosition(),
    153                         data.dataAvail());
    154             }
    155 
    156             notify(msg, ext1, ext2, &obj);
    157 
    158             return OK;
    159         }
    160 
    161         default:
    162             return BBinder::onTransact(code, data, reply, flags);
    163     }
    164 }
    165 
    166 status_t BnHDCP::onTransact(
    167         uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    168     switch (code) {
    169         case HDCP_SET_OBSERVER:
    170         {
    171             CHECK_INTERFACE(IHDCP, data, reply);
    172 
    173             sp<IHDCPObserver> observer =
    174                 interface_cast<IHDCPObserver>(data.readStrongBinder());
    175 
    176             reply->writeInt32(setObserver(observer));
    177             return OK;
    178         }
    179 
    180         case HDCP_INIT_ASYNC:
    181         {
    182             CHECK_INTERFACE(IHDCP, data, reply);
    183 
    184             const char *host = data.readCString();
    185             unsigned port = data.readInt32();
    186 
    187             reply->writeInt32(initAsync(host, port));
    188             return OK;
    189         }
    190 
    191         case HDCP_SHUTDOWN_ASYNC:
    192         {
    193             CHECK_INTERFACE(IHDCP, data, reply);
    194 
    195             reply->writeInt32(shutdownAsync());
    196             return OK;
    197         }
    198 
    199         case HDCP_ENCRYPT:
    200         {
    201             size_t size = data.readInt32();
    202 
    203             void *inData = malloc(2 * size);
    204             void *outData = (uint8_t *)inData + size;
    205 
    206             data.read(inData, size);
    207 
    208             uint32_t streamCTR = data.readInt32();
    209             uint64_t inputCTR;
    210             status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData);
    211 
    212             reply->writeInt32(err);
    213 
    214             if (err == OK) {
    215                 reply->writeInt64(inputCTR);
    216                 reply->write(outData, size);
    217             }
    218 
    219             free(inData);
    220             inData = outData = NULL;
    221 
    222             return OK;
    223         }
    224 
    225         case HDCP_DECRYPT:
    226         {
    227             size_t size = data.readInt32();
    228 
    229             void *inData = malloc(2 * size);
    230             void *outData = (uint8_t *)inData + size;
    231 
    232             data.read(inData, size);
    233 
    234             uint32_t streamCTR = data.readInt32();
    235             uint64_t inputCTR = data.readInt64();
    236             status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);
    237 
    238             reply->writeInt32(err);
    239 
    240             if (err == OK) {
    241                 reply->write(outData, size);
    242             }
    243 
    244             free(inData);
    245             inData = outData = NULL;
    246 
    247             return OK;
    248         }
    249 
    250         default:
    251             return BBinder::onTransact(code, data, reply, flags);
    252     }
    253 }
    254 
    255 }  // namespace android
    256