IDrm.cpp revision 0cb126a34fe32f81c830858102471e7be2ce85b1
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 "IDrm"
19#include <utils/Log.h>
20
21#include <binder/Parcel.h>
22#include <media/IDrm.h>
23#include <media/stagefright/MediaErrors.h>
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/foundation/AString.h>
26
27namespace android {
28
29enum {
30    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
31    IS_CRYPTO_SUPPORTED,
32    CREATE_PLUGIN,
33    DESTROY_PLUGIN,
34    OPEN_SESSION,
35    CLOSE_SESSION,
36    GET_KEY_REQUEST,
37    PROVIDE_KEY_RESPONSE,
38    REMOVE_KEYS,
39    RESTORE_KEYS,
40    QUERY_KEY_STATUS,
41    GET_PROVISION_REQUEST,
42    PROVIDE_PROVISION_RESPONSE,
43    GET_SECURE_STOPS,
44    RELEASE_SECURE_STOPS,
45    GET_PROPERTY_STRING,
46    GET_PROPERTY_BYTE_ARRAY,
47    SET_PROPERTY_STRING,
48    SET_PROPERTY_BYTE_ARRAY,
49    SET_CIPHER_ALGORITHM,
50    SET_MAC_ALGORITHM,
51    ENCRYPT,
52    DECRYPT,
53    SIGN,
54    VERIFY,
55    SET_LISTENER
56};
57
58struct BpDrm : public BpInterface<IDrm> {
59    BpDrm(const sp<IBinder> &impl)
60        : BpInterface<IDrm>(impl) {
61    }
62
63    virtual status_t initCheck() const {
64        Parcel data, reply;
65        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
66        remote()->transact(INIT_CHECK, data, &reply);
67
68        return reply.readInt32();
69    }
70
71    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
72        Parcel data, reply;
73        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
74        data.write(uuid, 16);
75        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
76
77        return reply.readInt32() != 0;
78    }
79
80    virtual status_t createPlugin(const uint8_t uuid[16]) {
81        Parcel data, reply;
82        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
83        data.write(uuid, 16);
84
85        remote()->transact(CREATE_PLUGIN, data, &reply);
86
87        return reply.readInt32();
88    }
89
90    virtual status_t destroyPlugin() {
91        Parcel data, reply;
92        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
93        remote()->transact(DESTROY_PLUGIN, data, &reply);
94
95        return reply.readInt32();
96    }
97
98    virtual status_t openSession(Vector<uint8_t> &sessionId) {
99        Parcel data, reply;
100        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
101
102        remote()->transact(OPEN_SESSION, data, &reply);
103        readVector(reply, sessionId);
104
105        return reply.readInt32();
106    }
107
108    virtual status_t closeSession(Vector<uint8_t> const &sessionId) {
109        Parcel data, reply;
110        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
111
112        writeVector(data, sessionId);
113        remote()->transact(CLOSE_SESSION, data, &reply);
114
115        return reply.readInt32();
116    }
117
118    virtual status_t
119        getKeyRequest(Vector<uint8_t> const &sessionId,
120                      Vector<uint8_t> const &initData,
121                      String8 const &mimeType, DrmPlugin::KeyType keyType,
122                      KeyedVector<String8, String8> const &optionalParameters,
123                      Vector<uint8_t> &request, String8 &defaultUrl) {
124        Parcel data, reply;
125        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
126
127        writeVector(data, sessionId);
128        writeVector(data, initData);
129        data.writeString8(mimeType);
130        data.writeInt32((uint32_t)keyType);
131
132        data.writeInt32(optionalParameters.size());
133        for (size_t i = 0; i < optionalParameters.size(); ++i) {
134            data.writeString8(optionalParameters.keyAt(i));
135            data.writeString8(optionalParameters.valueAt(i));
136        }
137        remote()->transact(GET_KEY_REQUEST, data, &reply);
138
139        readVector(reply, request);
140        defaultUrl = reply.readString8();
141
142        return reply.readInt32();
143    }
144
145    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
146                                        Vector<uint8_t> const &response,
147                                        Vector<uint8_t> &keySetId) {
148        Parcel data, reply;
149        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
150        writeVector(data, sessionId);
151        writeVector(data, response);
152        remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
153        readVector(reply, keySetId);
154
155        return reply.readInt32();
156    }
157
158    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
159        Parcel data, reply;
160        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
161
162        writeVector(data, keySetId);
163        remote()->transact(REMOVE_KEYS, data, &reply);
164
165        return reply.readInt32();
166    }
167
168    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
169                                 Vector<uint8_t> const &keySetId) {
170        Parcel data, reply;
171        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
172
173        writeVector(data, sessionId);
174        writeVector(data, keySetId);
175        remote()->transact(RESTORE_KEYS, data, &reply);
176
177        return reply.readInt32();
178    }
179
180    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
181                                        KeyedVector<String8, String8> &infoMap) const {
182        Parcel data, reply;
183        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
184
185        writeVector(data, sessionId);
186        remote()->transact(QUERY_KEY_STATUS, data, &reply);
187
188        infoMap.clear();
189        size_t count = reply.readInt32();
190        for (size_t i = 0; i < count; i++) {
191            String8 key = reply.readString8();
192            String8 value = reply.readString8();
193            infoMap.add(key, value);
194        }
195        return reply.readInt32();
196    }
197
198    virtual status_t getProvisionRequest(Vector<uint8_t> &request,
199                                         String8 &defaultUrl) {
200        Parcel data, reply;
201        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
202
203        remote()->transact(GET_PROVISION_REQUEST, data, &reply);
204
205        readVector(reply, request);
206        defaultUrl = reply.readString8();
207
208        return reply.readInt32();
209    }
210
211    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) {
212        Parcel data, reply;
213        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
214
215        writeVector(data, response);
216        remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
217
218        return reply.readInt32();
219    }
220
221    virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
222        Parcel data, reply;
223        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
224
225        remote()->transact(GET_SECURE_STOPS, data, &reply);
226
227        secureStops.clear();
228        uint32_t count = reply.readInt32();
229        for (size_t i = 0; i < count; i++) {
230            Vector<uint8_t> secureStop;
231            readVector(reply, secureStop);
232            secureStops.push_back(secureStop);
233        }
234        return reply.readInt32();
235    }
236
237    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
238        Parcel data, reply;
239        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
240
241        writeVector(data, ssRelease);
242        remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
243
244        return reply.readInt32();
245    }
246
247    virtual status_t getPropertyString(String8 const &name, String8 &value) const {
248        Parcel data, reply;
249        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
250
251        data.writeString8(name);
252        remote()->transact(GET_PROPERTY_STRING, data, &reply);
253
254        value = reply.readString8();
255        return reply.readInt32();
256    }
257
258    virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const {
259        Parcel data, reply;
260        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
261
262        data.writeString8(name);
263        remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
264
265        readVector(reply, value);
266        return reply.readInt32();
267    }
268
269    virtual status_t setPropertyString(String8 const &name, String8 const &value) const {
270        Parcel data, reply;
271        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
272
273        data.writeString8(name);
274        data.writeString8(value);
275        remote()->transact(SET_PROPERTY_STRING, data, &reply);
276
277        return reply.readInt32();
278    }
279
280    virtual status_t setPropertyByteArray(String8 const &name,
281                                          Vector<uint8_t> const &value) const {
282        Parcel data, reply;
283        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
284
285        data.writeString8(name);
286        writeVector(data, value);
287        remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
288
289        return reply.readInt32();
290    }
291
292
293    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
294                                        String8 const &algorithm) {
295        Parcel data, reply;
296        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
297
298        writeVector(data, sessionId);
299        data.writeString8(algorithm);
300        remote()->transact(SET_CIPHER_ALGORITHM, data, &reply);
301        return reply.readInt32();
302    }
303
304    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
305                                     String8 const &algorithm) {
306        Parcel data, reply;
307        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
308
309        writeVector(data, sessionId);
310        data.writeString8(algorithm);
311        remote()->transact(SET_MAC_ALGORITHM, data, &reply);
312        return reply.readInt32();
313    }
314
315    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
316                             Vector<uint8_t> const &keyId,
317                             Vector<uint8_t> const &input,
318                             Vector<uint8_t> const &iv,
319                             Vector<uint8_t> &output) {
320        Parcel data, reply;
321        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
322
323        writeVector(data, sessionId);
324        writeVector(data, keyId);
325        writeVector(data, input);
326        writeVector(data, iv);
327
328        remote()->transact(ENCRYPT, data, &reply);
329        readVector(reply, output);
330
331        return reply.readInt32();
332    }
333
334    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
335                             Vector<uint8_t> const &keyId,
336                             Vector<uint8_t> const &input,
337                             Vector<uint8_t> const &iv,
338                             Vector<uint8_t> &output) {
339        Parcel data, reply;
340        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
341
342        writeVector(data, sessionId);
343        writeVector(data, keyId);
344        writeVector(data, input);
345        writeVector(data, iv);
346
347        remote()->transact(DECRYPT, data, &reply);
348        readVector(reply, output);
349
350        return reply.readInt32();
351    }
352
353    virtual status_t sign(Vector<uint8_t> const &sessionId,
354                          Vector<uint8_t> const &keyId,
355                          Vector<uint8_t> const &message,
356                          Vector<uint8_t> &signature) {
357        Parcel data, reply;
358        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
359
360        writeVector(data, sessionId);
361        writeVector(data, keyId);
362        writeVector(data, message);
363
364        remote()->transact(SIGN, data, &reply);
365        readVector(reply, signature);
366
367        return reply.readInt32();
368    }
369
370    virtual status_t verify(Vector<uint8_t> const &sessionId,
371                            Vector<uint8_t> const &keyId,
372                            Vector<uint8_t> const &message,
373                            Vector<uint8_t> const &signature,
374                            bool &match) {
375        Parcel data, reply;
376        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
377
378        writeVector(data, sessionId);
379        writeVector(data, keyId);
380        writeVector(data, message);
381        writeVector(data, signature);
382
383        remote()->transact(VERIFY, data, &reply);
384        match = (bool)reply.readInt32();
385        return reply.readInt32();
386    }
387
388    virtual status_t setListener(const sp<IDrmClient>& listener) {
389        Parcel data, reply;
390        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
391        data.writeStrongBinder(listener->asBinder());
392        remote()->transact(SET_LISTENER, data, &reply);
393        return reply.readInt32();
394    }
395
396private:
397    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
398        uint32_t size = reply.readInt32();
399        vector.insertAt((size_t)0, size);
400        reply.read(vector.editArray(), size);
401    }
402
403    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
404        data.writeInt32(vector.size());
405        data.write(vector.array(), vector.size());
406    }
407
408    DISALLOW_EVIL_CONSTRUCTORS(BpDrm);
409};
410
411IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm");
412
413////////////////////////////////////////////////////////////////////////////////
414
415void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
416    uint32_t size = data.readInt32();
417    vector.insertAt((size_t)0, size);
418    data.read(vector.editArray(), size);
419}
420
421void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
422    reply->writeInt32(vector.size());
423    reply->write(vector.array(), vector.size());
424}
425
426status_t BnDrm::onTransact(
427    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
428    switch (code) {
429        case INIT_CHECK:
430        {
431            CHECK_INTERFACE(IDrm, data, reply);
432            reply->writeInt32(initCheck());
433            return OK;
434        }
435
436        case IS_CRYPTO_SUPPORTED:
437        {
438            CHECK_INTERFACE(IDrm, data, reply);
439            uint8_t uuid[16];
440            data.read(uuid, sizeof(uuid));
441            reply->writeInt32(isCryptoSchemeSupported(uuid));
442            return OK;
443        }
444
445        case CREATE_PLUGIN:
446        {
447            CHECK_INTERFACE(IDrm, data, reply);
448            uint8_t uuid[16];
449            data.read(uuid, sizeof(uuid));
450            reply->writeInt32(createPlugin(uuid));
451            return OK;
452        }
453
454        case DESTROY_PLUGIN:
455        {
456            CHECK_INTERFACE(IDrm, data, reply);
457            reply->writeInt32(destroyPlugin());
458            return OK;
459        }
460
461        case OPEN_SESSION:
462        {
463            CHECK_INTERFACE(IDrm, data, reply);
464            Vector<uint8_t> sessionId;
465            status_t result = openSession(sessionId);
466            writeVector(reply, sessionId);
467            reply->writeInt32(result);
468            return OK;
469        }
470
471        case CLOSE_SESSION:
472        {
473            CHECK_INTERFACE(IDrm, data, reply);
474            Vector<uint8_t> sessionId;
475            readVector(data, sessionId);
476            reply->writeInt32(closeSession(sessionId));
477            return OK;
478        }
479
480        case GET_KEY_REQUEST:
481        {
482            CHECK_INTERFACE(IDrm, data, reply);
483            Vector<uint8_t> sessionId, initData;
484
485            readVector(data, sessionId);
486            readVector(data, initData);
487            String8 mimeType = data.readString8();
488            DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
489
490            KeyedVector<String8, String8> optionalParameters;
491            uint32_t count = data.readInt32();
492            for (size_t i = 0; i < count; ++i) {
493                String8 key, value;
494                key = data.readString8();
495                value = data.readString8();
496                optionalParameters.add(key, value);
497            }
498
499            Vector<uint8_t> request;
500            String8 defaultUrl;
501
502            status_t result = getKeyRequest(sessionId, initData,
503                                            mimeType, keyType,
504                                            optionalParameters,
505                                            request, defaultUrl);
506            writeVector(reply, request);
507            reply->writeString8(defaultUrl);
508            reply->writeInt32(result);
509            return OK;
510        }
511
512        case PROVIDE_KEY_RESPONSE:
513        {
514            CHECK_INTERFACE(IDrm, data, reply);
515            Vector<uint8_t> sessionId, response, keySetId;
516            readVector(data, sessionId);
517            readVector(data, response);
518            uint32_t result = provideKeyResponse(sessionId, response, keySetId);
519            writeVector(reply, keySetId);
520            reply->writeInt32(result);
521            return OK;
522        }
523
524        case REMOVE_KEYS:
525        {
526            CHECK_INTERFACE(IDrm, data, reply);
527            Vector<uint8_t> keySetId;
528            readVector(data, keySetId);
529            reply->writeInt32(removeKeys(keySetId));
530            return OK;
531        }
532
533        case RESTORE_KEYS:
534        {
535            CHECK_INTERFACE(IDrm, data, reply);
536            Vector<uint8_t> sessionId, keySetId;
537            readVector(data, sessionId);
538            readVector(data, keySetId);
539            reply->writeInt32(restoreKeys(sessionId, keySetId));
540            return OK;
541        }
542
543        case QUERY_KEY_STATUS:
544        {
545            CHECK_INTERFACE(IDrm, data, reply);
546            Vector<uint8_t> sessionId;
547            readVector(data, sessionId);
548            KeyedVector<String8, String8> infoMap;
549            status_t result = queryKeyStatus(sessionId, infoMap);
550            size_t count = infoMap.size();
551            reply->writeInt32(count);
552            for (size_t i = 0; i < count; ++i) {
553                reply->writeString8(infoMap.keyAt(i));
554                reply->writeString8(infoMap.valueAt(i));
555            }
556            reply->writeInt32(result);
557            return OK;
558        }
559
560        case GET_PROVISION_REQUEST:
561        {
562            CHECK_INTERFACE(IDrm, data, reply);
563            Vector<uint8_t> request;
564            String8 defaultUrl;
565            status_t result = getProvisionRequest(request, defaultUrl);
566            writeVector(reply, request);
567            reply->writeString8(defaultUrl);
568            reply->writeInt32(result);
569            return OK;
570        }
571
572        case PROVIDE_PROVISION_RESPONSE:
573        {
574            CHECK_INTERFACE(IDrm, data, reply);
575            Vector<uint8_t> response;
576            readVector(data, response);
577            reply->writeInt32(provideProvisionResponse(response));
578            return OK;
579        }
580
581        case GET_SECURE_STOPS:
582        {
583            CHECK_INTERFACE(IDrm, data, reply);
584            List<Vector<uint8_t> > secureStops;
585            status_t result = getSecureStops(secureStops);
586            size_t count = secureStops.size();
587            reply->writeInt32(count);
588            List<Vector<uint8_t> >::iterator iter = secureStops.begin();
589            while(iter != secureStops.end()) {
590                size_t size = iter->size();
591                reply->writeInt32(size);
592                reply->write(iter->array(), iter->size());
593            }
594            reply->writeInt32(result);
595            return OK;
596        }
597
598        case RELEASE_SECURE_STOPS:
599        {
600            CHECK_INTERFACE(IDrm, data, reply);
601            Vector<uint8_t> ssRelease;
602            readVector(data, ssRelease);
603            reply->writeInt32(releaseSecureStops(ssRelease));
604            return OK;
605        }
606
607        case GET_PROPERTY_STRING:
608        {
609            CHECK_INTERFACE(IDrm, data, reply);
610            String8 name = data.readString8();
611            String8 value;
612            status_t result = getPropertyString(name, value);
613            reply->writeString8(value);
614            reply->writeInt32(result);
615            return OK;
616        }
617
618        case GET_PROPERTY_BYTE_ARRAY:
619        {
620            CHECK_INTERFACE(IDrm, data, reply);
621            String8 name = data.readString8();
622            Vector<uint8_t> value;
623            status_t result = getPropertyByteArray(name, value);
624            writeVector(reply, value);
625            reply->writeInt32(result);
626            return OK;
627        }
628
629        case SET_PROPERTY_STRING:
630        {
631            CHECK_INTERFACE(IDrm, data, reply);
632            String8 name = data.readString8();
633            String8 value = data.readString8();
634            reply->writeInt32(setPropertyString(name, value));
635            return OK;
636        }
637
638        case SET_PROPERTY_BYTE_ARRAY:
639        {
640            CHECK_INTERFACE(IDrm, data, reply);
641            String8 name = data.readString8();
642            Vector<uint8_t> value;
643            readVector(data, value);
644            reply->writeInt32(setPropertyByteArray(name, value));
645            return OK;
646        }
647
648        case SET_CIPHER_ALGORITHM:
649        {
650            CHECK_INTERFACE(IDrm, data, reply);
651            Vector<uint8_t> sessionId;
652            readVector(data, sessionId);
653            String8 algorithm = data.readString8();
654            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
655            return OK;
656        }
657
658        case SET_MAC_ALGORITHM:
659        {
660            CHECK_INTERFACE(IDrm, data, reply);
661            Vector<uint8_t> sessionId;
662            readVector(data, sessionId);
663            String8 algorithm = data.readString8();
664            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
665            return OK;
666        }
667
668        case ENCRYPT:
669        {
670            CHECK_INTERFACE(IDrm, data, reply);
671            Vector<uint8_t> sessionId, keyId, input, iv, output;
672            readVector(data, sessionId);
673            readVector(data, keyId);
674            readVector(data, input);
675            readVector(data, iv);
676            uint32_t result = encrypt(sessionId, keyId, input, iv, output);
677            writeVector(reply, output);
678            reply->writeInt32(result);
679            return OK;
680        }
681
682        case DECRYPT:
683        {
684            CHECK_INTERFACE(IDrm, data, reply);
685            Vector<uint8_t> sessionId, keyId, input, iv, output;
686            readVector(data, sessionId);
687            readVector(data, keyId);
688            readVector(data, input);
689            readVector(data, iv);
690            uint32_t result = decrypt(sessionId, keyId, input, iv, output);
691            writeVector(reply, output);
692            reply->writeInt32(result);
693            return OK;
694        }
695
696        case SIGN:
697        {
698            CHECK_INTERFACE(IDrm, data, reply);
699            Vector<uint8_t> sessionId, keyId, message, signature;
700            readVector(data, sessionId);
701            readVector(data, keyId);
702            readVector(data, message);
703            uint32_t result = sign(sessionId, keyId, message, signature);
704            writeVector(reply, signature);
705            reply->writeInt32(result);
706            return OK;
707        }
708
709        case VERIFY:
710        {
711            CHECK_INTERFACE(IDrm, data, reply);
712            Vector<uint8_t> sessionId, keyId, message, signature;
713            readVector(data, sessionId);
714            readVector(data, keyId);
715            readVector(data, message);
716            readVector(data, signature);
717            bool match;
718            uint32_t result = verify(sessionId, keyId, message, signature, match);
719            reply->writeInt32(match);
720            reply->writeInt32(result);
721            return OK;
722        }
723
724    case SET_LISTENER: {
725        CHECK_INTERFACE(IDrm, data, reply);
726        sp<IDrmClient> listener =
727            interface_cast<IDrmClient>(data.readStrongBinder());
728        reply->writeInt32(setListener(listener));
729        return NO_ERROR;
730    } break;
731
732    default:
733        return BBinder::onTransact(code, data, reply, flags);
734    }
735}
736
737}  // namespace android
738
739