• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 "ClearKeyDrmPlugin"
19 #include <utils/Log.h>
20 
21 #include <media/stagefright/MediaErrors.h>
22 #include <utils/StrongPointer.h>
23 
24 #include "DrmPlugin.h"
25 #include "ClearKeyDrmProperties.h"
26 #include "Session.h"
27 
28 namespace {
29 const android::String8 kStreaming("Streaming");
30 const android::String8 kOffline("Offline");
31 const android::String8 kTrue("True");
32 
33 const android::String8 kQueryKeyLicenseType("LicenseType");
34     // Value: "Streaming" or "Offline"
35 const android::String8 kQueryKeyPlayAllowed("PlayAllowed");
36     // Value: "True" or "False"
37 const android::String8 kQueryKeyRenewAllowed("RenewAllowed");
38     // Value: "True" or "False"
39 };
40 
41 namespace clearkeydrm {
42 
43 using android::sp;
44 
DrmPlugin(SessionLibrary * sessionLibrary)45 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
46         : mSessionLibrary(sessionLibrary) {
47 
48     mPlayPolicy.clear();
49     initProperties();
50 }
51 
initProperties()52 void DrmPlugin::initProperties() {
53     mStringProperties.clear();
54     mStringProperties.add(kVendorKey, kVendorValue);
55     mStringProperties.add(kVersionKey, kVersionValue);
56     mStringProperties.add(kPluginDescriptionKey, kPluginDescriptionValue);
57     mStringProperties.add(kAlgorithmsKey, kAlgorithmsValue);
58     mStringProperties.add(kListenerTestSupportKey, kListenerTestSupportValue);
59 
60     Vector<uint8_t> testDeviceId;
61     testDeviceId.appendArray(kTestDeviceIdData, sizeof(kTestDeviceIdData) / sizeof(uint8_t));
62     mByteArrayProperties.add(kDeviceIdKey, testDeviceId);
63 }
64 
openSession(Vector<uint8_t> & sessionId)65 status_t DrmPlugin::openSession(Vector<uint8_t>& sessionId) {
66     sp<Session> session = mSessionLibrary->createSession();
67     sessionId = session->sessionId();
68     return android::OK;
69 }
70 
closeSession(const Vector<uint8_t> & sessionId)71 status_t DrmPlugin::closeSession(const Vector<uint8_t>& sessionId) {
72     sp<Session> session = mSessionLibrary->findSession(sessionId);
73     if (sessionId.size() == 0) {
74         return android::BAD_VALUE;
75     }
76     if (session.get()) {
77         mSessionLibrary->destroySession(session);
78         return android::OK;
79     }
80     return android::ERROR_DRM_SESSION_NOT_OPENED;
81 }
82 
getKeyRequest(const Vector<uint8_t> & scope,const Vector<uint8_t> & initData,const String8 & mimeType,KeyType keyType,const KeyedVector<String8,String8> & optionalParameters,Vector<uint8_t> & request,String8 & defaultUrl,DrmPlugin::KeyRequestType * keyRequestType)83 status_t DrmPlugin::getKeyRequest(
84         const Vector<uint8_t>& scope,
85         const Vector<uint8_t>& initData,
86         const String8& mimeType,
87         KeyType keyType,
88         const KeyedVector<String8, String8>& optionalParameters,
89         Vector<uint8_t>& request,
90         String8& defaultUrl,
91         DrmPlugin::KeyRequestType *keyRequestType) {
92     UNUSED(optionalParameters);
93     if (scope.size() == 0) {
94         return android::BAD_VALUE;
95     }
96 
97     if (keyType != kKeyType_Streaming) {
98         return android::ERROR_DRM_CANNOT_HANDLE;
99     }
100 
101     *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
102     defaultUrl.clear();
103     sp<Session> session = mSessionLibrary->findSession(scope);
104     if (!session.get()) {
105         return android::ERROR_DRM_SESSION_NOT_OPENED;
106     }
107 
108     return session->getKeyRequest(initData, mimeType, &request);
109 }
110 
setPlayPolicy()111 void DrmPlugin::setPlayPolicy() {
112     android::Mutex::Autolock lock(mPlayPolicyLock);
113     mPlayPolicy.clear();
114     mPlayPolicy.add(kQueryKeyLicenseType, kStreaming);
115     mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue);
116     mPlayPolicy.add(kQueryKeyRenewAllowed, kTrue);
117 }
118 
provideKeyResponse(const Vector<uint8_t> & scope,const Vector<uint8_t> & response,Vector<uint8_t> & keySetId)119 status_t DrmPlugin::provideKeyResponse(
120         const Vector<uint8_t>& scope,
121         const Vector<uint8_t>& response,
122         Vector<uint8_t>& keySetId) {
123     if (scope.size() == 0 || response.size() == 0) {
124         return android::BAD_VALUE;
125     }
126     sp<Session> session = mSessionLibrary->findSession(scope);
127     if (!session.get()) {
128         return android::ERROR_DRM_SESSION_NOT_OPENED;
129     }
130 
131     setPlayPolicy();
132     status_t res = session->provideKeyResponse(response);
133     if (res == android::OK) {
134         // This is for testing AMediaDrm_setOnEventListener only.
135         sendEvent(kDrmPluginEventVendorDefined, 0, &scope, NULL);
136         keySetId.clear();
137     }
138     return res;
139 }
140 
getPropertyByteArray(const String8 & name,Vector<uint8_t> & value) const141 status_t DrmPlugin::getPropertyByteArray(
142         const String8& name, Vector<uint8_t>& value) const {
143     ssize_t index = mByteArrayProperties.indexOfKey(name);
144     if (index < 0) {
145         ALOGE("App requested unknown property: %s", name.string());
146         return android::ERROR_DRM_CANNOT_HANDLE;
147     }
148     value = mByteArrayProperties.valueAt(index);
149     return android::OK;
150 }
151 
setPropertyByteArray(const String8 & name,const Vector<uint8_t> & value)152 status_t DrmPlugin::setPropertyByteArray(
153         const String8& name, const Vector<uint8_t>& value)
154 {
155     UNUSED(value);
156     if (0 == name.compare(kDeviceIdKey)) {
157         ALOGD("Cannot set immutable property: %s", name.string());
158         return android::ERROR_DRM_CANNOT_HANDLE;
159     }
160 
161     // Setting of undefined properties is not supported
162     ALOGE("Failed to set property byte array, key=%s", name.string());
163     return android::ERROR_DRM_CANNOT_HANDLE;
164 }
165 
getPropertyString(const String8 & name,String8 & value) const166 status_t DrmPlugin::getPropertyString(
167         const String8& name, String8& value) const {
168     ssize_t index = mStringProperties.indexOfKey(name);
169     if (index < 0) {
170         ALOGE("App requested unknown property: %s", name.string());
171         return android::ERROR_DRM_CANNOT_HANDLE;
172     }
173     value = mStringProperties.valueAt(index);
174     return android::OK;
175 }
176 
setPropertyString(const String8 & name,const String8 & value)177 status_t DrmPlugin::setPropertyString(
178         const String8& name, const String8& value) {
179     String8 immutableKeys;
180     immutableKeys.appendFormat("%s,%s,%s,%s",
181             kAlgorithmsKey.string(), kPluginDescriptionKey.string(),
182             kVendorKey.string(), kVersionKey.string());
183     if (immutableKeys.contains(name.string())) {
184         ALOGD("Cannot set immutable property: %s", name.string());
185         return android::ERROR_DRM_CANNOT_HANDLE;
186     }
187 
188     ssize_t index = mStringProperties.indexOfKey(name);
189     if (index < 0) {
190         ALOGE("Cannot set undefined property string, key=%s", name.string());
191         return android::ERROR_DRM_CANNOT_HANDLE;
192     }
193 
194     if (mStringProperties.add(name, value) < 0) {
195         ALOGE("Failed to set property string, key=%s", name.string());
196         return android::ERROR_DRM_UNKNOWN;
197     }
198     return android::OK;
199 }
200 
queryKeyStatus(const Vector<uint8_t> & sessionId,KeyedVector<String8,String8> & infoMap) const201 status_t DrmPlugin::queryKeyStatus(
202         const Vector<uint8_t>& sessionId,
203         KeyedVector<String8, String8>& infoMap) const {
204 
205     if (sessionId.size() == 0) {
206         return android::BAD_VALUE;
207     }
208 
209     infoMap.clear();
210     android::Mutex::Autolock lock(mPlayPolicyLock);
211     for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
212         infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i));
213     }
214     return android::OK;
215 }
216 }  // namespace clearkeydrm
217