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