199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten/*
265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Copyright (C) 2012 The Android Open Source Project
365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * you may not use this file except in compliance with the License.
665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * You may obtain a copy of the License at
765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Unless required by applicable law or agreed to in writing, software
1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * See the License for the specific language governing permissions and
1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * limitations under the License.
1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */
1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//#define LOG_NDEBUG 0
1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define LOG_TAG "IHDCP"
1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/Log.h>
2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/Parcel.h>
2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/IHDCP.h>
2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/stagefright/MediaErrors.h>
2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/stagefright/foundation/ADebug.h>
254ff14bae91075eb274eb1c2975982358946e7e63John Grossman
264ff14bae91075eb274eb1c2975982358946e7e63John Grossmannamespace android {
2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianenum {
2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    OBSERVER_NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    HDCP_SET_OBSERVER,
31335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kasten    HDCP_INIT_ASYNC,
324ff14bae91075eb274eb1c2975982358946e7e63John Grossman    HDCP_SHUTDOWN_ASYNC,
3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    HDCP_ENCRYPT,
3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian};
3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstruct BpHDCPObserver : public BpInterface<IHDCPObserver> {
3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    BpHDCPObserver(const sp<IBinder> &impl)
38799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin        : BpInterface<IHDCPObserver>(impl) {
3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
415462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian    virtual void notify(
425462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian            int msg, int ext1, int ext2, const Parcel *obj) {
435462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian        Parcel data, reply;
4464760240f931714858a59c1579f07264d7182ba2Dima Zavin        data.writeInterfaceToken(IHDCPObserver::getInterfaceDescriptor());
457394a4f358fa9908a9f0a7c954b65c399f4268e6Dima Zavin        data.writeInt32(msg);
46a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent        data.writeInt32(ext1);
4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        data.writeInt32(ext2);
4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (obj && obj->dataSize() > 0) {
4958912562617941964939a4182cda71eaeb153d4bGlenn Kasten            data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
5058912562617941964939a4182cda71eaeb153d4bGlenn Kasten        }
5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        remote()->transact(OBSERVER_NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
52feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent    }
53feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent};
5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianIMPLEMENT_META_INTERFACE(HDCPObserver, "android.hardware.IHDCPObserver");
5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstruct BpHDCP : public BpInterface<IHDCP> {
5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    BpHDCP(const sp<IBinder> &impl)
5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        : BpInterface<IHDCP>(impl) {
6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
6158912562617941964939a4182cda71eaeb153d4bGlenn Kasten
6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    virtual status_t setObserver(const sp<IHDCPObserver> &observer) {
6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        Parcel data, reply;
6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
6553d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        data.writeStrongBinder(observer->asBinder());
6653d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        remote()->transact(HDCP_SET_OBSERVER, data, &reply);
6753d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        return reply.readInt32();
6853d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten    }
6953d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten
7053d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten    virtual status_t initAsync(const char *host, unsigned port) {
7153d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        Parcel data, reply;
7253d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
7353d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten        data.writeCString(host);
744ff14bae91075eb274eb1c2975982358946e7e63John Grossman        data.writeInt32(port);
7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        remote()->transact(HDCP_INIT_ASYNC, data, &reply);
765462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian        return reply.readInt32();
775462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian    }
785462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian
7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    virtual status_t shutdownAsync() {
801998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten        Parcel data, reply;
8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
8254c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten        remote()->transact(HDCP_SHUTDOWN_ASYNC, data, &reply);
8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return reply.readInt32();
8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
862f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten    virtual status_t encrypt(
8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            const void *inData, size_t size, uint32_t streamCTR,
8865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            uint64_t *outInputCTR, void *outData) {
89fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        Parcel data, reply;
9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
9158f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        data.writeInt32(size);
920d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi        data.write(inData, size);
9365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        data.writeInt32(streamCTR);
94a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten        remote()->transact(HDCP_ENCRYPT, data, &reply);
9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
9672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        status_t err = reply.readInt32();
973acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten
9865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (err != OK) {
9965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            *outInputCTR = 0;
10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1012f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten            return err;
1022f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten        }
1032f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten
1042f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten        *outInputCTR = reply.readInt64();
1052f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten        reply.read(outData, size);
1062f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten
1072f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten        return err;
108a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten    }
1092f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten};
1102f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten
1112f732eb768004c6362fae8a02c60b69c9400b032Glenn KastenIMPLEMENT_META_INTERFACE(HDCP, "android.hardware.IHDCP");
11272ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten
11372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kastenstatus_t BnHDCPObserver::onTransact(
11472ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
11572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten    switch (code) {
11672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        case OBSERVER_NOTIFY:
11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        {
11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            CHECK_INTERFACE(IHDCPObserver, data, reply);
11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            int msg = data.readInt32();
12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            int ext1 = data.readInt32();
1224ff14bae91075eb274eb1c2975982358946e7e63John Grossman            int ext2 = data.readInt32();
12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            Parcel obj;
12572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            if (data.dataAvail() > 0) {
12672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten                obj.appendFrom(
127fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten                        const_cast<Parcel *>(&data),
12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        data.dataPosition(),
12972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten                        data.dataAvail());
13072ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            }
131fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten
13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            notify(msg, ext1, ext2, &obj);
133f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten
13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return OK;
13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
13765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        default:
13872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            return BBinder::onTransact(code, data, reply, flags);
13972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten    }
14065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t BnHDCP::onTransact(
143f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten        uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    switch (code) {
145a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent        case HDCP_SET_OBSERVER:
146a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent        {
147a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent            CHECK_INTERFACE(IHDCP, data, reply);
148a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent
149a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent            sp<IHDCPObserver> observer =
150a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent                interface_cast<IHDCPObserver>(data.readStrongBinder());
1510ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent
15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            reply->writeInt32(setObserver(observer));
15372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            return OK;
15472ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        }
15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
15672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        case HDCP_INIT_ASYNC:
15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        {
15872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            CHECK_INTERFACE(IHDCP, data, reply);
15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
16072ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            const char *host = data.readCString();
16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            unsigned port = data.readInt32();
162a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent
163a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent            reply->writeInt32(initAsync(host, port));
164a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent            return OK;
165a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent        }
166a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent
16765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case HDCP_SHUTDOWN_ASYNC:
16872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        {
16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            CHECK_INTERFACE(IHDCP, data, reply);
17072ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten
17165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            reply->writeInt32(shutdownAsync());
17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return OK;
17365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
17472ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten
17572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten        case HDCP_ENCRYPT:
17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        {
1772f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten            size_t size = data.readInt32();
1782f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten
17965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            void *inData = malloc(2 * size);
18065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            void *outData = (uint8_t *)inData + size;
1813a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
1823a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen            data.read(inData, size);
1833a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
1843a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen            uint32_t streamCTR = data.readInt32();
185f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten            uint64_t inputCTR;
18665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData);
187f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten
18865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            reply->writeInt32(err);
1895e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kasten
190f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten            if (err == OK) {
19165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                reply->writeInt64(inputCTR);
19265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                reply->write(outData, size);
19365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
19465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
19565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            free(inData);
19672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            inData = outData = NULL;
19765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
19865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return OK;
19965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
20065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
20165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        default:
20272ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten            return BBinder::onTransact(code, data, reply, flags);
20372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten    }
20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
205a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent
206a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent}  // namespace android
20765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian