From 3d6bb94a9e7c80edc4b2a2321b464533a4a7f60b Mon Sep 17 00:00:00 2001 From: aavit Date: Wed, 10 Sep 2014 14:50:28 +0200 Subject: Rename DroidUtils -> B2QtUtils and refactor the API Preparing this module for being documented and presented for external users. - Renamed since this is for eLinux as well as eAndroid - Provide all settings as proper Q_PROPERTYs for easy QML access - Hide all the detailed audio stuff that's not useful for users - Implement a getter function for current backlight, so that we don't have to reset it to full every time this module is loaded - qmake now groks this as internal module, so get rid build kludges - hostname setting on eLinux fixed - getIPAddress() now returns ALL active addresses, and implentation is simplified Task-number: QTEE-704 Change-Id: I9f22d5531b5963ae7e78c840bcfe1edd6197f82a Reviewed-by: Samuli Piippo --- src/utils/b2qtdevice.cpp | 402 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 src/utils/b2qtdevice.cpp (limited to 'src/utils/b2qtdevice.cpp') diff --git a/src/utils/b2qtdevice.cpp b/src/utils/b2qtdevice.cpp new file mode 100644 index 0000000..c59859c --- /dev/null +++ b/src/utils/b2qtdevice.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** This file is part of Qt Enterprise Embedded. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** the contact form at http://qt.digia.com/ +** +****************************************************************************/ +#include "b2qtdevice.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_ANDROID_NO_SDK +#include +#include +#include +#include +#endif + +// When we can't query directly, at least remember what we have set it to +static quint8 knownBrightness = 255; + +B2QtDevice::B2QtDevice(QObject *parent) + : QObject(parent) +{ +} + +B2QtDevice::~B2QtDevice() +{ +} + +/*! + * Reboots the system. Does not return. + * + * \sa powerOff() + */ +void B2QtDevice::reboot() +{ + sync(); + ::reboot(RB_AUTOBOOT); + qWarning("reboot returned"); +} + + +/*! + * Shuts down the system. Does not return. + * + * \sa reboot() + */ +void B2QtDevice::powerOff() +{ + sync(); + ::reboot(RB_POWER_OFF); + qWarning("powerOff returned"); +} + + +/*! + * Sets the display brightness (i.e. the intensity of the backlight) + * to \a value. A value of 255 requests maximum brightness, while 0 requests + * minimum (typically, the backlight turned off). + * + * Returns true on success. + */ +bool B2QtDevice::setDisplayBrightness(quint8 value) +{ +#ifdef Q_OS_ANDROID_NO_SDK + const struct hw_module_t* module = 0; + if (hw_get_module(LIGHTS_HARDWARE_MODULE_ID, &module)) + return false; + if (!module || !module->methods || !module->methods->open) + return false; + + struct light_device_t* device = 0; + if (module->methods->open(module, LIGHT_ID_BACKLIGHT, (struct hw_device_t**)&device)) + return false; + if (!device || !device->set_light || !device->common.close) + return false; + + struct light_state_t state; + memset(&state, 0, sizeof(light_state_t)); + state.color = 0xff000000 | (value << 16) | (value << 8) | value; + if (!device->set_light(device, &state)) + return false; + + device->common.close(&device->common); + knownBrightness = value; + emit displayBrightnessChanged(value); + return true; +#else + return false; +#endif +} + + +/*! + * Returns the current backlight intensity. + * \sa setDisplayBrightness + */ +quint8 B2QtDevice::displayBrightness() const +{ + QFile sysFile(QStringLiteral("/sys/class/leds/lcd-backlight/brightness")); + if (sysFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) { + bool ok = false; + int sysVal = sysFile.read(3).simplified().toInt(&ok); + if (ok) + knownBrightness = qBound(0, sysVal, 255); + } + return knownBrightness; +} + + +/*! + * Gets the current IP address(es) of the device + */ +QString B2QtDevice::getIPAddress() const +{ + QStringList addresses; + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + QNetworkInterface::InterfaceFlags flags = interface.flags(); + if (flags.testFlag(QNetworkInterface::IsRunning) && !flags.testFlag(QNetworkInterface::IsLoopBack)) { + foreach (const QNetworkAddressEntry &entry, interface.addressEntries()) + addresses.append(entry.ip().toString().split('%').first()); + } + } + return addresses.join(QStringLiteral(", ")); +} + + +/*! + * Gets the current hostname of the device + */ +QString B2QtDevice::hostname() const +{ + QString name; +#ifdef Q_OS_ANDROID_NO_SDK + char prop_value[PROPERTY_VALUE_MAX]; + int len = property_get("net.hostname", prop_value, 0); + if (len) + name = QString::fromLocal8Bit(prop_value, len); +#else + name = QHostInfo::localHostName(); +#endif + return name; +} + + +/*! + * Sets new hostname for the device + */ +bool B2QtDevice::setHostname(const QString &name) +{ +#ifdef Q_OS_ANDROID_NO_SDK + property_set("net.hostname", name.toLocal8Bit().constData()); +#else + QByteArray lname = name.toLocal8Bit(); + if (::sethostname(lname.constData(), lname.length())) { + qWarning("Could not set system hostname"); + return false; + } + // Also store it for next boot: + QFile file(QStringLiteral("/etc/hostname")); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qWarning("Could not write to /etc/hostname"); + return false; + } + file.write(lname.append('\n')); + file.close(); +#endif + emit hostnameChanged(name); + return true; +} + + +/*! + * Sets the master volume to \a volume. + * The volume can range from 0 to 100 and is linear. + */ +void B2QtDevice::setMasterVolume(int volume) +{ +#ifdef Q_OS_ANDROID_NO_SDK + android::status_t rc; + volume = qBound(0, volume, 100); + rc = android::AudioSystem::setMasterVolume(android::AudioSystem::linearToLog(volume)); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while setting audio properties."; + else + emit masterVolumeChanged(volume); +#else + Q_UNUSED(volume) +#endif +} + + +/*! + * Returns the current master volume. + * The volume can range from 0 to 100 and is linear. + */ +int B2QtDevice::masterVolume() const +{ + float volume = 0; +#ifdef Q_OS_ANDROID_NO_SDK + android::status_t rc; + rc = android::AudioSystem::getMasterVolume(&volume); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while getting audio properties."; +#endif + return qBound(0, qRound(volume), 100); +} + +#ifdef Q_OS_ANDROID_NO_SDK +// Android audio handling + +enum AudioOrientation { + LandscapeAudioOrientation, + PortraitAudioOrientation, + SquareAudioOrientation, + UndefinedAudioOrientation, +}; + +enum AudioStreamType { + DefaultAudioStream = -1, + VoiceCallAudioStream = 0, + SystemAudioStream = 1, + RingAudioStream = 2, + MusicAudioStream = 3, + AlarmAudioStream = 4, + NotificationAudioStream = 5, + BluetoothAudioStream = 6, + EnforcedAudibleAudioStream = 7, + DTMFAudioStream = 8, + TTSAudioStream = 9 +}; + + +/* + \enum AudioStreamType + \value DefaultAudioStream + The default audio stream + + \value VoiceCallAudioStream + The audio stream for phone calls + + \value SystemAudioStream + The audio stream for system sounds + + \value RingAudioStream + The audio stream for the phone ring + + \value AlarmAudioStream + The audio stream for alarms + + \value NotificationAudioStream + The audio stream for notifications + + \value BluetoothAudioStream + The audio stream for audio transmitted over bluetooth + + \value EnforcedAudibleAudioStream + Sounds that cannot be muted by user and must be routed to speaker + + \value DTMFAudioStream + The audio stream for DTMF Tones + + \value TTSAudioStream + The audio stream for text-to-speech +*/ + +/* + * Sets the volume for a specific audio \a stream type to \a volume. + * The volume can range from 0 to 100 and is linear. + * All streams of the specified type will be affected. + * + * \sa setMasterVolume() + * \sa setStreamMute() + */ +void setStreamVolume(AudioStreamType streamType, int volume) +{ + android::status_t rc; + volume = qBound(0, volume, 100); + rc = android::AudioSystem::setStreamVolume(audio_stream_type_t(streamType), + android::AudioSystem::linearToLog(volume), 0); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while setting audio properties."; +} + +/* + * Mutes all audio \a streams of type \a streamType. + * + * \sa setStreamVolume() + * \sa setMasterMute() + */ +void setStreamMute(AudioStreamType streamType, bool mute) +{ + android::status_t rc; + rc = android::AudioSystem::setStreamMute(audio_stream_type_t(streamType), mute); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while setting audio properties."; +} + +void setOrientationForAudioSystem(AudioOrientation orientation) +{ + QString orientationString = QStringLiteral("undefined"); + switch (orientation) { + case LandscapeAudioOrientation: + orientationString = QStringLiteral("landscape"); + break; + case PortraitAudioOrientation: + orientationString = QStringLiteral("portrait"); + break; + case SquareAudioOrientation: + orientationString = QStringLiteral("square"); + break; + default: + break; + } + android::AudioSystem::setParameters(0, android::String8(QStringLiteral("orientation=%2") + .arg(orientationString).toLatin1().constData())); +} + + +/*! + * Sets the master mute to \a mute. Setting it to true will disable all + * sounds on the device. + * + * \sa setMasterVolume() + * \sa setStreamMute() + */ +void setMasterMute(bool mute) +{ + + android::status_t rc; + rc = android::AudioSystem::setMasterMute(mute); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while setting audio properties."; +} + +bool masterMute() +{ + bool mute = false; + android::status_t rc; + rc = android::AudioSystem::getMasterMute(&mute); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while getting audio properties."; + return mute; +} + +float streamVolume(AudioStreamType stream) +{ + float volume = NAN; + android::status_t rc; + rc = android::AudioSystem::getStreamVolume(audio_stream_type_t(stream), &volume, 0); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while getting audio properties."; + return volume; +} + +bool streamMute(AudioStreamType stream) +{ + bool mute = false; + android::status_t rc; + rc = android::AudioSystem::getStreamMute(audio_stream_type_t(stream), &mute); + if (rc != android::NO_ERROR) + qWarning() << Q_FUNC_INFO << "Error while getting audio properties."; + return mute; +} + +#endif + +/*! + * Initializes the audio subsystem, setting the volume to max. + * This is done during system startup, so there is normally no need to call this function from applications. + */ +void B2QtDevice::initAudio() +{ +#ifdef Q_OS_ANDROID_NO_SDK + // Set the audio orientation to something to force the HW driver to reconfigure + // audio routing (workaround for bug on Nexus 7) + setOrientationForAudioSystem(LandscapeAudioOrientation); + setMasterVolume(100); + setMasterMute(false); + setStreamVolume(SystemAudioStream, 100); + setStreamVolume(MusicAudioStream, 100); + setStreamVolume(NotificationAudioStream, 100); + setStreamVolume(EnforcedAudibleAudioStream, 100); +#endif +} -- cgit v1.2.3