blob: 91b5edd10a18c945d40a93c9ff91895bf22f74ce [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package power
import (
"context"
"time"
"github.com/godbus/dbus"
pmpb "chromiumos/system_api/power_manager_proto"
"chromiumos/tast/errors"
"chromiumos/tast/local/dbusutil"
"chromiumos/tast/local/upstart"
)
const (
dbusName = "org.chromium.PowerManager"
dbusPath = "/org/chromium/PowerManager"
dbusInterface = "org.chromium.PowerManager"
)
// PowerManager is used to interact with the powerd process over D-Bus.
// For detailed spec of each D-Bus method, please find
// src/platform2/power_manager/dbus_bindings/org.chromium.PowerManager.xml
type PowerManager struct { // NOLINT
conn *dbus.Conn
obj dbus.BusObject
}
// UserActivityType is a status code for the PowerManager related D-Bus methods.
type UserActivityType int32
// NewPowerManager connects to power_manager via D-Bus and returns a PowerManager object.
func NewPowerManager(ctx context.Context) (*PowerManager, error) {
conn, obj, err := dbusutil.Connect(ctx, dbusName, dbusPath)
if err != nil {
return nil, err
}
return &PowerManager{conn, obj}, nil
}
// GetSwitchStates calls PowerManager.GetSwitchStates D-Bus method.
func (m *PowerManager) GetSwitchStates(ctx context.Context) (*pmpb.SwitchStates, error) {
ret := &pmpb.SwitchStates{}
err := dbusutil.CallProtoMethod(ctx, m.obj, dbusInterface+".GetSwitchStates", nil, ret)
return ret, err
}
// HandleWakeNotification calls PowerManager.HandleWakeNotification D-Bus method.
func (m *PowerManager) HandleWakeNotification(ctx context.Context) error {
return dbusutil.CallProtoMethod(ctx, m.obj, dbusInterface+".HandleWakeNotification", nil, nil)
}
// GetScreenBrightnessPercent returns current screen brightness by calling PowerManager.GetScreenBrightnessPercent D-Bus method.
func (m *PowerManager) GetScreenBrightnessPercent(ctx context.Context) (float64, error) {
call := m.obj.CallWithContext(ctx, dbusInterface+".GetScreenBrightnessPercent", 0)
if call.Err != nil {
return 0.0, errors.Wrap(call.Err, "failed to call GetScreenBrightnessPercent D-Bus method")
}
var brightness float64
if err := call.Store(&brightness); err != nil {
return 0.0, errors.Wrap(err, "failed to store GetScreenBrightnessPercent D-Bus method call response into float64 pointer")
}
return brightness, nil
}
// SetScreenBrightness updates the screen brightness to the specified percentage by calling
// PowerManager.SetScreenBrightness D-Bus method.
func (m *PowerManager) SetScreenBrightness(ctx context.Context, percentage float64) error {
if err := dbusutil.CallProtoMethod(ctx, m.obj, dbusInterface+".SetScreenBrightness",
&pmpb.SetBacklightBrightnessRequest{
Percent: &percentage,
}, nil); err != nil {
return errors.Wrap(err, "failed to call SetScreenBrightness D-Bus method")
}
return nil
}
// TurnOnDisplay turns on a display by sending a HandleWakeNotification to PowerManager
// to light up the display.
func TurnOnDisplay(ctx context.Context) error {
// Emitting wake notification to powerd should finish quickly -- so setting
// 10 seconds of timeout which should be long enough.
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
if err := upstart.EnsureJobRunning(ctx, "powerd"); err != nil {
return errors.Wrap(err, "failed to ensure powerd running")
}
powerd, err := NewPowerManager(ctx)
if err != nil {
return errors.Wrap(err, "failed to create a PowerManager object")
}
if err := powerd.HandleWakeNotification(ctx); err != nil {
return errors.Wrap(err, "failed to call HandleWakeNotification D-Bus method")
}
return nil
}