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