Configure governors
A CPU governor controls how the CPU raises and lowers its frequency in response to the demands the user is placing on their device. Governors have a large impact on performance and power save.
Consider the following before selecting a governor:
- Performance. Consider the trade-offs between more speed and power usage.
- Power save. Being very battery friendly may correspond to less speed (or sometimes smoothness).
- Stability. Some governors are unstable and some are rock solid.
- Smoothness (or Fluidity). Smoothness is not the same as speed; a governor can be fast but not smooth. To test smoothness, scroll pages down/up or open and close apps. More smoothness equates to a better user experience.
Governor types
You can use one of several governor types to configure the CPU, all of which are contained in a enumerator called GovernorType. Each GovernorType is also represented by a class in the API.
| Governor | Type | Class | Description |
|---|---|---|---|
| Performance | GovernorType.PERFORMANCE | GovernorPerformance | Sets the CPU statically to the highest frequency |
| Powersave | GovernorType.POWERSAVE | GovernorPowerSave |
Sets the CPU statically to the lowest frequency |
| Userspace | GovernorType.USERSPACE | GovernorUserSpace | Sets the CPU statically to the user-specified frequencies |
| Ondemand | GovernorType.ONDEMAND | GovernorOnDemand |
Sets the CPU depending on the current usage. It jumps to max speed when there is load on the CPU. If the CPU load abates, it slowly steps back down through the kernel's frequency steppings until it settles at the lowest frequency. |
| Conservative | GovernorType.CONSERVATIVE | GovernorConservative |
Sets the CPU depending on the current usage. It gracefully increases and decreases the CPU speed rather than jumping to the maximum the moment there is load on the CPU. |
| Interactive | GovernorType.INTERACTIVE | GovernorInteractive |
Sets the CPU depending on the current usage. This governor is more aggressive about scaling the CPU speed up in response to CPU-intensive activity. |
To obtain the list of available governor types supported by the CPU, use the getAvaliableGovernorTypes() method of CPUManager.
Get available governor types
import com.digi.android.system.cpu.CPUManager;
import com.digi.android.system.cpu.GovernorType;
[...]
// Get the CPU manager.
CPUManager cpuManager = new CPUManager(context);
// Get the available governor types.
ArrayList<GovernorType> governorTypes = cpuManager.getAvailableGovernorTypes();
for (GovernorType type: governorTypes) {
System.out.println(type.getID() + ": " + type.getDescription());
}
[...]
Get and set the CPU governor
You can get and set the current CPU governor using the following methods:
| Method | Description |
|---|---|
| getGovernorType() | Returns the governor type the CPU is configured with |
| getGovernor() | Returns a Governor object corresponding to the governor that the CPU is configured with |
| setGovernorType(GovernorType) | Configures the CPU with the provided governor type and returns the corresponding Governor object |
If an error occurs during the reading or configuration process these methods may fail, throwing a CPUException.
Get and set current governor type
import com.digi.android.system.cpu.CPUManager;
import com.digi.android.system.cpu.Governor;
import com.digi.android.system.cpu.GovernorType;
[...]
CPUManager cpuManager = ...;
// Get the CPU governor type.
GovernorType governorType = cpuManager.getGovernorType();
System.out.println("Current CPU governor: " + governorType.getID());
// Configure the CPU to use the Powersave governor.
Governor governor = cpuManager.setGovernorType(GovernorType.POWERSAVE);
System.out.println("Configured new CPU governor: " + governor.getGovernorType());
[...]
The getGovernor() and setGovernorType(GovernorType) methods return a Governor object. You can cast this object to the corresponding governor class to access its specific features.
Governor classes
import com.digi.android.system.cpu.CPUManager;
import com.digi.android.system.cpu.Governor;
import com.digi.android.system.cpu.GovernorType;
[...]
CPUManager cpuManager = ...;
// Get the CPU governor type.
Governor governor = cpuManager.getGovernor();
// Cast governor depending on its type.
switch (governor.getGovernorType()) {
case GovernorType.PERFORMANCE:
GovernorPerformance performanceGovernor = (GovernorPerformance)governor;
// TODO Custom implementation.
break;
case GovernorType.POWERSAVE:
GovernorPowerSave powerSaveGovernor = (GovernorPowerSave)governor;
// TODO Custom implementation.
break;
case GovernorType.USERSPACE:
GovernorUserSpace userSpaceGovernor = (GovernorUserSpace)governor;
// TODO Custom implementation.
break;
case GovernorType.ONDEMAND:
GovernorOnDemand onDemandGovernor = (GovernorOnDemand)governor;
// TODO Custom implementation.
break;
case GovernorType.CONSERVATIVE:
GovernorConservative conservativeGovernor = (GovernorConservative)governor;
// TODO Custom implementation.
break;
case GovernorType.INTERACTIVE:
GovernorInteractive interactiveGovernor = (GovernorInteractive)governor;
// TODO Custom implementation.
break;
default:
// TODO Custom implementation.
break;
}
[...]
Configure governor parameters
Some governors are configurable and specify different parameters that can be read and set.
Performance, powersave, and userspace governors do not define any parameter. They just configure the CPU statically to the maximum, minimum, or user-specified frequency respectively when they are selected.
The configurable governors are:
- Ondemand
- Conservative
- Interactive
All of them define some common and specific accessible parameters:
| Parameter | Method | Description |
|---|---|---|
| sampling_rate | getSamplingRate() setSamplingRate(long) |
Represents in microseconds how often the kernel reads CPU usage and determines actions to take depending on frequency |
| sampling_rate_min | getMinSamplingRate() | Minimum sampling rate |
| up_threshold | getUpThreshold() setUpThreshold(int) |
Defines what the average CPU usage between the samplings of sampling_rate needs to be for the kernel to make a decision on whether it should increase the frequency |
| ignore_nice_load | isIgnoreNiceLoadEnabled() enableIgnoreNiceLoad() disableIgnoreNiceLoad() |
When disabled (its default), all processes are counted towards the 'CPU utilization' value. When enabled, the processes that are run with a 'nice' value will not count (and thus be ignored) in the overall usage calculation |
| sampling_down_factor | getSamplingDownFactor() setSamplingDownFactor(int) |
Controls the rate at which the kernel makes a decision on when to decrease the frequency while running at top speed |
| Parameter | Method | Description |
|---|---|---|
| sampling_rate | getSamplingRate() setSamplingRate(long) |
Represents in microseconds how often the kernel reads the CPU usage and determines actions to take based on frequency |
| sampling_rate_min | getMinSamplingRate() | Minimum sampling rate |
| up_threshold | getUpThreshold() setUpThreshold(int) |
Defines what the average CPU usage between the samplings of sampling_rate needs to be for the kernel to make a decision on whether it should increase the frequency |
| ignore_nice_load | isIgnoreNiceLoadEnabled() enableIgnoreNiceLoad() disableIgnoreNiceLoad() |
When disabled (its default), all processes are counted towards the 'CPU utilization' value. When enabled, the processes that are run with a 'nice' value will not count (and thus be ignored) in the overall usage calculation |
| sampling_down_factor | getSamplingDownFactor() setSamplingDownFactor(int) |
Controls the rate at which the kernel makes a decision on when to decrease the frequency while running at top speed |
| down_threshold | getDownThreshold() setDownThreshold(int) |
Defines what the average CPU usage between the samplings of sampling_rate needs to be for the kernel to make a decision on whether it should decrease the frequency |
| freq_step | getFreqStep() setFreqStep(int) |
Describes by what percentage steps the CPU frequency should be smoothly increased and decreased |
| Parameter | Method | Description |
|---|---|---|
| min_sample_time | getMinSampleTime() setMinSampleTime(long) |
Represents the minimum amount of microseconds to spend at the current frequency before ramping down |
| hispeed_freq | getHiSpeedFreq() setHiSpeedFreq(int) |
An intermediate "high speed" at which to initially ramp when CPU load hits the value specified in go_hispeed_load |
| go_hispeed_freq | getGoHiSpeedLoad() setGoHiSpeedLoad(int) |
The CPU load at which to ramp to the intermediate "high speed" specified in hispeed_freq |
| above_hispeed_delay | getAboveHiSpeedDelay() setAboveHiSpeedDelay(long) |
Once speed is set to hispeed_freq, time in microseconds to wait before bumping speed higher in response to continued high load |
| timer_rate | getTimerRate() setTimerRate(long) |
Sample rate in microseconds for reevaluating CPU load when the system is not idle |
| timer_slack | getTimerSlack() setTimerSlack(long) |
Maximum additional time in microseconds to defer handling the governor sampling timer beyond timer_rate when running at speeds above the minimum |
| boost | isBoostEnabled() enableBoost() disableBoost() |
When boost is enabled, immediately boosts the speed of all CPUs to at least hispeed_freq until boost is disabled again. When disabled, allows CPU speeds to drop below hispeed_freq to load as usual |
| bootspulse_duration | getBoostPulseDuration() setBoostPulseDuration(long) |
Amount of microseconds to hold CPU speed at hispeed_freq on a boost pulse before allowing speed to drop according to load as usual |
Configure governor parameters
import com.digi.android.system.cpu.CPUManager;
import com.digi.android.system.cpu.GovernorType;
import com.digi.android.system.cpu.GovernorInteractive;
[...]
CPUManager cpuManager = ...;
// Set the interactive governor.
GovernorInteractive interactiveGovernor = (GovernorInteractive)cpuManager.setGovernorType(GovernorType.INTERACTIVE);
// Configure the governor.
interactiveGovernor.setMinSampleTime(80000);
interactiveGovernor.setTimerRate(20000);
[...]
// Read some governor parameters.
System.out.println("High speed frequency: " + interactiveGovernor.getHiSpeedFreq());
System.out.println("Boost enabled: " + interactiveGovernor.getBoost());
[...]
| Example: CPU management |
|---|
|
The CPU Management Sample Application demonstrates the CPU API. In this example, you can enable and disable the CPU cores, configure frequencies, and select and set up the governor while monitoring the total CPU usage as well as the usage of each core.
You can import the example using Digi's Android Studio plugin. For more information, see Import a Digi sample application. To view the application source code, go to the GitHub repository. |
