| // Copyright 2023 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /// The system activity governor (SAG) is a subsystem of the power framework |
| /// that manages the execution and suspend state of the hardware platform. It |
| /// also allows observers to watch for suspend/resume transitions of the |
| /// platform. |
| /// |
| /// Other components can create dependencies on SAG's power elements with |
| /// [`fuchsia.power.broker/ElementControl`] to influence SAG's behavior |
| /// including preventing system suspension and/or changing the platform resume |
| /// latency for the next suspension. |
| /// |
| /// The power elements that SAG creates and manages are as follows: |
| /// * [`fuchsia.power.system/ExecutionState`] |
| /// * [`fuchsia.power.system/ExecutionResumeLatency`] |
| /// * [`fuchsia.power.system/WakeHandling`] |
| /// * [`fuchsia.power.system/FullWakeHandling`] |
| /// * [`fuchsia.power.system/ApplicationActivity`] |
| /// |
| /// # Internal Dependency Diagram |
| /// ``` |
| /// +--------------------+ +---------------------------------+ |
| /// | **ExecutionState** | | **ApplicationActivity** | |
| /// +--------------------+ +---------------------------------+ |
| /// | ACTIVE |<-----------------| ACTIVE | |
| /// +--------------------+ +---------------------------------+ |
| /// | WAKE_HANDLING |<--------+ | INACTIVE | |
| /// | |<------+ | +---------------------------------+ |
| /// +--------------------+ | | |
| /// | INACTIVE | | | +---------------------------------+ |
| /// +--------------------+ | | | **WakeHandling** | |
| /// | | +---------------------------------+ |
| /// | +--------| ACTIVE | |
| /// | +---------------------------------+ |
| /// | | INACTIVE | |
| /// | +---------------------------------+ |
| /// | |
| /// | +---------------------------------+ |
| /// | | **FullWakeHandling** | |
| /// | +---------------------------------+ |
| /// +----------| ACTIVE | |
| /// +---------------------------------+ |
| /// | INACTIVE | |
| /// +---------------------------------+ |
| /// |
| /// +---------------------------------+ |
| /// | **ExecutionResumeLatency** | |
| /// +---------------------------------+ |
| /// | SUSPEND_STATE_N | |
| /// +---------------------------------+ |
| /// | ... | |
| /// +---------------------------------+ |
| /// | SUSPEND_STATE_1 | |
| /// +---------------------------------+ |
| /// | SUSPEND_STATE_0 | |
| /// +---------------------------------+ |
| /// ``` |
| /// |
| /// # Usage |
| /// |
| /// To prevent system suspension, a component can create an active dependency |
| /// using the `active_dependency_token` from `ApplicationActivity` or |
| /// `WakeHandling`. If the dependency causes the power level of |
| /// `ApplicationActivity` and/or `WakeHandling` to be raised to |
| /// [`fuchsia.power.system/ApplicationActivityPowerLevel.ACTIVE`] and/or |
| /// [`fuchsia.power.system/WakeHandlingPowerLevel.ACTIVE`], respectively, SAG |
| /// will not trigger system suspension until their power levels drop to |
| /// `INACTIVE`. |
| /// |
| /// To change the platform resume latency, a component can create an active |
| /// dependency using the `active_dependency_token` from |
| /// `ExecutionResumeLatency`. If the dependency causes the power level of |
| /// `ExecutionResumeLatency` to be raised, SAG will request a suspend state with |
| /// an appropriate resume latency for that power level. |
| /// |
| /// If a component is managing a power element that requires the platform to be |
| /// in a specific state, a passive dependency can be created on |
| /// `ExecutionState`. When `ExecutionState` changes its power level, all |
| /// dependent power elements will power down first. Ideally, this forces the |
| /// entire system into a configuration with a lower power consumption as the |
| /// power level of `ExecutionState` decreases. |
| @available(added=HEAD) |
| library fuchsia.power.system; |
| |
| using fuchsia.power.broker; |
| using zx; |
| |
| /// Holds a token to the execution state power element. |
| /// |
| /// Power elements intentionally cannot take active dependencies on this power |
| /// element. Elements that need to force the execution state to ACTIVE can use |
| /// ApplicationActivity which provides more semantic meaning to the |
| /// dependencies. |
| /// |
| /// [`fuchsia.power.system/ExecutionStateLevel`] defines the power levels supported by this power element. |
| type ExecutionState = resource table { |
| 1: passive_dependency_token fuchsia.power.broker.DependencyToken; |
| }; |
| |
| /// Execution state power levels |
| /// |
| /// Elements should take a passive dependency on `ExecutionStateLevel::ACTIVE` |
| /// to ensure that the element will be suspended when the rest of the system |
| /// suspends. |
| /// |
| /// Drivers can take a passive dependency on either |
| /// `ExecutionStateLevel::WAKE_HANDLING` or `ExecutionStateLevel::ACTIVE` and |
| /// request a persistent lease on this state to ensure that their element's |
| /// power level is always activated when the system comes out of a suspend |
| /// state. |
| type ExecutionStateLevel = flexible enum : uint8 { |
| INACTIVE = 0; |
| WAKE_HANDLING = 1; |
| ACTIVE = 2; |
| }; |
| |
| /// Holds tokens to the execution resume latency power element and its |
| /// supported resume latencies. |
| /// |
| /// The execution resume latency power element represents the |
| /// suspension-to-resume delay that must be met by the hardware platform. |
| /// |
| /// The execution resume latency power element's power levels are platform and |
| /// hardware dependent. The power levels supported by the power element match |
| /// the index of the resume latency in the table, i.e. The item at index 0 in |
| /// `resume_latencies` is represented by power level 0, the item at index 1 is |
| /// represented by power level 1, and so on. |
| type ExecutionResumeLatency = resource table { |
| 1: passive_dependency_token fuchsia.power.broker.DependencyToken; |
| 2: active_dependency_token fuchsia.power.broker.DependencyToken; |
| 3: resume_latencies vector<zx.Duration>:MAX; |
| }; |
| |
| /// Holds tokens to the full wake handling power element. |
| /// |
| /// [`fuchsia.power.system/FullWakeHandlingLevel`] defines the power levels supported by this power element. |
| type FullWakeHandling = resource table { |
| 1: active_dependency_token fuchsia.power.broker.DependencyToken; |
| }; |
| |
| /// Full wake handling power levels |
| /// |
| /// Driver power elements should take an active dependency on |
| /// `FullWakeHandlingLevel::ACTIVE` if it expects the system to perform a full |
| /// wakeup. While the drivers are handling a wake event, they should request a |
| /// lease to pull the state to Active, and drop the release once the event is |
| /// fully handled. |
| type FullWakeHandlingLevel = flexible enum : uint8 { |
| INACTIVE = 0; |
| ACTIVE = 1; |
| }; |
| |
| /// Holds tokens to the wake handling power element. |
| /// |
| /// [`fuchsia.power.system/WakeHandlingLevel`] defines the power levels supported by this power element. |
| type WakeHandling = resource table { |
| 1: active_dependency_token fuchsia.power.broker.DependencyToken; |
| }; |
| |
| /// Wake handling power levels |
| /// |
| /// Driver power elements should take an active dependency on |
| /// `WakeHandlingLevel::ACTIVE` if it does NOT expect the system to |
| /// perform a full wakeup. While the drivers are handling a wake event, they |
| /// should request a lease to pull the state to Active, and drop the release |
| /// once the event is fully handled. |
| type WakeHandlingLevel = flexible enum : uint8 { |
| INACTIVE = 0; |
| ACTIVE = 1; |
| }; |
| |
| /// Holds tokens to the application activity power element. |
| /// |
| /// [`fuchsia.power.system/ApplicationActivityLevel`] defines the power levels supported by this power element. |
| type ApplicationActivity = resource table { |
| 1: active_dependency_token fuchsia.power.broker.DependencyToken; |
| }; |
| |
| /// Application activity power levels |
| /// |
| /// Elements that need to keep the system from suspending should take an active |
| /// dependency on `ApplicationActivityLevel::ACTIVE`. When these components are |
| /// performing work, they should request a lease to ensure the system remains |
| /// active, and drop the lease when they are done. |
| type ApplicationActivityLevel = flexible enum : uint8 { |
| INACTIVE = 0; |
| ACTIVE = 1; |
| }; |
| |
| /// A collection of power elements that are managed by the activity governor. |
| type PowerElements = resource table { |
| 1: execution_state ExecutionState; |
| 2: execution_resume_latency ExecutionResumeLatency; |
| 3: application_activity ApplicationActivity; |
| 4: full_wake_handling FullWakeHandling; |
| 5: wake_handling WakeHandling; |
| }; |
| |
| /// A listener for activity governor events. |
| open protocol ActivityGovernorListener { |
| /// Called when the activity governor detects a system resume. |
| /// |
| /// This is only called when the wakeup reason returned by the platform |
| /// requires a full system resume. |
| /// The server is expected to respond once it has performed the operations |
| /// required to keep the system awake, if needed. |
| strict OnResume() -> (); |
| |
| /// Called when the activity governor detects a system suspension. |
| /// |
| /// There is no guarantee the server will receive this message before |
| /// suspension is triggered by the platform. |
| flexible OnSuspend(); |
| }; |
| |
| /// A service for exposing events and power elements managed by the system |
| /// activity governor (SAG). |
| /// |
| /// SAG is responsible for managing the execution state and resume-from-suspend |
| /// latency of the hardware platform. The hardware platform consists of the |
| /// components required to execute code on the device. This typically includes |
| /// the CPU, memory, operating system, and other components required for these |
| /// components to function (clock trees, power domains, etc.). |
| @discoverable |
| open protocol ActivityGovernor { |
| // TODO(b/315994898): Provide tokens more granularly once client usage |
| // patterns are better understood. |
| |
| /// Gets the power elements owned by the activity governor. |
| /// |
| /// If an error occurs while the server is registering a power element with |
| /// the power broker or an error occurs while creating a token for a power |
| /// element, then the channel to `ActivityGovernor` will be closed by the |
| /// server and no response will be returned. |
| flexible GetPowerElements() -> (PowerElements); |
| |
| /// Registers a listener for activity governor events. |
| /// |
| /// If there is an error in registering the listener, then the given |
| /// `ActivityGovernorListener` channel will be closed before the response |
| /// is sent. |
| /// |
| /// To unregister, close the `ActivityGovernorListener` channel. |
| flexible RegisterListener(resource table { |
| /// The client end of the service that receives activity governor events. |
| /// |
| /// Required. |
| 1: listener client_end:ActivityGovernorListener; |
| // TODO(b/315994974): Handle filtering by wakeup reason. |
| }) -> (); |
| }; |