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