1 /***************************************************************************
2  *   Copyright (C) 2016 by Jan Grulich <jgrulich@redhat.com>               *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
18  ***************************************************************************/
19 
20 #include "wirelesspowersaving.h"
21 
22 #include "wirelesspowersavingadaptor.h"
23 
24 #include <powerdevilcore.h>
25 #include <powerdevil_debug.h>
26 
27 #include <KConfigGroup>
28 
29 #include <NetworkManagerQt/Manager>
30 
31 
32 namespace PowerDevil {
33 namespace BundledActions {
34 
WirelessPowerSaving(QObject * parent)35 WirelessPowerSaving::WirelessPowerSaving(QObject* parent)
36     : Action(parent)
37     , m_btManager(new BluezQt::Manager())
38     , m_currentProfileWifiOption(BundledActions::WirelessPowerSaving::TurnOff)
39     , m_currentProfileWwanOption(BundledActions::WirelessPowerSaving::TurnOff)
40     , m_currentProfileBtOption(BundledActions::WirelessPowerSaving::TurnOff)
41     , m_lastProfileWifiOption(BundledActions::WirelessPowerSaving::TurnOff)
42     , m_lastProfileWwanOption(BundledActions::WirelessPowerSaving::TurnOff)
43     , m_lastProfileBtOption(BundledActions::WirelessPowerSaving::TurnOff)
44     , m_lastWifiState(false)
45     , m_lastWwanState(false)
46     , m_lastBtState(false)
47 {
48     // DBus
49     new WirelessPowerSavingAdaptor(this);
50 
51     setRequiredPolicies(PowerDevil::PolicyAgent::None);
52 }
53 
onProfileUnload()54 void WirelessPowerSaving::onProfileUnload()
55 {
56     if (m_lastWifiState && m_currentProfileWifiOption == BundledActions::WirelessPowerSaving::TurnOff) {
57         setWirelessEnabled(true);
58     } else if (!m_lastWifiState && m_currentProfileWifiOption == BundledActions::WirelessPowerSaving::TurnOn) {
59         setWirelessEnabled(false);
60     }
61 
62     if (m_lastWwanState && m_currentProfileWwanOption == BundledActions::WirelessPowerSaving::TurnOff) {
63         setMobileBroadbandEnabled(true);
64     } else if (!m_lastWwanState && m_currentProfileWwanOption == BundledActions::WirelessPowerSaving::TurnOn) {
65         setMobileBroadbandEnabled(false);
66     }
67 
68     if (m_lastBtState && m_currentProfileBtOption == BundledActions::WirelessPowerSaving::TurnOff) {
69         setBluetoothEnabled(true);
70     } else if (!m_lastBtState && m_currentProfileBtOption == BundledActions::WirelessPowerSaving::TurnOn) {
71         setBluetoothEnabled(false);
72     }
73 }
74 
onWakeupFromIdle()75 void WirelessPowerSaving::onWakeupFromIdle()
76 {
77     // Nothing to do
78 }
79 
onIdleTimeout(int msec)80 void WirelessPowerSaving::onIdleTimeout(int msec)
81 {
82     Q_UNUSED(msec);
83     // Nothing to do
84 }
85 
onProfileLoad()86 void WirelessPowerSaving::onProfileLoad()
87 {
88     qCDebug(POWERDEVIL) << m_currentProfile << m_lastProfile;
89 
90     if (((m_currentProfile == QLatin1String("Battery") && m_lastProfile == QLatin1String("AC")) ||
91          (m_currentProfile == QLatin1String("LowBattery") && (m_lastProfile == QLatin1String("AC") || m_lastProfile == QLatin1String("Battery")))) &&
92          (((m_lastProfileWifiOption == BundledActions::WirelessPowerSaving::TurnOff && m_currentProfileWifiOption == BundledActions::WirelessPowerSaving::TurnOn) || m_currentProfileWifiOption == NoAction) &&
93           ((m_lastProfileWwanOption == BundledActions::WirelessPowerSaving::TurnOff && m_currentProfileWwanOption == BundledActions::WirelessPowerSaving::TurnOn) || m_currentProfileWwanOption == NoAction) &&
94           ((m_lastProfileBtOption == BundledActions::WirelessPowerSaving::TurnOff && m_currentProfileBtOption == BundledActions::WirelessPowerSaving::TurnOn) || m_currentProfileBtOption == NoAction))) {
95         // We don't want to change anything here
96         qCDebug(POWERDEVIL) << "Not changing anything, the current profile is more conservative";
97     } else {
98         QVariantMap args{
99             {{QLatin1String("wifiOption"), QVariant::fromValue((uint)m_currentProfileWifiOption)},
100              {QLatin1String("wwanOption"), QVariant::fromValue((uint)m_currentProfileWwanOption)},
101              {QLatin1String("btOption"), QVariant::fromValue((uint)m_currentProfileBtOption)}}
102         };
103 
104         trigger(args);
105     }
106 }
107 
triggerImpl(const QVariantMap & args)108 void WirelessPowerSaving::triggerImpl(const QVariantMap& args)
109 {
110     const PowerSavingOption wifiOption = (PowerSavingOption)args.value(QLatin1String("wifiOption")).toUInt();
111     const PowerSavingOption wwanOption = (PowerSavingOption)args.value(QLatin1String("wwanOption")).toUInt();
112     const PowerSavingOption btOption = (PowerSavingOption)args.value(QLatin1String("btOption")).toUInt();
113 
114     if (wifiOption == BundledActions::WirelessPowerSaving::TurnOff) {
115         setWirelessEnabled(false);
116     } else if (wifiOption == BundledActions::WirelessPowerSaving::TurnOn) {
117         setWirelessEnabled(true);
118     }
119 
120     if (wwanOption == BundledActions::WirelessPowerSaving::TurnOff) {
121         setMobileBroadbandEnabled(false);
122     } else if (wwanOption == BundledActions::WirelessPowerSaving::TurnOn) {
123         setMobileBroadbandEnabled(true);
124     }
125 
126     if (btOption == BundledActions::WirelessPowerSaving::TurnOff) {
127         setBluetoothEnabled(false);
128     } else if (btOption == BundledActions::WirelessPowerSaving::TurnOn) {
129         setBluetoothEnabled(true);
130     }
131 }
132 
isSupported()133 bool WirelessPowerSaving::isSupported()
134 {
135     /* Check if we can enable/disable bluetooth ???
136      * This would require to check if we can read/write from/to /dev/rfkill. Maybe Rfkill class from bluez-qt
137      * can be used for this, but it seems to be private class
138      */
139 
140     NMStringMap permissions = NetworkManager::permissions();
141     bool changeWifiAllowed = false;
142     bool changeWwanAllowed = false;
143     for (auto it = permissions.constBegin(); it != permissions.constEnd(); ++it) {
144         if (it.key() == QLatin1String("org.freedesktop.NetworkManager.enable-disable-wifi")) {
145             changeWifiAllowed = it.value() == QLatin1String("yes");
146         } else if (it.key() == QLatin1String("org.freedesktop.NetworkManager.enable-disable-wwan")) {
147             changeWwanAllowed = it.value() == QLatin1String("yes");
148         }
149     }
150 
151     return changeWifiAllowed || changeWwanAllowed;
152 }
153 
loadAction(const KConfigGroup & config)154 bool WirelessPowerSaving::loadAction(const KConfigGroup& config)
155 {
156     // Handle profile changes
157     m_lastProfile = m_currentProfile;
158     m_currentProfile = config.parent().name();
159 
160     qCDebug(POWERDEVIL) << "Profiles: " << m_currentProfile << m_lastProfile;
161 
162     m_lastProfileWifiOption = m_currentProfileWifiOption;
163     m_lastProfileWwanOption = m_currentProfileWwanOption;
164     m_lastProfileBtOption = m_currentProfileBtOption;
165 
166     if (config.hasKey("wifiOption")) {
167         m_currentProfileWifiOption = (PowerSavingOption)config.readEntry<uint>("wifiOption", 0);
168     }
169 
170     if (config.hasKey("wwanOption")) {
171         m_currentProfileWwanOption = (PowerSavingOption)config.readEntry<uint>("wwanOption", 0);
172     }
173 
174     if (config.hasKey("btOption")) {
175         m_currentProfileBtOption = (PowerSavingOption)config.readEntry<uint>("btOption", 0);
176     }
177 
178 
179     m_lastWifiState = NetworkManager::isWirelessEnabled();
180     m_lastWwanState = NetworkManager::isWwanEnabled();
181     m_lastBtState = !m_btManager->isBluetoothBlocked();
182 
183     return true;
184 }
185 
setBluetoothEnabled(bool enabled)186 void WirelessPowerSaving::setBluetoothEnabled(bool enabled)
187 {
188     m_btManager->setBluetoothBlocked(!enabled);
189 }
190 
setMobileBroadbandEnabled(bool enabled)191 void WirelessPowerSaving::setMobileBroadbandEnabled(bool enabled)
192 {
193     NetworkManager::setWwanEnabled(enabled);
194 }
195 
setWirelessEnabled(bool enabled)196 void WirelessPowerSaving::setWirelessEnabled(bool enabled)
197 {
198     NetworkManager::setWirelessEnabled(enabled);
199 }
200 
201 }
202 
203 }
204