00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "halpower.h"
00021
00022 #include <QtDBus/QDBusReply>
00023
00024 #include <kdebug.h>
00025
00026 #include "halsuspendjob.h"
00027
00028 #include <solid/deviceinterface.h>
00029 #include <solid/acadapter.h>
00030 #include <solid/battery.h>
00031 #include <solid/button.h>
00032 #include <solid/genericinterface.h>
00033
00034 HalPower::HalPower(QObject *parent, const QStringList & )
00035 : PowerManager(parent),
00036 m_halComputer("org.freedesktop.Hal",
00037 "/org/freedesktop/Hal/devices/computer",
00038 "org.freedesktop.Hal.Device",
00039 QDBusConnection::systemBus()),
00040 m_halPowerManagement("org.freedesktop.Hal",
00041 "/org/freedesktop/Hal/devices/computer",
00042 "org.freedesktop.Hal.Device.SystemPowerManagement",
00043 QDBusConnection::systemBus()),
00044 m_halCpuFreq("org.freedesktop.Hal",
00045 "/org/freedesktop/Hal/devices/computer",
00046 "org.freedesktop.Hal.Device.CPUFreq",
00047 QDBusConnection::systemBus()),
00048 m_halManager("org.freedesktop.Hal",
00049 "/org/freedesktop/Hal/Manager",
00050 "org.freedesktop.Hal.Manager",
00051 QDBusConnection::systemBus())
00052 {
00053 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString &)),
00054 this, SLOT(slotDeviceRemoved(const QString &)));
00055 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString &)),
00056 this, SLOT(slotDeviceAdded(const QString &)));
00057
00058 m_pluggedAdapterCount = 0;
00059 computeAcAdapters();
00060
00061 computeBatteries();
00062 updateBatteryStats();
00063
00064 computeButtons();
00065 }
00066
00067 HalPower::~HalPower()
00068 {
00069 QList<Solid::Device *> devices;
00070
00071 devices << m_acAdapters.values();
00072 devices << m_batteries.values();
00073 devices << m_buttons.values();
00074
00075 foreach (Solid::Device *dev, devices)
00076 {
00077 delete dev;
00078 }
00079 }
00080
00081 QStringList HalPower::supportedSchemes() const
00082 {
00083 return QStringList() << "performance" << "powersaving";
00084 }
00085
00086 QString HalPower::schemeDescription(const QString &schemeName) const
00087 {
00088 if (schemeName=="performance")
00089 {
00090 return "Use all the performances of the system";
00091 }
00092 else if (schemeName=="powersaving")
00093 {
00094 return "Try to keep as much power as possible to improve battery life";
00095 }
00096 else
00097 {
00098 return QString();
00099 }
00100
00101 return QString();
00102 }
00103
00104 QString HalPower::scheme() const
00105 {
00106
00107 return QString();
00108 }
00109
00110 bool HalPower::setScheme(const QString &name)
00111 {
00112 bool powersave;
00113
00114 if (name=="powersaving")
00115 {
00116 powersave = true;
00117 }
00118 else if (name=="performance")
00119 {
00120 powersave = false;
00121 }
00122 else
00123 {
00124 return false;
00125 }
00126
00127 QDBusReply<int> reply = m_halPowerManagement.call("SetPowerSave", powersave);
00128
00129 if (reply.isValid())
00130 {
00131 int code = reply;
00132 return code==0;
00133 }
00134 else
00135 {
00136 return false;
00137 }
00138 }
00139
00140 Solid::Control::PowerManager::BatteryState HalPower::batteryState() const
00141 {
00142 if (m_batteries.size()==0)
00143 {
00144 return Solid::Control::PowerManager::NoBatteryState;
00145 }
00146 else if (m_currentBatteryCharge <= m_criticalBatteryCharge)
00147 {
00148 return Solid::Control::PowerManager::Critical;
00149 }
00150 else if (m_currentBatteryCharge <= m_lowBatteryCharge)
00151 {
00152 return Solid::Control::PowerManager::Low;
00153 }
00154 else if (m_currentBatteryCharge <= m_warningBatteryCharge)
00155 {
00156 return Solid::Control::PowerManager::Warning;
00157 }
00158 else
00159 {
00160 return Solid::Control::PowerManager::Normal;
00161 }
00162 }
00163
00164 int HalPower::batteryChargePercent() const
00165 {
00166 if (!m_maxBatteryCharge) return 0;
00167
00168 return (m_currentBatteryCharge *100)/m_maxBatteryCharge;
00169 }
00170
00171 Solid::Control::PowerManager::AcAdapterState HalPower::acAdapterState() const
00172 {
00173 if (m_acAdapters.size()==0)
00174 {
00175 return Solid::Control::PowerManager::UnknownAcAdapterState;
00176 }
00177 else if (m_pluggedAdapterCount==0)
00178 {
00179 return Solid::Control::PowerManager::Unplugged;
00180 }
00181 else
00182 {
00183 return Solid::Control::PowerManager::Plugged;
00184 }
00185 }
00186
00187 Solid::Control::PowerManager::SuspendMethods HalPower::supportedSuspendMethods() const
00188 {
00189 Solid::Control::PowerManager::SuspendMethods supported = Solid::Control::PowerManager::UnknownSuspendMethod;
00190
00191 QDBusReply<bool> reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_hibernate");
00192
00193 if (reply.isValid())
00194 {
00195 bool can_suspend = reply;
00196 if (can_suspend)
00197 {
00198 supported |= Solid::Control::PowerManager::ToRam;
00199 }
00200 }
00201 else
00202 {
00203 kDebug() << reply.error().name() << ": " << reply.error().message();
00204 }
00205
00206 reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_hibernate");
00207
00208 if (reply.isValid())
00209 {
00210 bool can_hibernate = reply;
00211 if (can_hibernate)
00212 {
00213 supported |= Solid::Control::PowerManager::ToDisk;
00214 }
00215 }
00216 else
00217 {
00218 kDebug() << reply.error().name() << ": " << reply.error().message();
00219 }
00220
00221 return supported;
00222 }
00223
00224 KJob *HalPower::suspend(Solid::Control::PowerManager::SuspendMethod method) const
00225 {
00226 return new HalSuspendJob(m_halPowerManagement,
00227 method, supportedSuspendMethods());
00228 }
00229
00230 Solid::Control::PowerManager::CpuFreqPolicies HalPower::supportedCpuFreqPolicies() const
00231 {
00232 QDBusReply<QStringList> reply = m_halCpuFreq.call("GetCPUFreqAvailableGovernors");
00233
00234 if (!reply.isValid())
00235 {
00236 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00237 }
00238 else
00239 {
00240 QStringList governors = reply;
00241 Solid::Control::PowerManager::CpuFreqPolicies policies = Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00242
00243 foreach (QString governor, governors)
00244 {
00245 if (governor == "ondemand")
00246 {
00247 policies|= Solid::Control::PowerManager::OnDemand;
00248 }
00249 else if (governor == "userspace")
00250 {
00251 policies|= Solid::Control::PowerManager::Userspace;
00252 }
00253 else if (governor == "powersave")
00254 {
00255 policies|= Solid::Control::PowerManager::Powersave;
00256 }
00257 else if (governor == "performance")
00258 {
00259 policies|= Solid::Control::PowerManager::Performance;
00260 }
00261 else if (governor == "conservative")
00262 {
00263 policies|= Solid::Control::PowerManager::Conservative;
00264 }
00265 else
00266 {
00267 kWarning() << "Unknown governor: " << governor ;
00268 }
00269 }
00270
00271 return policies;
00272 }
00273 }
00274
00275 Solid::Control::PowerManager::CpuFreqPolicy HalPower::cpuFreqPolicy() const
00276 {
00277 QDBusReply<QString> reply = m_halCpuFreq.call("GetCPUFreqGovernor");
00278
00279 if (!reply.isValid())
00280 {
00281 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00282 }
00283 else
00284 {
00285 QString governor = reply;
00286
00287 if (governor == "ondemand")
00288 {
00289 return Solid::Control::PowerManager::OnDemand;
00290 }
00291 else if (governor == "userspace")
00292 {
00293 return Solid::Control::PowerManager::Userspace;
00294 }
00295 else if (governor == "powersave")
00296 {
00297 return Solid::Control::PowerManager::Powersave;
00298 }
00299 else if (governor == "performance")
00300 {
00301 return Solid::Control::PowerManager::Performance;
00302 }
00303 else if (governor == "conservative")
00304 {
00305 return Solid::Control::PowerManager::Conservative;
00306 }
00307 else
00308 {
00309 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00310 }
00311 }
00312 }
00313
00314 bool HalPower::setCpuFreqPolicy(Solid::Control::PowerManager::CpuFreqPolicy newPolicy)
00315 {
00316 QString governor;
00317
00318 switch(newPolicy)
00319 {
00320 case Solid::Control::PowerManager::OnDemand:
00321 governor = "ondemand";
00322 break;
00323 case Solid::Control::PowerManager::Userspace:
00324 governor = "userspace";
00325 break;
00326 case Solid::Control::PowerManager::Powersave:
00327 governor = "powersave";
00328 break;
00329 case Solid::Control::PowerManager::Performance:
00330 governor = "performance";
00331 break;
00332 case Solid::Control::PowerManager::Conservative:
00333 governor = "conservative";
00334 break;
00335 default:
00336 return false;
00337 }
00338
00339 QDBusReply<int> reply = m_halCpuFreq.call("SetCPUFreqGovernor", governor);
00340
00341 if (reply.isValid())
00342 {
00343 int code = reply;
00344 return code==0;
00345 }
00346 else
00347 {
00348 return false;
00349 }
00350 }
00351
00352 bool HalPower::canDisableCpu(int ) const
00353 {
00354 return false;
00355 }
00356
00357 bool HalPower::setCpuEnabled(int , bool )
00358 {
00359 return false;
00360 }
00361
00362 Solid::Control::PowerManager::BrightnessControlsList HalPower::brightnessControlsAvailable()
00363 {
00364 Solid::Control::PowerManager::BrightnessControlsList deviceList;
00365 foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList())
00366 {
00367 deviceList.insert(name, Solid::Control::PowerManager::Screen);
00368 }
00369 foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList())
00370 {
00371 deviceList.insert(name, Solid::Control::PowerManager::Keyboard);
00372 }
00373 return deviceList;
00374 }
00375
00376 float HalPower::brightness(const QString &device)
00377 {
00378 float brightness;
00379 if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
00380 {
00381 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
00382 brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
00383 if(deviceInterface.lastError().isValid())
00384 {
00385 return 0;
00386 }
00387 else
00388 {
00389 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00390 int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
00391 return (float)(100*(brightness/(levels-1)));
00392 }
00393 }
00394 if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
00395 {
00396 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus());
00397 brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
00398 if(deviceInterface.lastError().isValid())
00399 {
00400 return 0;
00401 }
00402 else
00403 {
00404 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00405 int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
00406 return (float)(100*(brightness/(levels-1)));
00407 }
00408 }
00409 return 0;
00410 }
00411
00412 bool HalPower::setBrightness(float brightness, const QString &device)
00413 {
00414 if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
00415 {
00416 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00417 int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
00418 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
00419 deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0)));
00420 if(!deviceInterface.lastError().isValid())
00421 {
00422 emit(brightnessChanged(brightness));
00423 return true;
00424 }
00425 }
00426 if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
00427 {
00428 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00429 int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
00430 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus());
00431 deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0)));
00432 if(!deviceInterface.lastError().isValid())
00433 {
00434 emit(brightnessChanged(brightness));
00435 return true;
00436 }
00437 }
00438 return false;
00439 }
00440
00441 void HalPower::computeAcAdapters()
00442 {
00443 QList<Solid::Device> adapters
00444 = Solid::Device::listFromType(Solid::DeviceInterface::AcAdapter);
00445
00446 foreach (Solid::Device adapter, adapters)
00447 {
00448 m_acAdapters[adapter.udi()] = new Solid::Device(adapter);
00449 connect(m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
00450 this, SLOT(slotPlugStateChanged(bool)));
00451
00452 if (m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()!=0
00453 && m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()->isPlugged())
00454 {
00455 m_pluggedAdapterCount++;
00456 }
00457 }
00458 }
00459
00460 void HalPower::computeBatteries()
00461 {
00462 QList<Solid::Device> batteries
00463 = Solid::Device::listFromQuery("Battery.type == 'PrimaryBattery'");
00464
00465 foreach (Solid::Device battery, batteries)
00466 {
00467 m_batteries[battery.udi()] = new Solid::Device(battery);
00468 connect(m_batteries[battery.udi()]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
00469 this, SLOT(updateBatteryStats()));
00470 }
00471
00472 updateBatteryStats();
00473 }
00474
00475 void HalPower::computeButtons()
00476 {
00477 QList<Solid::Device> buttons
00478 = Solid::Device::listFromType(Solid::DeviceInterface::Button);
00479
00480 foreach (Solid::Device button, buttons)
00481 {
00482 m_buttons[button.udi()] = new Solid::Device(button);
00483 connect(m_buttons[button.udi()]->as<Solid::Button>(), SIGNAL(pressed(Solid::Button::ButtonType, const QString &)),
00484 this, SLOT(slotButtonPressed(Solid::Button::ButtonType)));
00485 }
00486 }
00487
00488 void HalPower::updateBatteryStats()
00489 {
00490 m_currentBatteryCharge = 0;
00491 m_maxBatteryCharge = 0;
00492 m_warningBatteryCharge = 0;
00493 m_lowBatteryCharge = 0;
00494 m_criticalBatteryCharge = 0;
00495
00496 foreach (Solid::Device *d, m_batteries.values())
00497 {
00498 Solid::GenericInterface *interface = d->as<Solid::GenericInterface>();
00499
00500 if (interface == 0) continue;
00501
00502 m_currentBatteryCharge+= interface->property("battery.charge_level.current").toInt();
00503 m_maxBatteryCharge+= interface->property("battery.charge_level.last_full").toInt();
00504 m_warningBatteryCharge+= interface->property("battery.charge_level.warning").toInt();
00505 m_lowBatteryCharge+= interface->property("battery.charge_level.low").toInt();
00506 }
00507
00508 m_criticalBatteryCharge = m_lowBatteryCharge/2;
00509 }
00510
00511 void HalPower::slotPlugStateChanged(bool newState)
00512 {
00513 if (newState)
00514 {
00515 if(m_pluggedAdapterCount == 0)
00516 {
00517 emit acAdapterStateChanged(Solid::Control::PowerManager::Plugged);
00518 }
00519 m_pluggedAdapterCount++;
00520 }
00521 else
00522 {
00523 if(m_pluggedAdapterCount == 1)
00524 {
00525 emit acAdapterStateChanged(Solid::Control::PowerManager::Unplugged);
00526 }
00527 m_pluggedAdapterCount--;
00528 }
00529 }
00530
00531 void HalPower::slotButtonPressed(Solid::Button::ButtonType type)
00532 {
00533 Solid::Button *button = qobject_cast<Solid::Button *>(sender());
00534
00535 if (button == 0) return;
00536
00537 switch(type)
00538 {
00539 case Solid::Button::PowerButton:
00540 emit buttonPressed(Solid::Control::PowerManager::PowerButton);
00541 break;
00542 case Solid::Button::SleepButton:
00543 emit buttonPressed(Solid::Control::PowerManager::SleepButton);
00544 break;
00545 case Solid::Button::LidButton:
00546 if (button->stateValue())
00547 {
00548 emit buttonPressed(Solid::Control::PowerManager::LidClose);
00549 }
00550 else
00551 {
00552 emit buttonPressed(Solid::Control::PowerManager::LidOpen);
00553 }
00554 break;
00555 default:
00556 kWarning() << "Unknown button type" ;
00557 break;
00558 }
00559 }
00560
00561 void HalPower::slotDeviceAdded(const QString &udi)
00562 {
00563 Solid::Device *device = new Solid::Device(udi);
00564 if (device->is<Solid::AcAdapter>())
00565 {
00566 m_acAdapters[udi] = device;
00567 connect(m_acAdapters[udi]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
00568 this, SLOT(slotPlugStateChanged(bool)));
00569
00570 if (m_acAdapters[udi]->as<Solid::AcAdapter>()!=0
00571 && m_acAdapters[udi]->as<Solid::AcAdapter>()->isPlugged())
00572 {
00573 m_pluggedAdapterCount++;
00574 }
00575 }
00576 else if (device->is<Solid::Battery>())
00577 {
00578 m_batteries[udi] = device;
00579 connect(m_batteries[udi]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
00580 this, SLOT(updateBatteryStats()));
00581 }
00582 else if (device->is<Solid::Button>())
00583 {
00584 m_buttons[udi] = device;
00585 connect(m_buttons[udi]->as<Solid::Button>(), SIGNAL(pressed(int, const QString &)),
00586 this, SLOT(slotButtonPressed(int)));
00587 }
00588 else
00589 {
00590 delete device;
00591 }
00592 }
00593
00594 void HalPower::slotDeviceRemoved(const QString &udi)
00595 {
00596 Solid::Device *device = 0;
00597
00598 device = m_acAdapters.take(udi);
00599
00600 if (device!=0)
00601 {
00602 delete device;
00603
00604 m_pluggedAdapterCount = 0;
00605
00606 foreach (Solid::Device *d, m_acAdapters.values())
00607 {
00608 if (d->as<Solid::AcAdapter>()!=0
00609 && d->as<Solid::AcAdapter>()->isPlugged())
00610 {
00611 m_pluggedAdapterCount++;
00612 }
00613 }
00614
00615 return;
00616 }
00617
00618 device = m_batteries.take(udi);
00619
00620 if (device!=0)
00621 {
00622 delete device;
00623 updateBatteryStats();
00624 return;
00625 }
00626
00627 device = m_buttons.take(udi);
00628
00629 if (device!=0)
00630 {
00631 delete device;
00632 return;
00633 }
00634 }
00635
00636 #include "halpower.moc"