/****************************************************************************
**
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (developer.feedback@nokia.com)
**
** This file is part of the HbCore module of the UI Extensions for Mobile.
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/
#include "hbsysteminfosym_p_p.h"
#include "hbdevicedialogserverstatus_p.h"
#include <qapplication.h>
#include <qcoreevent.h>
#include <QMutexLocker>
const TUint32 secureId = 0x20022FC5;
const TUint32 splashGenServerSecureId = 0x2002E68B;
// publish & subscribe
const TUid PropertyCategoryUid = {secureId};
const TUint InfoKey = 0x496e666f; // 'Info'
_LIT_SECURITY_POLICY_PASS(KRdPolicy); // all pass
_LIT_SECURITY_POLICY_S0(KWrPolicy, PropertyCategoryUid.iUid); // pass device dialog server
HbSystemInfoPrivate::HbSystemInfoPrivate()
: CActive(CActive::EPriorityStandard),
mPtr(0,0),
mListening(false),
mWatcher(0)
{
}
HbSystemInfoPrivate::~HbSystemInfoPrivate()
{
Cancel();
if (!mWriter) {
lostForeground();
}
delete mSystemNetworkInfo;
delete mSystemDeviceInfo;
mInfoProperty.Close();
delete mDataBuffer;
delete mServerStatus;
}
void HbSystemInfoPrivate::init(bool writer)
{
// device dialog server is the writer
if (writer) {
RProcess me;
if ((me.SecureId().iId != secureId )) {
me.Close();
return;
}
me.Close();
}
if (writer) {
mSystemNetworkInfo = new QtMobility::QSystemNetworkInfo();
mDeviceSystemInfo.networkMode = mSystemNetworkInfo->currentMode();
mDeviceSystemInfo.networkStatus = mSystemNetworkInfo->networkStatus(mDeviceSystemInfo.networkMode);
mDeviceSystemInfo.signalStrength = QSystemNetworkInfo::networkSignalStrength(mDeviceSystemInfo.networkMode);
connect(mSystemNetworkInfo, SIGNAL(networkStatusChanged(QSystemNetworkInfo::NetworkMode, QSystemNetworkInfo::NetworkStatus)),
this, SLOT(setNetworkStatus(QSystemNetworkInfo::NetworkMode, QSystemNetworkInfo::NetworkStatus)));
connect(mSystemNetworkInfo, SIGNAL(networkSignalStrengthChanged(QSystemNetworkInfo::NetworkMode, int)),
this, SLOT(setNetworkSignalStrength(QSystemNetworkInfo::NetworkMode, int)));
connect(mSystemNetworkInfo, SIGNAL(networkModeChanged(QSystemNetworkInfo::NetworkMode)),
this, SLOT(setNetworkMode(QSystemNetworkInfo::NetworkMode)));
mSystemDeviceInfo = new QtMobility::QSystemDeviceInfo();
mDeviceSystemInfo.batteryLevel = mSystemDeviceInfo->batteryLevel();
mDeviceSystemInfo.powerState = mSystemDeviceInfo->currentPowerState();
connect(mSystemDeviceInfo, SIGNAL(batteryLevelChanged(int)),
this, SLOT(setBatteryLevel(int)));
connect(mSystemDeviceInfo, SIGNAL(powerStateChanged(QSystemDeviceInfo::PowerState)),
this, SLOT(setPowerState(QSystemDeviceInfo::PowerState)));
int err = mInfoProperty.Define(PropertyCategoryUid, InfoKey, RProperty::EByteArray, KRdPolicy, KWrPolicy);
if (err == KErrNone) {
writeDeviceInfo();
}
} else {
CActiveScheduler::Add(this);
qApp->installEventFilter(this);
mWatcher = HbForegroundWatcher::instance();
connect(mWatcher, SIGNAL(foregroundGained()), SLOT(gainedForeground()));
connect(mWatcher, SIGNAL(foregroundLost()), SLOT(lostForeground()));
mDataBuffer = HBufC8::New(RProperty::KMaxPropertySize);
if (mDataBuffer) {
mPtr.Set(mDataBuffer->Des());
mInfoProperty.Attach(PropertyCategoryUid, InfoKey);
}
mServerStatus = new HbDeviceDialogServerStatus(false);
// hbsplashgenerator will not have any Qt widget shown (and
// thus created) so we cannot rely on foreground-background
// notifications. Instead, invoke gainedForeground manually.
RProcess me;
if (me.SecureId().iId == splashGenServerSecureId) {
QMetaObject::invokeMethod(this, "gainedForeground", Qt::QueuedConnection);
}
me.Close();
}
}
void HbSystemInfoPrivate::start()
{
if (mInfoProperty.Handle()) {
mServerStatus->enableMonitoring(true);
mInfoProperty.Subscribe(iStatus);
SetActive();
}
}
void HbSystemInfoPrivate::readDeviceInfo()
{
int error(KErrGeneral);
if (mDataBuffer) {
mPtr.Zero();
error = mInfoProperty.Get(PropertyCategoryUid, InfoKey, mPtr);
}
if (error == KErrNone) {
QByteArray resArray( (const char*) mPtr.Ptr(), mPtr.Size() );
QDataStream stream( &resArray, QIODevice::ReadOnly);
DeviceSystemInfo sysInfo;
stream >> sysInfo;
dataReceived(sysInfo);
}
}
void HbSystemInfoPrivate::writeDeviceInfo()
{
QMutexLocker locker(&mutex);
QByteArray array;
QDataStream stream(&array, QIODevice::WriteOnly);
stream << mDeviceSystemInfo;
//write data
TPtr8 ptr( reinterpret_cast<TUint8*>(array.data()),
array.size(), array.size());
mInfoProperty.Set(PropertyCategoryUid, InfoKey, ptr);
}
void HbSystemInfoPrivate::dataReceived(const DeviceSystemInfo& info)
{
Q_Q(HbSystemInfo);
bool modeChanged = info.networkMode != mDeviceSystemInfo.networkMode;
bool statusChanged = info.networkStatus != mDeviceSystemInfo.networkStatus;
if (modeChanged) {
mDeviceSystemInfo.networkMode = info.networkMode;
}
if (statusChanged) {
mDeviceSystemInfo.networkStatus = info.networkStatus;
}
if (modeChanged || statusChanged) {
emit q->networkModeChanged((QSystemNetworkInfo::NetworkMode)mDeviceSystemInfo.networkMode,
(QSystemNetworkInfo::NetworkStatus)mDeviceSystemInfo.networkStatus);
}
if (info.signalStrength != mDeviceSystemInfo.signalStrength) {
mDeviceSystemInfo.signalStrength = info.signalStrength;
emit q->networkSignalStrengthChanged((QSystemNetworkInfo::NetworkMode)mDeviceSystemInfo.networkMode,
mDeviceSystemInfo.signalStrength);
}
if (info.powerState != mDeviceSystemInfo.powerState) {
mDeviceSystemInfo.powerState = info.powerState;
emit q->powerStateChanged(((QSystemDeviceInfo::PowerState)mDeviceSystemInfo.powerState));
}
if (info.batteryLevel != mDeviceSystemInfo.batteryLevel) {
mDeviceSystemInfo.batteryLevel = info.batteryLevel;
emit q->batteryLevelChanged(mDeviceSystemInfo.batteryLevel);
}
}
void HbSystemInfoPrivate::DoCancel()
{
if (mListening) {
mInfoProperty.Cancel();
mListening = false;
mServerStatus->enableMonitoring(false);
}
}
void HbSystemInfoPrivate::RunL()
{
int result = iStatus.Int();
if (result != KErrCancel) {
start();
}
if (result == KErrNone) {
readDeviceInfo();
}
}
void HbSystemInfoPrivate::setNetworkStatus(
QSystemNetworkInfo::NetworkMode networkMode,
QSystemNetworkInfo::NetworkStatus networkStatus)
{
bool changed(false);
if (networkMode != mDeviceSystemInfo.networkMode) {
mDeviceSystemInfo.networkMode = networkMode;
changed = true;
}
if (networkStatus != mDeviceSystemInfo.networkStatus) {
mDeviceSystemInfo.networkStatus = networkStatus;
changed = true;
}
if (changed) {
writeDeviceInfo();
}
}
void HbSystemInfoPrivate::setNetworkSignalStrength(
QSystemNetworkInfo::NetworkMode mode,
int strength)
{
bool changed(false);
if (mode != mDeviceSystemInfo.networkMode) {
mDeviceSystemInfo.networkMode = mode;
changed = true;
}
if (strength != mDeviceSystemInfo.signalStrength) {
mDeviceSystemInfo.signalStrength = strength;
changed = true;
}
if (changed) {
writeDeviceInfo();
}
}
void HbSystemInfoPrivate::setNetworkMode(QSystemNetworkInfo::NetworkMode mode)
{
if (mode != mDeviceSystemInfo.networkMode) {
mDeviceSystemInfo.networkMode = mode;
mDeviceSystemInfo.networkStatus = mSystemNetworkInfo->networkStatus(mode);
mDeviceSystemInfo.signalStrength = QSystemNetworkInfo::networkSignalStrength(mode);
writeDeviceInfo();
}
}
void HbSystemInfoPrivate::setBatteryLevel(int level)
{
if (level != mDeviceSystemInfo.batteryLevel) {
mDeviceSystemInfo.batteryLevel = level;
writeDeviceInfo();
}
}
void HbSystemInfoPrivate::setPowerState(QSystemDeviceInfo::PowerState state)
{
if (state != mDeviceSystemInfo.powerState) {
mDeviceSystemInfo.powerState = state;
writeDeviceInfo();
}
}
void HbSystemInfoPrivate::lostForeground()
{
// Statusbars are rendered in the background by hbsplashgenerator
// so cannot stop listening in that case.
RProcess me;
if (mListening && me.SecureId().iId != splashGenServerSecureId) {
HbDeviceDialogServerStatus::StatusFlags flags = mServerStatus->status();
if ((flags & HbDeviceDialogServerStatus::ShowingDialog) == HbDeviceDialogServerStatus::NoFlags ||
flags & HbDeviceDialogServerStatus::ShowingScreenSaver) {
mInfoProperty.Cancel();
Cancel();
mListening = false;
}
}
me.Close();
}
void HbSystemInfoPrivate::gainedForeground()
{
if (!mListening) {
start();
readDeviceInfo();
mListening = true;
}
}
QSystemNetworkInfo::NetworkStatus HbSystemInfoPrivate::networkStatus() const
{
return mDeviceSystemInfo.networkStatus;
}
int HbSystemInfoPrivate::networkSignalStrength() const
{
return mDeviceSystemInfo.signalStrength;
}
QSystemNetworkInfo::NetworkMode HbSystemInfoPrivate::networkMode() const
{
return mDeviceSystemInfo.networkMode;
}
int HbSystemInfoPrivate::batteryLevel() const
{
return mDeviceSystemInfo.batteryLevel;
}
QSystemDeviceInfo::PowerState HbSystemInfoPrivate::powerState() const
{
return mDeviceSystemInfo.powerState;
}
bool HbSystemInfoPrivate::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ApplicationActivate) {
gainedForeground();
} else if (event->type() == QEvent::ApplicationDeactivate) {
lostForeground();
}
return QObject::eventFilter(obj, event);
}