Delete Singleton on Library Unload

(This is a merge of http://go/wvgerrit/14531)

As an optimization, the Media Server now unloads our library when not
in use. This has exposed a bug by which we were never deleting the CDM
singleton. Fix is to make WvContentDecryptionModule an Android smart
pointer ref base and then make sure all the plugins store a strong
pointer to it. The singleton is a weak pointer, so when the last
plugin is cleaned up, the CDM will be as well. And on the off chance
that the library isn't immediately unloaded, the singleton code will
generate a new CDM next time one is needed.

Bug: 21153732
Change-Id: Ifaf02fa9afe0a70a8b53e8b92ee0a3d1359ca001
This commit is contained in:
John "Juce" Bruce
2015-06-03 15:57:00 -07:00
parent a54ae37ceb
commit a8328dd2f9
7 changed files with 25 additions and 11 deletions

View File

@@ -4,6 +4,7 @@
#define CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
#include <UniquePtr.h>
#include <utils/RefBase.h>
#include "lock.h"
#include "timer.h"
@@ -15,7 +16,7 @@ class CdmClientPropertySet;
class CdmEngine;
class WvCdmEventListener;
class WvContentDecryptionModule : public TimerHandler {
class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
public:
WvContentDecryptionModule();
virtual ~WvContentDecryptionModule();

View File

@@ -5,11 +5,13 @@
#ifndef WV_CDM_SINGLETON_H_
#define WV_CDM_SINGLETON_H_
#include "utils/StrongPointer.h"
#include "wv_content_decryption_module.h"
namespace wvdrm {
wvcdm::WvContentDecryptionModule* getCDM();
android::sp<wvcdm::WvContentDecryptionModule> getCDM();
} // namespace wvdrm

View File

@@ -7,6 +7,7 @@
#include <stdint.h>
#include "utils/StrongPointer.h"
#include "utils/Vector.h"
#include "media/hardware/CryptoAPI.h"
@@ -19,7 +20,7 @@ namespace wvdrm {
class WVCryptoPlugin : public android::CryptoPlugin {
public:
WVCryptoPlugin(const void* data, size_t size,
wvcdm::WvContentDecryptionModule* cdm);
const android::sp<wvcdm::WvContentDecryptionModule>& cdm);
virtual ~WVCryptoPlugin() {}
virtual bool requiresSecureDecoderComponent(const char* mime) const;
@@ -37,7 +38,7 @@ class WVCryptoPlugin : public android::CryptoPlugin {
private:
DISALLOW_EVIL_CONSTRUCTORS(WVCryptoPlugin);
wvcdm::WvContentDecryptionModule* const mCDM;
android::sp<wvcdm::WvContentDecryptionModule> const mCDM;
bool mTestMode;
wvcdm::CdmSessionId mSessionId;

View File

@@ -29,7 +29,7 @@ using namespace std;
using namespace wvcdm;
WVCryptoPlugin::WVCryptoPlugin(const void* data, size_t size,
WvContentDecryptionModule* cdm)
const sp<WvContentDecryptionModule>& cdm)
: mCDM(cdm),
mTestMode(false),
mSessionId(configureTestMode(data, size)) {}

View File

@@ -17,6 +17,7 @@
#include "utils/KeyedVector.h"
#include "utils/List.h"
#include "utils/String8.h"
#include "utils/StrongPointer.h"
#include "utils/Vector.h"
#include "wv_cdm_event_listener.h"
#include "wv_content_decryption_module.h"
@@ -41,7 +42,7 @@ const OEMCrypto_Algorithm kInvalidCrytpoAlgorithm =
class WVDrmPlugin : public android::DrmPlugin,
public wvcdm::WvCdmEventListener {
public:
WVDrmPlugin(WvContentDecryptionModule* cdm,
WVDrmPlugin(const android::sp<wvcdm::WvContentDecryptionModule>& cdm,
WVGenericCryptoInterface* crypto);
virtual ~WVDrmPlugin();
@@ -248,7 +249,7 @@ class WVDrmPlugin : public android::DrmPlugin,
std::string mAppId;
} mPropertySet;
WvContentDecryptionModule* mCDM;
android::sp<wvcdm::WvContentDecryptionModule> const mCDM;
WVGenericCryptoInterface* mCrypto;
std::string mOrigin;
map<CdmSessionId, CryptoSession> mCryptoSessions;

View File

@@ -73,7 +73,7 @@ DrmPlugin::KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
} // namespace
WVDrmPlugin::WVDrmPlugin(WvContentDecryptionModule* cdm,
WVDrmPlugin::WVDrmPlugin(const sp<WvContentDecryptionModule>& cdm,
WVGenericCryptoInterface* crypto)
: mCDM(cdm), mCrypto(crypto), mOrigin(), mCryptoSessions() {}

View File

@@ -9,21 +9,30 @@
#include "WVCDMSingleton.h"
#include "utils/Mutex.h"
#include "utils/RefBase.h"
namespace wvdrm {
using wvcdm::WvContentDecryptionModule;
using android::Mutex;
using android::sp;
using android::wp;
Mutex cdmLock;
WvContentDecryptionModule* cdm = NULL;
// The strong pointers that keep this object alive live in the plugin objects.
// If all the plugins are deleted, the CDM will be deleted, and subsequent
// invocations of this code will construct a new CDM.
wp<WvContentDecryptionModule> sCdm;
WvContentDecryptionModule* getCDM() {
Mutex::Autolock lock(cdmLock);
sp<WvContentDecryptionModule> getCDM() {
Mutex::Autolock lock(cdmLock); // This function is a critical section.
sp<WvContentDecryptionModule> cdm = sCdm.promote();
if (cdm == NULL) {
ALOGD("Instantiating CDM.");
cdm = new WvContentDecryptionModule();
sCdm = cdm;
}
return cdm;