Qt copyrights are now in The Qt Company, so we could update the source code headers accordingly. In the same go we should also fix the links to point to qt.io. Change-Id: I1c6faa4f59f8eca54f01ef20941fa60161dd7872 Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
400 lines
13 KiB
C++
400 lines
13 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2013 Jolla Ltd, author: <robin.burchell@jollamobile.com>
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL21$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <policy/resource.h>
|
|
#include <policy/resources.h>
|
|
#include <policy/resource-set.h>
|
|
|
|
#include "resourcepolicyint.h"
|
|
#include "resourcepolicyimpl.h"
|
|
|
|
#include <QMap>
|
|
#include <QByteArray>
|
|
#include <QString>
|
|
|
|
static int clientid = 0;
|
|
|
|
ResourcePolicyInt::ResourcePolicyInt(QObject *parent)
|
|
: QObject(parent)
|
|
, m_acquired(0)
|
|
, m_status(Initial)
|
|
, m_video(0)
|
|
, m_available(false)
|
|
, m_resourceSet(0)
|
|
{
|
|
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();
|
|
|
|
connect(m_resourceSet, SIGNAL(resourcesGranted(QList<ResourcePolicy::ResourceType>)),
|
|
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(handleResourcesReleasedByManager()));
|
|
|
|
connect(m_resourceSet, SIGNAL(resourcesBecameAvailable(const QList<ResourcePolicy::ResourceType>)),
|
|
this, SLOT(handleResourcesBecameAvailable(const QList<ResourcePolicy::ResourceType>)));
|
|
|
|
ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource(resourceClass);
|
|
|
|
audioResource->setProcessID(QCoreApplication::applicationPid());
|
|
audioResource->setStreamTag("media.name", "*");
|
|
m_resourceSet->addResourceObject(audioResource);
|
|
m_resourceSet->update();
|
|
}
|
|
|
|
ResourcePolicyInt::~ResourcePolicyInt()
|
|
{
|
|
delete m_resourceSet;
|
|
m_resourceSet = 0;
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### Tearing down singleton.";
|
|
#endif
|
|
}
|
|
|
|
void ResourcePolicyInt::addClient(ResourcePolicyImpl *client)
|
|
{
|
|
clientEntry entry;
|
|
entry.id = clientid++;
|
|
entry.client = client;
|
|
entry.status = Initial;
|
|
entry.videoEnabled = false;
|
|
m_clients.insert(entry.client, entry);
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### Add client " << client << " : " << entry.id;
|
|
#endif
|
|
}
|
|
|
|
void ResourcePolicyInt::removeClient(ResourcePolicyImpl *client)
|
|
{
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.find(client);
|
|
if (i != m_clients.end()) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### Remove client " << client << " : " << i.value().id;
|
|
#endif
|
|
if (i.value().status == GrantedResource)
|
|
--m_acquired;
|
|
m_clients.erase(i);
|
|
}
|
|
|
|
if (m_acquired == 0 && m_status != Initial) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### Remove client, acquired = 0, release";
|
|
#endif
|
|
m_resourceSet->release();
|
|
m_status = Initial;
|
|
}
|
|
}
|
|
|
|
bool ResourcePolicyInt::isVideoEnabled(const ResourcePolicyImpl *client) const
|
|
{
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::const_iterator i = m_clients.find(client);
|
|
if (i != m_clients.constEnd())
|
|
return i.value().videoEnabled;
|
|
|
|
return false;
|
|
}
|
|
|
|
void ResourcePolicyInt::setVideoEnabled(const ResourcePolicyImpl *client, bool videoEnabled)
|
|
{
|
|
bool update = false;
|
|
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.find(client);
|
|
if (i != m_clients.end()) {
|
|
if (videoEnabled == i.value().videoEnabled)
|
|
return;
|
|
|
|
if (videoEnabled) {
|
|
if (m_video > 0) {
|
|
i.value().videoEnabled = true;
|
|
} else {
|
|
m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
|
|
update = true;
|
|
}
|
|
++m_video;
|
|
} else {
|
|
--m_video;
|
|
i.value().videoEnabled = false;
|
|
if (m_video == 0) {
|
|
m_resourceSet->deleteResource(ResourcePolicy::VideoPlaybackType);
|
|
update = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (update)
|
|
m_resourceSet->update();
|
|
}
|
|
|
|
void ResourcePolicyInt::acquire(const ResourcePolicyImpl *client)
|
|
{
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.find(client);
|
|
if (i != m_clients.end()) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": ACQUIRE";
|
|
#endif
|
|
if (i.value().status == Initial) {
|
|
|
|
if (m_status == RequestedResource) {
|
|
i.value().status = RequestedResource;
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": Already requesting, set client as RequestResource and return";
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (m_status == GrantedResource) {
|
|
++m_acquired;
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": Already granted, set as GrantedResource and return";
|
|
#endif
|
|
i.value().status = GrantedResource;
|
|
emit i.value().client->resourcesGranted();
|
|
return;
|
|
}
|
|
} else if (i.value().status == RequestedResource) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": Already requesting, return";
|
|
#endif
|
|
return;
|
|
} else {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": Already granted, return ";
|
|
#endif
|
|
return;
|
|
}
|
|
i.value().status = RequestedResource;
|
|
m_status = RequestedResource;
|
|
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": ACQUIRE call resourceSet->acquire()";
|
|
#endif
|
|
// If m_status was Initial this is the first time resources are requested,
|
|
// so let's actually do the acquiring
|
|
m_resourceSet->acquire();
|
|
}
|
|
}
|
|
|
|
void ResourcePolicyInt::release(const ResourcePolicyImpl *client)
|
|
{
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.find(client);
|
|
if (i != m_clients.end()) {
|
|
if (i.value().status == GrantedResource) {
|
|
i.value().status = Initial;
|
|
--m_acquired;
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": RELEASE, acquired (" << m_acquired << ")";
|
|
#endif
|
|
emit i.value().client->resourcesReleased();
|
|
}
|
|
}
|
|
|
|
if (m_acquired == 0 && m_status != Initial) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": RELEASE call resourceSet->release()";
|
|
#endif
|
|
m_resourceSet->release();
|
|
m_status = Initial;
|
|
}
|
|
}
|
|
|
|
bool ResourcePolicyInt::isGranted(const ResourcePolicyImpl *client) const
|
|
{
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::const_iterator i = m_clients.find(client);
|
|
if (i != m_clients.constEnd()) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": IS GRANTED, status: " << i.value().status;
|
|
#endif
|
|
return i.value().status == GrantedResource;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ResourcePolicyInt::isAvailable() const
|
|
{
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### isAvailable " << m_available;
|
|
#endif
|
|
return m_available;
|
|
}
|
|
|
|
void ResourcePolicyInt::handleResourcesGranted()
|
|
{
|
|
m_status = GrantedResource;
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.begin();
|
|
while (i != m_clients.end()) {
|
|
if (i.value().status == RequestedResource) {
|
|
++m_acquired;
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": HANDLE GRANTED, acquired (" << m_acquired << ") emitting resourcesGranted()";
|
|
#endif
|
|
i.value().status = GrantedResource;
|
|
emit i.value().client->resourcesGranted();
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
void ResourcePolicyInt::handleResourcesDenied()
|
|
{
|
|
m_status = Initial;
|
|
m_acquired = 0;
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.begin();
|
|
while (i != m_clients.end()) {
|
|
if (i.value().status == RequestedResource) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": HANDLE DENIED, acquired (" << m_acquired << ") emitting resourcesDenied()";
|
|
#endif
|
|
i.value().status = Initial;
|
|
emit i.value().client->resourcesDenied();
|
|
}
|
|
// Do we need to act for clients that are in granted state?
|
|
++i;
|
|
}
|
|
}
|
|
|
|
void ResourcePolicyInt::handleResourcesReleased()
|
|
{
|
|
m_status = Initial;
|
|
m_acquired = 0;
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.begin();
|
|
while (i != m_clients.end()) {
|
|
if (i.value().status != Initial) {
|
|
#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 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<const ResourcePolicyImpl*, clientEntry>::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;
|
|
|
|
QMap<const ResourcePolicyImpl*, clientEntry>::iterator i = m_clients.begin();
|
|
while (i != m_clients.end()) {
|
|
if (i.value().status != Initial) {
|
|
#ifdef RESOURCE_DEBUG
|
|
qDebug() << "##### " << i.value().id << ": HANDLE RELEASEDBYMANAGER, acquired (" << m_acquired << ") emitting resourcesLost()";
|
|
#endif
|
|
i.value().status = Initial;
|
|
emit i.value().client->resourcesLost();
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
void ResourcePolicyInt::handleResourcesBecameAvailable(const QList<ResourcePolicy::ResourceType> &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 ResourcePolicyImpl*, clientEntry>::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;
|
|
}
|
|
}
|