From 1c5ea9561ac2686fb01ebd87b2d2b990a27dddad Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 22 Jul 2014 18:23:47 +0200 Subject: [PATCH] Implement more full resource policy features. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Handle released by manager properly. Signal resourcesReleasedByManager is different from signal handleResourcesLost and needs to be handled separately. Signal handleResourcesLost means some other client has acquired the resources, thus the resources are lost from us, but if the other client frees the resources, we will automatically get the resources back. With resourcesReleasedByManager we lose the resources, and resource manager releases them as well (same as if client would call release()), so only way to re-acquire resources in latter case is calling acquire() again. This distinction is useful for example in cases where user is listening to music with headphones connected and removes the headphones, then the music player shouldn't continue playback until user requests so. But if user is listening to music when phone call is received, it is convenient to resume the playback automatically after the call. * Implement availability changed. Availability changed is information whether resources the client is interested in are available (no higher priority resource classes have acquired the resources). * Implement missing resources released. Emit resourcesReleased signal when receiving corresponding signal from libresource-qt. * Add mechanism to change used resource class. Check for environment for special variable, and if the variable has proper data, use that as the resource class. Can be set with for example qputenv("NEMO_RESOURCE_CLASS_OVERRIDE", "game"); Change-Id: I8e92f40cc5c01b6b94f54c3fa0f7a07775e87df0 Done-with: Juho Hämäläinen Reviewed-by: Andrew den Exter --- .../resourcepolicy/resourcepolicyimpl.cpp | 3 +- .../resourcepolicy/resourcepolicyint.cpp | 134 +++++++++++++++--- .../resourcepolicy/resourcepolicyint.h | 8 ++ 3 files changed, 125 insertions(+), 20 deletions(-) diff --git a/src/plugins/resourcepolicy/resourcepolicyimpl.cpp b/src/plugins/resourcepolicy/resourcepolicyimpl.cpp index 3ad92fa1..b3c370f6 100644 --- a/src/plugins/resourcepolicy/resourcepolicyimpl.cpp +++ b/src/plugins/resourcepolicy/resourcepolicyimpl.cpp @@ -61,7 +61,8 @@ ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent) ResourcePolicyImpl::~ResourcePolicyImpl() { ResourcePolicyInt *set = globalResourcePolicyInt; - set->removeClient(this); + if (!globalResourcePolicyInt.isDestroyed()) + set->removeClient(this); } bool ResourcePolicyImpl::isVideoEnabled() const diff --git a/src/plugins/resourcepolicy/resourcepolicyint.cpp b/src/plugins/resourcepolicy/resourcepolicyint.cpp index 2fff64bf..a0086a4d 100644 --- a/src/plugins/resourcepolicy/resourcepolicyint.cpp +++ b/src/plugins/resourcepolicy/resourcepolicyint.cpp @@ -49,6 +49,8 @@ #include "resourcepolicyimpl.h" #include +#include +#include static int clientid = 0; @@ -57,26 +59,51 @@ ResourcePolicyInt::ResourcePolicyInt(QObject *parent) , m_acquired(0) , m_status(Initial) , m_video(0) + , m_available(false) , m_resourceSet(0) { - m_resourceSet = new ResourcePolicy::ResourceSet("player", this); + const char *resourceClass = "player"; + + QByteArray envVar = qgetenv("NEMO_RESOURCE_CLASS_OVERRIDE"); + if (!envVar.isEmpty()) { + QString data(envVar); + // Only allow few resource classes + if (data == "navigator" || + data == "call" || + data == "camera" || + data == "game" || + data == "player" || + data == "event") + resourceClass = envVar.constData(); + } + +#ifdef RESOURCE_DEBUG + qDebug() << "##### Using resource class " << resourceClass; +#endif + + m_resourceSet = new ResourcePolicy::ResourceSet(resourceClass, this); m_resourceSet->setAlwaysReply(); - ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource("player"); - audioResource->setProcessID(QCoreApplication::applicationPid()); - audioResource->setStreamTag("media.name", "*"); - m_resourceSet->addResourceObject(audioResource); - - m_resourceSet->update(); - connect(m_resourceSet, SIGNAL(resourcesGranted(QList)), this, SLOT(handleResourcesGranted())); connect(m_resourceSet, SIGNAL(resourcesDenied()), this, SLOT(handleResourcesDenied())); + connect(m_resourceSet, SIGNAL(resourcesReleased()), + this, SLOT(handleResourcesReleased())); connect(m_resourceSet, SIGNAL(lostResources()), this, SLOT(handleResourcesLost())); connect(m_resourceSet, SIGNAL(resourcesReleasedByManager()), - this, SLOT(handleResourcesLost())); + this, SLOT(handleResourcesReleasedByManager())); + + connect(m_resourceSet, SIGNAL(resourcesBecameAvailable(const QList)), + this, SLOT(handleResourcesBecameAvailable(const QList))); + + ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource(resourceClass); + + audioResource->setProcessID(QCoreApplication::applicationPid()); + audioResource->setStreamTag("media.name", "*"); + m_resourceSet->addResourceObject(audioResource); + m_resourceSet->update(); } ResourcePolicyInt::~ResourcePolicyInt() @@ -113,7 +140,7 @@ void ResourcePolicyInt::removeClient(ResourcePolicyImpl *client) m_clients.erase(i); } - if (m_acquired == 0) { + if (m_acquired == 0 && m_status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### Remove client, acquired = 0, release"; #endif @@ -221,10 +248,11 @@ void ResourcePolicyInt::release(const ResourcePolicyImpl *client) #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": RELEASE, acquired (" << m_acquired << ")"; #endif + emit i.value().client->resourcesReleased(); } } - if (m_acquired == 0) { + if (m_acquired == 0 && m_status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": RELEASE call resourceSet->release()"; #endif @@ -248,9 +276,10 @@ bool ResourcePolicyInt::isGranted(const ResourcePolicyImpl *client) const bool ResourcePolicyInt::isAvailable() const { - // TODO: is this used? what is it for? - qWarning() << Q_FUNC_INFO << "Stub"; - return true; +#ifdef RESOURCE_DEBUG + qDebug() << "##### isAvailable " << m_available; +#endif + return m_available; } void ResourcePolicyInt::handleResourcesGranted() @@ -288,20 +317,58 @@ void ResourcePolicyInt::handleResourcesDenied() } } +void ResourcePolicyInt::handleResourcesReleased() +{ + m_status = Initial; + m_acquired = 0; + QMap::iterator i = m_clients.begin(); + while (i != m_clients.end()) { + if (i.value().status == GrantedResource) { +#ifdef RESOURCE_DEBUG + qDebug() << "##### " << i.value().id << ": HANDLE RELEASED, acquired (" << m_acquired << ") emitting resourcesReleased()"; +#endif + i.value().status = Initial; + emit i.value().client->resourcesReleased(); + } + ++i; + } +} + void ResourcePolicyInt::handleResourcesLost() { - if (m_status != Initial) { - m_status = Initial; - } + // If resources were granted switch to acquiring state, + // so that if the resources are freed elsewhere we + // will acquire them again properly. + if (m_status == GrantedResource) + m_status = RequestedResource; + + m_acquired = 0; + + QMap::iterator i = m_clients.begin(); + while (i != m_clients.end()) { + if (i.value().status == GrantedResource) { +#ifdef RESOURCE_DEBUG + qDebug() << "##### " << i.value().id << ": HANDLE LOST, acquired (" << m_acquired << ") emitting resourcesLost()"; +#endif + i.value().status = RequestedResource; + emit i.value().client->resourcesLost(); + } + ++i; + } +} + +void ResourcePolicyInt::handleResourcesReleasedByManager() +{ + if (m_status != Initial) + m_status = Initial; m_acquired = 0; - m_resourceSet->release(); QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status != Initial) { #ifdef RESOURCE_DEBUG - qDebug() << "##### " << i.value().id << ": HANDLE LOST, acquired (" << m_acquired << ") emitting resourcesLost()"; + qDebug() << "##### " << i.value().id << ": HANDLE RELEASEDBYMANAGER, acquired (" << m_acquired << ") emitting resourcesLost()"; #endif i.value().status = Initial; emit i.value().client->resourcesLost(); @@ -309,3 +376,32 @@ void ResourcePolicyInt::handleResourcesLost() ++i; } } + +void ResourcePolicyInt::handleResourcesBecameAvailable(const QList &resources) +{ + bool available = false; + + for (int i = 0; i < resources.size(); ++i) { + if (resources.at(i) == ResourcePolicy::AudioPlaybackType) + available = true; + } + + availabilityChanged(available); +} + +void ResourcePolicyInt::availabilityChanged(bool available) +{ + if (available == m_available) + return; + + m_available = available; + + QMap::const_iterator i = m_clients.constBegin(); + while (i != m_clients.constEnd()) { +#ifdef RESOURCE_DEBUG + qDebug() << "##### " << i.value().id << ": emitting availabilityChanged(" << m_available << ")"; +#endif + emit i.value().client->availabilityChanged(m_available); + ++i; + } +} diff --git a/src/plugins/resourcepolicy/resourcepolicyint.h b/src/plugins/resourcepolicy/resourcepolicyint.h index 39882b52..6290c754 100644 --- a/src/plugins/resourcepolicy/resourcepolicyint.h +++ b/src/plugins/resourcepolicy/resourcepolicyint.h @@ -46,6 +46,8 @@ #include #include +#include +#include #include #include "resourcepolicyimpl.h" @@ -86,14 +88,20 @@ public: private slots: void handleResourcesGranted(); void handleResourcesDenied(); + void handleResourcesReleased(); void handleResourcesLost(); + void handleResourcesReleasedByManager(); + void handleResourcesBecameAvailable(const QList &resources); private: + void availabilityChanged(bool available); + QMap m_clients; int m_acquired; ResourceStatus m_status; int m_video; + bool m_available; ResourcePolicy::ResourceSet *m_resourceSet; };