/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "ClearKeyCryptoPlugin" #include #include #include #include "DrmPlugin.h" #include "Session.h" namespace { const android::String8 kStreaming("Streaming"); const android::String8 kOffline("Offline"); const android::String8 kTrue("True"); const android::String8 kQueryKeyLicenseType("LicenseType"); // Value: "Streaming" or "Offline" const android::String8 kQueryKeyPlayAllowed("PlayAllowed"); // Value: "True" or "False" const android::String8 kQueryKeyRenewAllowed("RenewAllowed"); // Value: "True" or "False" }; namespace clearkeydrm { using android::sp; DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary) : mSessionLibrary(sessionLibrary) { mPlayPolicy.clear(); } status_t DrmPlugin::openSession(Vector& sessionId) { sp session = mSessionLibrary->createSession(); sessionId = session->sessionId(); return android::OK; } status_t DrmPlugin::closeSession(const Vector& sessionId) { sp session = mSessionLibrary->findSession(sessionId); if (sessionId.size() == 0) { return android::BAD_VALUE; } if (session.get()) { mSessionLibrary->destroySession(session); return android::OK; } return android::ERROR_DRM_SESSION_NOT_OPENED; } status_t DrmPlugin::getKeyRequest( const Vector& scope, const Vector& initData, const String8& mimeType, KeyType keyType, const KeyedVector& optionalParameters, Vector& request, String8& defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) { UNUSED(optionalParameters); if (scope.size() == 0) { return android::BAD_VALUE; } if (keyType != kKeyType_Streaming) { return android::ERROR_DRM_CANNOT_HANDLE; } *keyRequestType = DrmPlugin::kKeyRequestType_Initial; defaultUrl.clear(); sp session = mSessionLibrary->findSession(scope); if (!session.get()) { return android::ERROR_DRM_SESSION_NOT_OPENED; } return session->getKeyRequest(initData, mimeType, &request); } void DrmPlugin::setPlayPolicy() { mPlayPolicy.clear(); mPlayPolicy.add(kQueryKeyLicenseType, kStreaming); mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue); mPlayPolicy.add(kQueryKeyRenewAllowed, kTrue); } status_t DrmPlugin::provideKeyResponse( const Vector& scope, const Vector& response, Vector& keySetId) { if (scope.size() == 0 || response.size() == 0) { return android::BAD_VALUE; } sp session = mSessionLibrary->findSession(scope); if (!session.get()) { return android::ERROR_DRM_SESSION_NOT_OPENED; } setPlayPolicy(); status_t res = session->provideKeyResponse(response); if (res == android::OK) { // This is for testing AMediaDrm_setOnEventListener only. sendEvent(kDrmPluginEventVendorDefined, 0, &scope, NULL); keySetId.clear(); } return res; } status_t DrmPlugin::getPropertyString( const String8& name, String8& value) const { if (name == "vendor") { value = "Google"; } else if (name == "version") { value = "1.0"; } else if (name == "description") { value = "ClearKey CDM"; } else if (name == "algorithms") { value = ""; } else if (name == "listenerTestSupport") { value = "true"; } else { ALOGE("App requested unknown string property %s", name.string()); return android::ERROR_DRM_CANNOT_HANDLE; } return android::OK; } status_t DrmPlugin::queryKeyStatus( const Vector& sessionId, KeyedVector& infoMap) const { if (sessionId.size() == 0) { return android::BAD_VALUE; } infoMap.clear(); for (size_t i = 0; i < mPlayPolicy.size(); ++i) { infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i)); } return android::OK; } } // namespace clearkeydrm