Note that this version does not have Widevine Provisioning 4.0 support. It is only suitable for device upgrades. A new patch with provisioning 4.0 support will be made later.
155 lines
6.4 KiB
C++
155 lines
6.4 KiB
C++
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||
// source code may only be used and distributed under the Widevine Master
|
||
// License Agreement.
|
||
|
||
#ifndef WIDEVINE_MEDIA_CAS_PLUGIN
|
||
#define WIDEVINE_MEDIA_CAS_PLUGIN
|
||
|
||
#include <memory>
|
||
|
||
#include "media/cas/CasAPI.h"
|
||
#include "widevine_cas_api.h"
|
||
|
||
using android::CasPlugin;
|
||
using android::CasPluginCallback;
|
||
using android::CasPluginCallbackExt;
|
||
using android::CasPluginStatusCallback;
|
||
using android::CasSessionId;
|
||
using android::status_t;
|
||
using android::String8;
|
||
|
||
namespace wvcas {
|
||
|
||
// WidevineCasPlugin inplements the android::CasPlugin interface.
|
||
class WidevineCasPlugin : public CasPlugin, public CasEventListener {
|
||
public:
|
||
// Constructs a new WidevineCasPlugin. The |callback| is a method to transmit
|
||
// events to the user application. To receive these events, a MediaCas
|
||
// application must implement The MediaCas.EventListener java interface and
|
||
// call MediaCas.setEventListener. More information can be found in the
|
||
// MediaCas platform api documentation.
|
||
WidevineCasPlugin(void* appData, CasPluginCallback callback);
|
||
WidevineCasPlugin(void* appData, CasPluginCallbackExt callback);
|
||
~WidevineCasPlugin() override;
|
||
|
||
status_t initialize();
|
||
|
||
// Provide a callback to report plugin status.
|
||
status_t setStatusCallback(CasPluginStatusCallback callback) override;
|
||
|
||
// Provide the CA private data from a CA_descriptor in the conditional
|
||
// access table.
|
||
status_t setPrivateData(const CasData& privateData) override;
|
||
|
||
// Open a session for descrambling a program, or one or more elementary
|
||
// streams.
|
||
status_t openSession(CasSessionId* sessionId) override;
|
||
|
||
// Open a session with intend and mode for descrambling a program, or one
|
||
// or more elementary streams.
|
||
status_t openSession(uint32_t intent, uint32_t mode,
|
||
CasSessionId* sessionId) override;
|
||
|
||
// Close a previously opened session.
|
||
status_t closeSession(const CasSessionId& sessionId) override;
|
||
|
||
// Provide the CA private data from a CA_descriptor in the program map
|
||
// table.
|
||
status_t setSessionPrivateData(const CasSessionId& sessionId,
|
||
const CasData& privateData) override;
|
||
|
||
// Process an ECM from the ECM stream for this session’s elementary stream.
|
||
status_t processEcm(const CasSessionId& sessionId,
|
||
const CasEcm& ecm) override;
|
||
|
||
// Process an in-band EMM from the EMM stream.
|
||
status_t processEmm(const CasEmm& emm) override;
|
||
|
||
// Deliver an event to the CasPlugin. The format of the event is specific
|
||
// to the CA scheme and is opaque to the framework.
|
||
status_t sendEvent(int32_t event, int32_t arg,
|
||
const CasData& eventData) override;
|
||
|
||
// Deliver an session event to the CasPlugin. The format of the event is
|
||
// specific to the CA scheme and is opaque to the framework.
|
||
status_t sendSessionEvent(const CasSessionId& sessionId, int32_t event,
|
||
int32_t arg, const CasData& eventData) override;
|
||
|
||
// Native implementation of the MediaCas Java API provision method.
|
||
status_t provision(const String8& provisionString) override;
|
||
|
||
// Native implementation of the MediaCas Java API refreshEntitlements method.
|
||
status_t refreshEntitlements(int32_t refreshType,
|
||
const CasData& refreshData) override;
|
||
|
||
WidevineCasPlugin(const WidevineCasPlugin&) = delete;
|
||
WidevineCasPlugin& operator=(const WidevineCasPlugin&) = delete;
|
||
|
||
protected:
|
||
// For unit test only.
|
||
virtual void SetWidevineCasApi(
|
||
std::unique_ptr<WidevineCas> widevine_cas_api) {
|
||
widevine_cas_api_ = std::move(widevine_cas_api);
|
||
}
|
||
WidevineCasPlugin(){};
|
||
|
||
private:
|
||
// |sessionId| is nullptr if the event is not a session event.
|
||
CasStatus processEvent(int32_t event, int32_t arg, const CasData& eventData,
|
||
const CasSessionId* sessionId);
|
||
CasStatus HandleIndividualizationResponse(const CasData& response);
|
||
CasStatus HandleEntitlementResponse(const CasData& response);
|
||
status_t requestLicense(const std::string& init_data);
|
||
CasStatus HandleEntitlementRenewalResponse(const CasData& response);
|
||
CasStatus HandleUniqueIDQuery();
|
||
CasStatus HandleSetParentalControlAge(const CasData& data);
|
||
CasStatus HandleLicenseRemoval(const CasData& license_id);
|
||
CasStatus HandleAssignLicenseID(const CasData& license_id);
|
||
CasStatus HandlePluginVersionQuery();
|
||
CasStatus HandleEntitlementPeriodUpdateResponse(const CasData& response);
|
||
|
||
// Returns true if the device has been provisioned with a device certificate.
|
||
bool is_provisioned() const;
|
||
// Event listener implementation
|
||
void OnSessionRenewalNeeded() override;
|
||
void OnSessionKeysChange(const KeyStatusMap& keys_status,
|
||
bool has_new_usable_key) override;
|
||
// |new_expiry_time_seconds| of 0 means "never expires".
|
||
void OnExpirationUpdate(int64_t new_expiry_time_seconds) override;
|
||
void OnNewRenewalServerUrl(const std::string& renewal_server_url) override;
|
||
void OnLicenseExpiration() override;
|
||
void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId,
|
||
uint8_t ecm_age_restriction) override;
|
||
void OnSessionFingerprintingUpdated(const WvCasSessionId& sessionId,
|
||
const CasData& fingerprinting) override;
|
||
void OnSessionServiceBlockingUpdated(
|
||
const WvCasSessionId& sessionId,
|
||
const CasData& service_blocking) override;
|
||
void OnFingerprintingUpdated(const CasData& fingerprinting) override;
|
||
void OnServiceBlockingUpdated(const CasData& service_blocking) override;
|
||
void OnEntitlementPeriodUpdateNeeded(
|
||
const std::string& signed_license_request) override;
|
||
|
||
// Choose to use |callback_| or |callback_ext_| to send back information.
|
||
// |sessionId| is ignored if |callback_ext_| is null,
|
||
virtual void CallBack(void* appData, int32_t event, int32_t arg,
|
||
uint8_t* data, size_t size,
|
||
const CasSessionId* sessionId) const;
|
||
|
||
void* app_data_;
|
||
CasPluginCallback callback_;
|
||
CasPluginCallbackExt callback_ext_;
|
||
// If provision is called with a non-empty string,
|
||
// it is taken as a PSSH that overrides data in CA descripor.
|
||
// Otherwise, first CA descriptor available to the plugin
|
||
// is used to build a PSSH, and others are discarded.
|
||
bool is_emm_request_sent_ = false;
|
||
// This is always the serialized PSSH data.
|
||
std::string init_data_;
|
||
std::unique_ptr<WidevineCas> widevine_cas_api_;
|
||
};
|
||
|
||
} // namespace wvcas
|
||
|
||
#endif // WIDEVINE_MEDIA_CAS_PLUGIN
|