blob: 7b702059bec7e749d377cb0e7a684a6b3bd505e3 [file] [log] [blame]
Andreas Hubered3e3e02012-03-26 11:13:27 -07001/*
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 "ICrypto"
19#include <utils/Log.h>
20
21#include <binder/Parcel.h>
Jeff Tinkerc481b502015-04-06 18:21:05 -070022#include <binder/IMemory.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070023#include <media/ICrypto.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070024#include <media/stagefright/MediaErrors.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070025#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070026#include <media/stagefright/foundation/AString.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070027
28namespace android {
29
30enum {
Andreas Huber1bd139a2012-04-03 14:19:20 -070031 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
32 IS_CRYPTO_SUPPORTED,
33 CREATE_PLUGIN,
34 DESTROY_PLUGIN,
35 REQUIRES_SECURE_COMPONENT,
36 DECRYPT,
Jeff Tinker2514d082014-11-03 13:29:35 -080037 NOTIFY_RESOLUTION,
Jeff Tinker18495702015-04-10 04:10:59 -070038 SET_MEDIADRM_SESSION,
Chong Zhangd07c9272017-03-28 11:02:06 -070039 SET_HEAP,
40 UNSET_HEAP,
Andreas Hubered3e3e02012-03-26 11:13:27 -070041};
42
43struct BpCrypto : public BpInterface<ICrypto> {
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070044 explicit BpCrypto(const sp<IBinder> &impl)
Andreas Hubered3e3e02012-03-26 11:13:27 -070045 : BpInterface<ICrypto>(impl) {
46 }
47
Andreas Huber1bd139a2012-04-03 14:19:20 -070048 virtual status_t initCheck() const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070049 Parcel data, reply;
50 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070051 remote()->transact(INIT_CHECK, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070052
53 return reply.readInt32();
54 }
55
Jeff Tinkerbafb6822013-03-22 15:26:39 -070056 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
Andreas Hubered3e3e02012-03-26 11:13:27 -070057 Parcel data, reply;
58 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070059 data.write(uuid, 16);
60 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
61
62 return reply.readInt32() != 0;
63 }
64
65 virtual status_t createPlugin(
66 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
67 Parcel data, reply;
68 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
69 data.write(uuid, 16);
70 data.writeInt32(opaqueSize);
Andreas Huber705868c2012-04-11 15:41:45 -070071
72 if (opaqueSize > 0) {
73 data.write(opaqueData, opaqueSize);
74 }
75
Andreas Huber1bd139a2012-04-03 14:19:20 -070076 remote()->transact(CREATE_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070077
78 return reply.readInt32();
79 }
80
Andreas Huber1bd139a2012-04-03 14:19:20 -070081 virtual status_t destroyPlugin() {
Andreas Hubered3e3e02012-03-26 11:13:27 -070082 Parcel data, reply;
83 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070084 remote()->transact(DESTROY_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070085
86 return reply.readInt32();
87 }
88
Andreas Huber1bd139a2012-04-03 14:19:20 -070089 virtual bool requiresSecureDecoderComponent(
90 const char *mime) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070091 Parcel data, reply;
92 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070093 data.writeCString(mime);
94 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070095
Andreas Huber1bd139a2012-04-03 14:19:20 -070096 return reply.readInt32() != 0;
Andreas Hubered3e3e02012-03-26 11:13:27 -070097 }
98
Jeff Tinkera53d6552017-01-20 00:31:46 -080099 virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800100 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
Jeff Tinkera53d6552017-01-20 00:31:46 -0800101 const sp<IMemory> &source, size_t offset,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700102 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
Jeff Tinkera53d6552017-01-20 00:31:46 -0800103 const DestinationBuffer &destination, AString *errorDetailMsg) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700104 Parcel data, reply;
105 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -0700106 data.writeInt32(mode);
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800107 data.writeInt32(pattern.mEncryptBlocks);
108 data.writeInt32(pattern.mSkipBlocks);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700109
110 static const uint8_t kDummy[16] = { 0 };
111
112 if (key == NULL) {
113 key = kDummy;
114 }
115
116 if (iv == NULL) {
117 iv = kDummy;
118 }
119
Andreas Huber1bd139a2012-04-03 14:19:20 -0700120 data.write(key, 16);
121 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700122
Andreas Huber1bd139a2012-04-03 14:19:20 -0700123 size_t totalSize = 0;
124 for (size_t i = 0; i < numSubSamples; ++i) {
125 totalSize += subSamples[i].mNumBytesOfEncryptedData;
126 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700127 }
128
Andreas Huber1bd139a2012-04-03 14:19:20 -0700129 data.writeInt32(totalSize);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800130 data.writeStrongBinder(IInterface::asBinder(source));
Jeff Tinkerc481b502015-04-06 18:21:05 -0700131 data.writeInt32(offset);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700132
Andreas Huber1bd139a2012-04-03 14:19:20 -0700133 data.writeInt32(numSubSamples);
134 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700135
Jeff Tinkera53d6552017-01-20 00:31:46 -0800136 data.writeInt32((int32_t)destination.mType);
137 if (destination.mType == kDestinationTypeNativeHandle) {
138 if (destination.mHandle == NULL) {
139 return BAD_VALUE;
140 }
141 data.writeNativeHandle(destination.mHandle);
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800142 } else {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800143 if (destination.mSharedMemory == NULL) {
144 return BAD_VALUE;
145 }
146 data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700147 }
148
Andreas Huber1bd139a2012-04-03 14:19:20 -0700149 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700150
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700151 ssize_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700152
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700153 if (isCryptoError(result)) {
Jeff Tinker0be134a2017-03-09 17:01:10 -0800154 AString msg = reply.readCString();
155 if (errorDetailMsg) {
156 *errorDetailMsg = msg;
157 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700158 }
159
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700160 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700161 }
162
Jeff Tinker2514d082014-11-03 13:29:35 -0800163 virtual void notifyResolution(
164 uint32_t width, uint32_t height) {
165 Parcel data, reply;
166 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
167 data.writeInt32(width);
168 data.writeInt32(height);
169 remote()->transact(NOTIFY_RESOLUTION, data, &reply);
170 }
171
Jeff Tinker18495702015-04-10 04:10:59 -0700172 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
173 Parcel data, reply;
174 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
175
176 writeVector(data, sessionId);
177 remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
178
179 return reply.readInt32();
180 }
181
Chong Zhangd07c9272017-03-28 11:02:06 -0700182 virtual void setHeap(const sp<IMemoryHeap> &heap) {
183 Parcel data, reply;
184 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
185 data.writeStrongBinder(IInterface::asBinder(heap));
186 remote()->transact(SET_HEAP, data, &reply);
187 return;
188 }
189
190 virtual void unsetHeap(const sp<IMemoryHeap>& heap) {
191 Parcel data, reply;
192 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
193 data.writeStrongBinder(IInterface::asBinder(heap));
194 remote()->transact(UNSET_HEAP, data, &reply);
195 return;
196 }
197
198
Andreas Hubered3e3e02012-03-26 11:13:27 -0700199private:
Jeff Tinker18495702015-04-10 04:10:59 -0700200 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
201 uint32_t size = reply.readInt32();
202 vector.insertAt((size_t)0, size);
203 reply.read(vector.editArray(), size);
204 }
205
206 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
207 data.writeInt32(vector.size());
208 data.write(vector.array(), vector.size());
209 }
210
Andreas Hubered3e3e02012-03-26 11:13:27 -0700211 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
212};
213
214IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
215
216////////////////////////////////////////////////////////////////////////////////
217
Jeff Tinker18495702015-04-10 04:10:59 -0700218void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
219 uint32_t size = data.readInt32();
220 vector.insertAt((size_t)0, size);
221 data.read(vector.editArray(), size);
222}
223
224void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
225 reply->writeInt32(vector.size());
226 reply->write(vector.array(), vector.size());
227}
228
Andreas Hubered3e3e02012-03-26 11:13:27 -0700229status_t BnCrypto::onTransact(
230 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
231 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700232 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700233 {
234 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700235 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700236
237 return OK;
238 }
239
Andreas Huber1bd139a2012-04-03 14:19:20 -0700240 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700241 {
242 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700243 uint8_t uuid[16];
244 data.read(uuid, sizeof(uuid));
245 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700246
247 return OK;
248 }
249
Andreas Huber1bd139a2012-04-03 14:19:20 -0700250 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700251 {
252 CHECK_INTERFACE(ICrypto, data, reply);
253
Andreas Huber1bd139a2012-04-03 14:19:20 -0700254 uint8_t uuid[16];
255 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700256
Andreas Huber1bd139a2012-04-03 14:19:20 -0700257 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700258 void *opaqueData = NULL;
259
Edwin Wong9247e102017-03-13 16:38:20 -0700260 const size_t kMaxOpaqueSize = 100 * 1024;
261 if (opaqueSize > kMaxOpaqueSize) {
262 return BAD_VALUE;
Andreas Huber705868c2012-04-11 15:41:45 -0700263 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700264
Edwin Wong9247e102017-03-13 16:38:20 -0700265 opaqueData = malloc(opaqueSize);
266 if (NULL == opaqueData) {
267 return NO_MEMORY;
268 }
269
270 data.read(opaqueData, opaqueSize);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700271 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
272
Edwin Wong9247e102017-03-13 16:38:20 -0700273 free(opaqueData);
274 opaqueData = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700275
276 return OK;
277 }
278
Andreas Huber1bd139a2012-04-03 14:19:20 -0700279 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700280 {
281 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700282 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700283
284 return OK;
285 }
286
Andreas Huber1bd139a2012-04-03 14:19:20 -0700287 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700288 {
289 CHECK_INTERFACE(ICrypto, data, reply);
290
Andreas Huber1bd139a2012-04-03 14:19:20 -0700291 const char *mime = data.readCString();
Wei Jia2afac0c2016-01-07 12:13:07 -0800292 if (mime == NULL) {
293 reply->writeInt32(BAD_VALUE);
294 } else {
295 reply->writeInt32(requiresSecureDecoderComponent(mime));
296 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700297
Andreas Huber1bd139a2012-04-03 14:19:20 -0700298 return OK;
299 }
300
301 case DECRYPT:
302 {
303 CHECK_INTERFACE(ICrypto, data, reply);
304
Andreas Huber1bd139a2012-04-03 14:19:20 -0700305 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800306 CryptoPlugin::Pattern pattern;
307 pattern.mEncryptBlocks = data.readInt32();
308 pattern.mSkipBlocks = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700309
310 uint8_t key[16];
311 data.read(key, sizeof(key));
312
313 uint8_t iv[16];
314 data.read(iv, sizeof(iv));
315
316 size_t totalSize = data.readInt32();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800317 sp<IMemory> source =
Jeff Tinkerc481b502015-04-06 18:21:05 -0700318 interface_cast<IMemory>(data.readStrongBinder());
Jeff Tinkera53d6552017-01-20 00:31:46 -0800319 if (source == NULL) {
Wei Jia2afac0c2016-01-07 12:13:07 -0800320 reply->writeInt32(BAD_VALUE);
321 return OK;
322 }
Jeff Tinkerc481b502015-04-06 18:21:05 -0700323 int32_t offset = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700324
325 int32_t numSubSamples = data.readInt32();
Jeff Tinker4183d532016-05-20 17:19:31 -0700326 if (numSubSamples < 0 || numSubSamples > 0xffff) {
327 reply->writeInt32(BAD_VALUE);
328 return OK;
329 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700330
331 CryptoPlugin::SubSample *subSamples =
Jeff Tinkera53d6552017-01-20 00:31:46 -0800332 new CryptoPlugin::SubSample[numSubSamples];
Andreas Huber1bd139a2012-04-03 14:19:20 -0700333
Jeff Tinkera53d6552017-01-20 00:31:46 -0800334 data.read(subSamples,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700335 sizeof(CryptoPlugin::SubSample) * numSubSamples);
336
Jeff Tinkera53d6552017-01-20 00:31:46 -0800337 DestinationBuffer destination;
338 destination.mType = (DestinationType)data.readInt32();
339 if (destination.mType == kDestinationTypeNativeHandle) {
340 destination.mHandle = data.readNativeHandle();
341 if (destination.mHandle == NULL) {
342 reply->writeInt32(BAD_VALUE);
343 return OK;
344 }
345 } else if (destination.mType == kDestinationTypeSharedMemory) {
346 destination.mSharedMemory =
347 interface_cast<IMemory>(data.readStrongBinder());
348 if (destination.mSharedMemory == NULL) {
349 reply->writeInt32(BAD_VALUE);
350 return OK;
351 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700352 }
353
Andreas Huber5b8987e2012-04-19 12:52:20 -0700354 AString errorDetailMsg;
Jeff Tinkerc481b502015-04-06 18:21:05 -0700355 ssize_t result;
356
Jeff Tinkerc6fc6a32015-08-26 20:22:39 -0700357 size_t sumSubsampleSizes = 0;
358 bool overflow = false;
359 for (int32_t i = 0; i < numSubSamples; ++i) {
360 CryptoPlugin::SubSample &ss = subSamples[i];
361 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
362 sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
363 } else {
364 overflow = true;
365 }
366 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
367 sumSubsampleSizes += ss.mNumBytesOfClearData;
368 } else {
369 overflow = true;
370 }
371 }
372
373 if (overflow || sumSubsampleSizes != totalSize) {
374 result = -EINVAL;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800375 } else if (totalSize > source->size()) {
Jeff Tinkerbb4877d2015-12-04 16:29:16 -0800376 result = -EINVAL;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800377 } else if ((size_t)offset > source->size() - totalSize) {
Jeff Tinkerc481b502015-04-06 18:21:05 -0700378 result = -EINVAL;
379 } else {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800380 result = decrypt(key, iv, mode, pattern, source, offset,
381 subSamples, numSubSamples, destination, &errorDetailMsg);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700382 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700383
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700384 reply->writeInt32(result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700385
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700386 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700387 reply->writeCString(errorDetailMsg.c_str());
388 }
389
Jeff Tinkera53d6552017-01-20 00:31:46 -0800390 if (destination.mType == kDestinationTypeNativeHandle) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800391 int err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800392 if ((err = native_handle_close(destination.mHandle)) < 0) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800393 ALOGW("secure buffer native_handle_close failed: %d", err);
394 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800395 if ((err = native_handle_delete(destination.mHandle)) < 0) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800396 ALOGW("secure buffer native_handle_delete failed: %d", err);
397 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700398 }
399
400 delete[] subSamples;
401 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700402
Andreas Hubered3e3e02012-03-26 11:13:27 -0700403 return OK;
404 }
405
Jeff Tinker2514d082014-11-03 13:29:35 -0800406 case NOTIFY_RESOLUTION:
407 {
408 CHECK_INTERFACE(ICrypto, data, reply);
409
410 int32_t width = data.readInt32();
411 int32_t height = data.readInt32();
412 notifyResolution(width, height);
413
414 return OK;
415 }
416
Jeff Tinker18495702015-04-10 04:10:59 -0700417 case SET_MEDIADRM_SESSION:
418 {
419 CHECK_INTERFACE(IDrm, data, reply);
420 Vector<uint8_t> sessionId;
421 readVector(data, sessionId);
422 reply->writeInt32(setMediaDrmSession(sessionId));
423 return OK;
424 }
425
Chong Zhangd07c9272017-03-28 11:02:06 -0700426 case SET_HEAP:
427 {
428 CHECK_INTERFACE(ICrypto, data, reply);
429 sp<IMemoryHeap> heap =
430 interface_cast<IMemoryHeap>(data.readStrongBinder());
431 setHeap(heap);
432 return OK;
433 }
434
435 case UNSET_HEAP:
436 {
437 CHECK_INTERFACE(ICrypto, data, reply);
438 sp<IMemoryHeap> heap =
439 interface_cast<IMemoryHeap>(data.readStrongBinder());
440 unsetHeap(heap);
441 return OK;
442 }
443
Andreas Hubered3e3e02012-03-26 11:13:27 -0700444 default:
445 return BBinder::onTransact(code, data, reply, flags);
446 }
447}
448
449} // namespace android