IHDCP.cpp revision 308bcaa44e578279e61be32b572fdb0b11b1e4c7
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 26namespace android { 27 28enum { 29 OBSERVER_NOTIFY = IBinder::FIRST_CALL_TRANSACTION, 30 HDCP_SET_OBSERVER, 31 HDCP_INIT_ASYNC, 32 HDCP_SHUTDOWN_ASYNC, 33 HDCP_ENCRYPT, 34 HDCP_ENCRYPT_NATIVE, 35 HDCP_DECRYPT, 36}; 37 38struct BpHDCPObserver : public BpInterface<IHDCPObserver> { 39 BpHDCPObserver(const sp<IBinder> &impl) 40 : BpInterface<IHDCPObserver>(impl) { 41 } 42 43 virtual void notify( 44 int msg, int ext1, int ext2, const Parcel *obj) { 45 Parcel data, reply; 46 data.writeInterfaceToken(IHDCPObserver::getInterfaceDescriptor()); 47 data.writeInt32(msg); 48 data.writeInt32(ext1); 49 data.writeInt32(ext2); 50 if (obj && obj->dataSize() > 0) { 51 data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize()); 52 } 53 remote()->transact(OBSERVER_NOTIFY, data, &reply, IBinder::FLAG_ONEWAY); 54 } 55}; 56 57IMPLEMENT_META_INTERFACE(HDCPObserver, "android.hardware.IHDCPObserver"); 58 59struct BpHDCP : public BpInterface<IHDCP> { 60 BpHDCP(const sp<IBinder> &impl) 61 : BpInterface<IHDCP>(impl) { 62 } 63 64 virtual status_t setObserver(const sp<IHDCPObserver> &observer) { 65 Parcel data, reply; 66 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 67 data.writeStrongBinder(observer->asBinder()); 68 remote()->transact(HDCP_SET_OBSERVER, data, &reply); 69 return reply.readInt32(); 70 } 71 72 virtual status_t initAsync(const char *host, unsigned port) { 73 Parcel data, reply; 74 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 75 data.writeCString(host); 76 data.writeInt32(port); 77 remote()->transact(HDCP_INIT_ASYNC, data, &reply); 78 return reply.readInt32(); 79 } 80 81 virtual status_t shutdownAsync() { 82 Parcel data, reply; 83 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 84 remote()->transact(HDCP_SHUTDOWN_ASYNC, data, &reply); 85 return reply.readInt32(); 86 } 87 88 virtual status_t encrypt( 89 const void *inData, size_t size, uint32_t streamCTR, 90 uint64_t *outInputCTR, void *outData) { 91 Parcel data, reply; 92 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 93 data.writeInt32(size); 94 data.write(inData, size); 95 data.writeInt32(streamCTR); 96 remote()->transact(HDCP_ENCRYPT, data, &reply); 97 98 status_t err = reply.readInt32(); 99 100 if (err != OK) { 101 *outInputCTR = 0; 102 103 return err; 104 } 105 106 *outInputCTR = reply.readInt64(); 107 reply.read(outData, size); 108 109 return err; 110 } 111 112 virtual status_t encryptNative( 113 const sp<GraphicBuffer> &graphicBuffer, 114 size_t offset, size_t size, uint32_t streamCTR, 115 uint64_t *outInputCTR, void *outData) { 116 Parcel data, reply; 117 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 118 data.write(*graphicBuffer); 119 data.writeInt32(offset); 120 data.writeInt32(size); 121 data.writeInt32(streamCTR); 122 remote()->transact(HDCP_ENCRYPT_NATIVE, data, &reply); 123 124 status_t err = reply.readInt32(); 125 126 if (err != OK) { 127 *outInputCTR = 0; 128 return err; 129 } 130 131 *outInputCTR = reply.readInt64(); 132 reply.read(outData, size); 133 134 return err; 135 } 136 137 virtual status_t decrypt( 138 const void *inData, size_t size, 139 uint32_t streamCTR, uint64_t inputCTR, 140 void *outData) { 141 Parcel data, reply; 142 data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); 143 data.writeInt32(size); 144 data.write(inData, size); 145 data.writeInt32(streamCTR); 146 data.writeInt64(inputCTR); 147 remote()->transact(HDCP_DECRYPT, data, &reply); 148 149 status_t err = reply.readInt32(); 150 151 if (err != OK) { 152 return err; 153 } 154 155 reply.read(outData, size); 156 157 return err; 158 } 159}; 160 161IMPLEMENT_META_INTERFACE(HDCP, "android.hardware.IHDCP"); 162 163status_t BnHDCPObserver::onTransact( 164 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 165 switch (code) { 166 case OBSERVER_NOTIFY: 167 { 168 CHECK_INTERFACE(IHDCPObserver, data, reply); 169 170 int msg = data.readInt32(); 171 int ext1 = data.readInt32(); 172 int ext2 = data.readInt32(); 173 174 Parcel obj; 175 if (data.dataAvail() > 0) { 176 obj.appendFrom( 177 const_cast<Parcel *>(&data), 178 data.dataPosition(), 179 data.dataAvail()); 180 } 181 182 notify(msg, ext1, ext2, &obj); 183 184 return OK; 185 } 186 187 default: 188 return BBinder::onTransact(code, data, reply, flags); 189 } 190} 191 192status_t BnHDCP::onTransact( 193 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 194 switch (code) { 195 case HDCP_SET_OBSERVER: 196 { 197 CHECK_INTERFACE(IHDCP, data, reply); 198 199 sp<IHDCPObserver> observer = 200 interface_cast<IHDCPObserver>(data.readStrongBinder()); 201 202 reply->writeInt32(setObserver(observer)); 203 return OK; 204 } 205 206 case HDCP_INIT_ASYNC: 207 { 208 CHECK_INTERFACE(IHDCP, data, reply); 209 210 const char *host = data.readCString(); 211 unsigned port = data.readInt32(); 212 213 reply->writeInt32(initAsync(host, port)); 214 return OK; 215 } 216 217 case HDCP_SHUTDOWN_ASYNC: 218 { 219 CHECK_INTERFACE(IHDCP, data, reply); 220 221 reply->writeInt32(shutdownAsync()); 222 return OK; 223 } 224 225 case HDCP_ENCRYPT: 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; 236 status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData); 237 238 reply->writeInt32(err); 239 240 if (err == OK) { 241 reply->writeInt64(inputCTR); 242 reply->write(outData, size); 243 } 244 245 free(inData); 246 inData = outData = NULL; 247 248 return OK; 249 } 250 251 case HDCP_ENCRYPT_NATIVE: 252 { 253 CHECK_INTERFACE(IHDCP, data, reply); 254 255 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 256 data.read(*graphicBuffer); 257 size_t offset = data.readInt32(); 258 size_t size = data.readInt32(); 259 uint32_t streamCTR = data.readInt32(); 260 void *outData = malloc(size); 261 uint64_t inputCTR; 262 263 status_t err = encryptNative(graphicBuffer, offset, size, 264 streamCTR, &inputCTR, outData); 265 266 reply->writeInt32(err); 267 268 if (err == OK) { 269 reply->writeInt64(inputCTR); 270 reply->write(outData, size); 271 } 272 273 free(outData); 274 outData = NULL; 275 276 return OK; 277 } 278 279 case HDCP_DECRYPT: 280 { 281 size_t size = data.readInt32(); 282 283 void *inData = malloc(2 * size); 284 void *outData = (uint8_t *)inData + size; 285 286 data.read(inData, size); 287 288 uint32_t streamCTR = data.readInt32(); 289 uint64_t inputCTR = data.readInt64(); 290 status_t err = decrypt(inData, size, streamCTR, inputCTR, outData); 291 292 reply->writeInt32(err); 293 294 if (err == OK) { 295 reply->write(outData, size); 296 } 297 298 free(inData); 299 inData = outData = NULL; 300 301 return OK; 302 } 303 304 default: 305 return BBinder::onTransact(code, data, reply, flags); 306 } 307} 308 309} // namespace android 310