// 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 #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 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 widevine_cas_api_; }; } // namespace wvcas #endif // WIDEVINE_MEDIA_CAS_PLUGIN