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 45 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary) 46 : mSessionLibrary(sessionLibrary) { 47 48 mPlayPolicy.clear(); 49 initProperties(); 50 } 51 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 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 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 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 111 void DrmPlugin::setPlayPolicy() { 112 mPlayPolicy.clear(); 113 mPlayPolicy.add(kQueryKeyLicenseType, kStreaming); 114 mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue); 115 mPlayPolicy.add(kQueryKeyRenewAllowed, kTrue); 116 } 117 118 status_t DrmPlugin::provideKeyResponse( 119 const Vector<uint8_t>& scope, 120 const Vector<uint8_t>& response, 121 Vector<uint8_t>& keySetId) { 122 if (scope.size() == 0 || response.size() == 0) { 123 return android::BAD_VALUE; 124 } 125 sp<Session> session = mSessionLibrary->findSession(scope); 126 if (!session.get()) { 127 return android::ERROR_DRM_SESSION_NOT_OPENED; 128 } 129 130 setPlayPolicy(); 131 status_t res = session->provideKeyResponse(response); 132 if (res == android::OK) { 133 // This is for testing AMediaDrm_setOnEventListener only. 134 sendEvent(kDrmPluginEventVendorDefined, 0, &scope, NULL); 135 keySetId.clear(); 136 } 137 return res; 138 } 139 140 status_t DrmPlugin::getPropertyByteArray( 141 const String8& name, Vector<uint8_t>& value) const { 142 ssize_t index = mByteArrayProperties.indexOfKey(name); 143 if (index < 0) { 144 ALOGE("App requested unknown property: %s", name.string()); 145 return android::ERROR_DRM_CANNOT_HANDLE; 146 } 147 value = mByteArrayProperties.valueAt(index); 148 return android::OK; 149 } 150 151 status_t DrmPlugin::setPropertyByteArray( 152 const String8& name, const Vector<uint8_t>& value) 153 { 154 UNUSED(value); 155 if (0 == name.compare(kDeviceIdKey)) { 156 ALOGD("Cannot set immutable property: %s", name.string()); 157 return android::ERROR_DRM_CANNOT_HANDLE; 158 } 159 160 // Setting of undefined properties is not supported 161 ALOGE("Failed to set property byte array, key=%s", name.string()); 162 return android::ERROR_DRM_CANNOT_HANDLE; 163 } 164 165 status_t DrmPlugin::getPropertyString( 166 const String8& name, String8& value) const { 167 ssize_t index = mStringProperties.indexOfKey(name); 168 if (index < 0) { 169 ALOGE("App requested unknown property: %s", name.string()); 170 return android::ERROR_DRM_CANNOT_HANDLE; 171 } 172 value = mStringProperties.valueAt(index); 173 return android::OK; 174 } 175 176 status_t DrmPlugin::setPropertyString( 177 const String8& name, const String8& value) { 178 String8 immutableKeys; 179 immutableKeys.appendFormat("%s,%s,%s,%s", 180 kAlgorithmsKey.string(), kPluginDescriptionKey.string(), 181 kVendorKey.string(), kVersionKey.string()); 182 if (immutableKeys.contains(name.string())) { 183 ALOGD("Cannot set immutable property: %s", name.string()); 184 return android::ERROR_DRM_CANNOT_HANDLE; 185 } 186 187 ssize_t index = mStringProperties.indexOfKey(name); 188 if (index < 0) { 189 ALOGE("Cannot set undefined property string, key=%s", name.string()); 190 return android::ERROR_DRM_CANNOT_HANDLE; 191 } 192 193 if (mStringProperties.add(name, value) < 0) { 194 ALOGE("Failed to set property string, key=%s", name.string()); 195 return android::ERROR_DRM_UNKNOWN; 196 } 197 return android::OK; 198 } 199 200 status_t DrmPlugin::queryKeyStatus( 201 const Vector<uint8_t>& sessionId, 202 KeyedVector<String8, String8>& infoMap) const { 203 204 if (sessionId.size() == 0) { 205 return android::BAD_VALUE; 206 } 207 208 infoMap.clear(); 209 for (size_t i = 0; i < mPlayPolicy.size(); ++i) { 210 infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i)); 211 } 212 return android::OK; 213 } 214 } // namespace clearkeydrm 215