DrmPlugin.cpp revision 56134cc9e790f39b3b10a18b701b0607c20b6154
1/*
2 * Copyright (C) 2018 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 "hidl_ClearKeyPlugin"
19#include <utils/Log.h>
20
21#include <stdio.h>
22
23#include "DrmPlugin.h"
24#include "ClearKeyDrmProperties.h"
25#include "Session.h"
26#include "TypeConvert.h"
27
28namespace {
29const std::string kStreaming("Streaming");
30const std::string kOffline("Offline");
31const std::string kTrue("True");
32
33const std::string kQueryKeyLicenseType("LicenseType");
34    // Value: "Streaming" or "Offline"
35const std::string kQueryKeyPlayAllowed("PlayAllowed");
36    // Value: "True" or "False"
37const std::string kQueryKeyRenewAllowed("RenewAllowed");
38    // Value: "True" or "False"
39};
40
41namespace android {
42namespace hardware {
43namespace drm {
44namespace V1_1 {
45namespace clearkey {
46
47DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
48        : mSessionLibrary(sessionLibrary),
49          mOpenSessionOkCount(0),
50          mCloseSessionOkCount(0),
51          mCloseSessionNotOpenedCount(0) {
52    mPlayPolicy.clear();
53    initProperties();
54}
55
56void DrmPlugin::initProperties() {
57    mStringProperties.clear();
58    mStringProperties[kVendorKey] = kVendorValue;
59    mStringProperties[kVersionKey] = kVersionValue;
60    mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
61    mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
62    mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
63
64    std::vector<uint8_t> valueVector;
65    valueVector.clear();
66    valueVector.insert(valueVector.end(),
67            kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
68    mByteArrayProperties[kDeviceIdKey] = valueVector;
69
70    valueVector.clear();
71    valueVector.insert(valueVector.end(),
72            kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
73    mByteArrayProperties[kMetricsKey] = valueVector;
74}
75
76
77Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
78    sp<Session> session = mSessionLibrary->createSession();
79    std::vector<uint8_t> sessionId = session->sessionId();
80
81    Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
82    _hidl_cb(status, toHidlVec(sessionId));
83    mOpenSessionOkCount++;
84    return Void();
85}
86
87Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
88        openSession_1_1_cb _hidl_cb) {
89    sp<Session> session = mSessionLibrary->createSession();
90    std::vector<uint8_t> sessionId = session->sessionId();
91
92    Status status = setSecurityLevel(sessionId, securityLevel);
93    _hidl_cb(status, toHidlVec(sessionId));
94    mOpenSessionOkCount++;
95    return Void();
96}
97
98Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
99    if (sessionId.size() == 0) {
100        return Status::BAD_VALUE;
101    }
102
103    sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
104    if (session.get()) {
105        mCloseSessionOkCount++;
106        mSessionLibrary->destroySession(session);
107        return Status::OK;
108    }
109    mCloseSessionNotOpenedCount++;
110    return Status::ERROR_DRM_SESSION_NOT_OPENED;
111}
112
113Return<void> DrmPlugin::getKeyRequest(
114        const hidl_vec<uint8_t>& scope,
115        const hidl_vec<uint8_t>& initData,
116        const hidl_string& mimeType,
117        KeyType keyType,
118        const hidl_vec<KeyValue>& optionalParameters,
119        getKeyRequest_cb _hidl_cb) {
120    UNUSED(optionalParameters);
121
122    if (scope.size() == 0) {
123        // Returns empty keyRequest, unknown keyType and empty defaultUrl
124        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(),
125                KeyRequestType::UNKNOWN, "");
126        return Void();
127    }
128
129    if (keyType != KeyType::STREAMING) {
130        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(),
131                KeyRequestType::UNKNOWN, "");
132        return Void();
133    }
134
135    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
136    if (!session.get()) {
137        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>(),
138                KeyRequestType::UNKNOWN, "");
139        return Void();
140    }
141
142    std::vector<uint8_t> request;
143    Status status = session->getKeyRequest(initData, mimeType, &request);
144    _hidl_cb(status, toHidlVec(request), KeyRequestType::INITIAL, "");
145    return Void();
146}
147
148Return<void> DrmPlugin::getKeyRequest_1_1(
149        const hidl_vec<uint8_t>& scope,
150        const hidl_vec<uint8_t>& initData,
151        const hidl_string& mimeType,
152        KeyType keyType,
153        const hidl_vec<KeyValue>& optionalParameters,
154        getKeyRequest_1_1_cb _hidl_cb) {
155    hidl_string defaultUrl;
156    hidl_vec<uint8_t> request;
157    ::android::hardware::drm::V1_1::KeyRequestType requestType =
158            static_cast<::android::hardware::drm::V1_1::KeyRequestType>(KeyRequestType::UNKNOWN);
159    Status status = Status::OK;
160
161    defaultUrl.clear();
162    getKeyRequest(scope, initData, mimeType, keyType, optionalParameters,
163            [&](Status statusCode, const hidl_vec<uint8_t>& hResult,
164            KeyRequestType hKeyRequestType,
165            const hidl_string& hDefaultUrl) {
166        defaultUrl = hDefaultUrl;
167        request = hResult;
168        requestType = static_cast<::android::hardware::drm::V1_1::KeyRequestType>(hKeyRequestType);
169        status = statusCode;
170    });
171    _hidl_cb(status, request, requestType, defaultUrl);
172    return Void();
173}
174
175void DrmPlugin::setPlayPolicy() {
176    mPlayPolicy.clear();
177
178    KeyValue policy;
179    policy.key = kQueryKeyLicenseType;
180    policy.value = kStreaming;
181    mPlayPolicy.push_back(policy);
182
183    policy.key = kQueryKeyPlayAllowed;
184    policy.value = kTrue;
185    mPlayPolicy.push_back(policy);
186
187    policy.key = kQueryKeyRenewAllowed;
188    mPlayPolicy.push_back(policy);
189}
190
191Return<void> DrmPlugin::provideKeyResponse(
192        const hidl_vec<uint8_t>& scope,
193        const hidl_vec<uint8_t>& response,
194        provideKeyResponse_cb _hidl_cb) {
195    if (scope.size() == 0 || response.size() == 0) {
196        // Returns empty keySetId
197        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
198        return Void();
199    }
200    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
201    if (!session.get()) {
202        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
203        return Void();
204    }
205
206    setPlayPolicy();
207    std::vector<uint8_t> keySetId;
208    Status status = session->provideKeyResponse(response);
209    if (status == Status::OK) {
210        // This is for testing AMediaDrm_setOnEventListener only.
211        sendEvent(EventType::VENDOR_DEFINED, 0, scope);
212        keySetId.clear();
213    }
214
215    // Returns status and empty keySetId
216    _hidl_cb(status, toHidlVec(keySetId));
217    return Void();
218}
219
220Return<void> DrmPlugin::getPropertyString(
221        const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
222    std::string name(propertyName.c_str());
223    std::string value;
224
225    if (name == "vendor") {
226        value = "Google";
227    } else if (name == "version") {
228        value = "1.1";
229    } else if (name == "description") {
230        value = "ClearKey CDM";
231    } else if (name == "algorithms") {
232        value = "";
233    } else if (name == "listenerTestSupport") {
234        value = mStringProperties[name];
235    } else {
236        ALOGE("App requested unknown string property %s", name.c_str());
237        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
238        return Void();
239    }
240    _hidl_cb(Status::OK, value.c_str());
241    return Void();
242}
243
244Return<void> DrmPlugin::getPropertyByteArray(
245        const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
246    std::map<std::string, std::vector<uint8_t> >::iterator itr =
247            mByteArrayProperties.find(std::string(propertyName.c_str()));
248    if (itr == mByteArrayProperties.end()) {
249        ALOGE("App requested unknown property: %s", propertyName.c_str());
250        _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
251        return Void();
252    }
253    _hidl_cb(Status::OK, itr->second);
254    return Void();
255
256}
257
258Return<Status> DrmPlugin::setPropertyString(
259    const hidl_string& name, const hidl_string& value) {
260    std::string immutableKeys;
261    immutableKeys.append(kAlgorithmsKey + ",");
262    immutableKeys.append(kPluginDescriptionKey + ",");
263    immutableKeys.append(kVendorKey + ",");
264    immutableKeys.append(kVersionKey + ",");
265
266    std::string key = std::string(name.c_str());
267    if (immutableKeys.find(key) != std::string::npos) {
268        ALOGD("Cannot set immutable property: %s", key.c_str());
269        return Status::BAD_VALUE;
270    }
271
272    std::map<std::string, std::string>::iterator itr =
273            mStringProperties.find(key);
274    if (itr == mStringProperties.end()) {
275        ALOGE("Cannot set undefined property string, key=%s", key.c_str());
276        return Status::BAD_VALUE;
277    }
278
279    mStringProperties[key] = std::string(value.c_str());
280    return Status::OK;
281}
282
283Return<Status> DrmPlugin::setPropertyByteArray(
284    const hidl_string& name, const hidl_vec<uint8_t>& value) {
285   UNUSED(value);
286   if (name == kDeviceIdKey) {
287      ALOGD("Cannot set immutable property: %s", name.c_str());
288      return Status::BAD_VALUE;
289   }
290
291   // Setting of undefined properties is not supported
292   ALOGE("Failed to set property byte array, key=%s", name.c_str());
293   return Status::ERROR_DRM_CANNOT_HANDLE;
294}
295
296Return<void> DrmPlugin::queryKeyStatus(
297        const hidl_vec<uint8_t>& sessionId,
298        queryKeyStatus_cb _hidl_cb) {
299
300    if (sessionId.size() == 0) {
301        // Returns empty key status KeyValue pair
302        _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
303        return Void();
304    }
305
306    std::vector<KeyValue> infoMapVec;
307    infoMapVec.clear();
308
309    KeyValue keyValuePair;
310    for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
311        keyValuePair.key = mPlayPolicy[i].key;
312        keyValuePair.value = mPlayPolicy[i].value;
313        infoMapVec.push_back(keyValuePair);
314    }
315    _hidl_cb(Status::OK, toHidlVec(infoMapVec));
316    return Void();
317}
318
319Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
320        uint32_t currentSessions = mSessionLibrary->numOpenSessions();
321        uint32_t maxSessions = 10;
322        _hidl_cb(Status::OK, currentSessions, maxSessions);
323        return Void();
324}
325
326Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
327            getSecurityLevel_cb _hidl_cb) {
328    if (sessionId.size() == 0) {
329        _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
330        return Void();
331    }
332
333    std::vector<uint8_t> sid = toVector(sessionId);
334    sp<Session> session = mSessionLibrary->findSession(sid);
335    if (!session.get()) {
336        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
337        return Void();
338    }
339
340    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
341            mSecurityLevel.find(sid);
342    if (itr == mSecurityLevel.end()) {
343        ALOGE("Session id not found");
344        _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
345        return Void();
346    }
347
348    _hidl_cb(Status::OK, itr->second);
349    return Void();
350}
351
352Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
353            SecurityLevel level) {
354    if (sessionId.size() == 0) {
355        ALOGE("Invalid empty session id");
356        return Status::BAD_VALUE;
357    }
358
359    if (level > SecurityLevel::SW_SECURE_CRYPTO) {
360        ALOGE("Cannot set security level > max");
361        return Status::BAD_VALUE;
362    }
363
364    std::vector<uint8_t> sid = toVector(sessionId);
365    sp<Session> session = mSessionLibrary->findSession(sid);
366    if (!session.get()) {
367        return Status::ERROR_DRM_SESSION_NOT_OPENED;
368    }
369
370    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
371            mSecurityLevel.find(sid);
372    if (itr != mSecurityLevel.end()) {
373        mSecurityLevel[sid] = level;
374    } else {
375        if (!mSecurityLevel.insert(
376                std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
377            ALOGE("Failed to set security level");
378            return Status::ERROR_DRM_INVALID_STATE;
379        }
380    }
381    return Status::OK;
382}
383
384Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
385    // Set the open session count metric.
386    DrmMetricGroup::Attribute openSessionOkAttribute = {
387      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
388    };
389    DrmMetricGroup::Value openSessionMetricValue = {
390      "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
391    };
392    DrmMetricGroup::Metric openSessionMetric = {
393      "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
394    };
395
396    // Set the close session count metric.
397    DrmMetricGroup::Attribute closeSessionOkAttribute = {
398      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
399    };
400    DrmMetricGroup::Value closeSessionMetricValue = {
401      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
402    };
403    DrmMetricGroup::Metric closeSessionMetric = {
404      "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
405    };
406
407    // Set the close session, not opened metric.
408    DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
409      "status", DrmMetricGroup::ValueType::INT64_TYPE,
410      (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
411    };
412    DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
413      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
414    };
415    DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
416      "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
417    };
418
419    DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
420                                closeSessionNotOpenedMetric } };
421
422    _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
423    return Void();
424}
425
426
427
428}  // namespace clearkey
429}  // namespace V1_1
430}  // namespace drm
431}  // namespace hardware
432}  // namespace android
433