Wake Locks - Android Platform Developer's Guide

Wake Locks
Wake locks are used by applications and services to request CPU resources.
A locked wakelock, depending on its type, prevents the system from entering suspend or other low-power states. This document describes how to employ wakelocks.
There are two settings for a wakelock:
WAKE_LOCK_SUSPEND: prevents a full system suspend.
WAKE_LOCK_IDLE: low-power states, which often cause large interrupt latencies or that disable a set of interrupts, will not be entered from idle until the wakelocks are released.
Unless the type is specified, this document refers to wakelocks of type WAKE_LOCK_SUSPEND.
If the suspend operation has already started when locking a wakelock, the system will abort the suspend operation as long it has not already reached the suspend_late stage. This means that locking a wakelock from an interrupt handler or a freezeable thread always works, but if you lock a wakelock from a suspend_late handler, you must also return an error from that handler to abort suspend. You can use wakelocks to allow the user-space to decide which keys should wake the full system and turn on the screen. Use set_irq_wake or a platform-specific API to ensure that the keypad interrupt wakes up the CPU. Once the keypad driver has resumed, the sequence of events can look like this:
The Keypad driver receives an interrupt, locks the keypad-scan wakelock, and starts scanning the keypad matrix.
The keypad-scan code detects a key change and reports it to the input-event driver.
The input-event driver sees the key change, enqueues an event, and locks the input-event-queue wakelock.
The keypad-scan code detects that no keys are held and unlocks the keypad-scan wakelock.
The user-space input-event thread returns from select/poll, locks the process-input-events wakelock, and calls read in the input-event device.
The input-event driver dequeues the key-event and, since the queue is now empty, unlocks the input-event-queue wakelock.
The user-space input-event thread returns from read. It determines that the key should not wake up the full system, releases the process-input-events wakelock, and calls select or poll.
The simple sequence diagram below illustrates these steps:
Key pressed Key released
| |
keypad-scan ++++++++++++++++++++++
input-event-queue +++ +++
process-input-events +++ +++
Driver API
A driver can use the wakelock API by adding a wakelock variable to its state and calling wake_lock_init, as illustrated in the snippet below:
struct state {
struct wakelock wakelock;
}
init() {
wake_lock_init(&state->wakelock, WAKE_LOCK_SUSPEND, "wakelockname");
}
Before freeing the memory, wake_lock_destroy must be called:
uninit() {
wake_lock_destroy(&state->wakelock);
}
When the driver determines that it needs to run (usually in an interrupt handler), it calls wake_lock:
wake_lock(&state->wakelock);
When it no longer needs to run, it calls wake_unlock:
wake_unlock(&state->wakelock);
It can also call wake_lock_timeout to release the wakelock after a delay:
wake_lock_timeout(&state->wakelock, HZ);
This works whether or not the wakelock is already held. It is useful if the driver woke up other parts of the system that do not use wakelocks but still need to run. Avoid this when possible, since it will waste power if the timeout is long or may fail to finish needed work if the timeout is short.
Write lockname or lockname timeout to /sys/power/wake_lock lock and, if needed, create a wakelock. The timeout here is specified in nanoseconds. Write lockname to /sys/power/wake_unlock to unlock a user wakelock.
Do not use randomly generated wakelock names as there is no API to free a user-space wakelock.
Types of Wake Locks
Wake Lock
|
Description
|
ACQUIRE_CAUSES_WAKEUP
|
Normally wake locks don't actually wake the device, they just cause it to remain on once it's already on. Think of the video player app as the normal behavior. Notifications that pop up and want the device to be on are the exception; use this flag to be like them.
|
FULL_WAKE_LOCK
|
Wake lock that ensures that the screen and keyboard are on at full brightness.
|
ON_AFTER_RELEASE
|
When this wake lock is released, poke the user activity timer so the screen stays on for a little longer.
|
PARTIAL_WAKE_LOCK
|
Wake lock that ensures that the CPU is running. The screen might not be on.
|
SCREEN_BRIGHT_WAKE_LOCK
|
Wake lock that ensures that the screen is on at full brightness; the keyboard backlight will be allowed to go off.
|
SCREEN_DIM_WAKE_LOCK
|
Wake lock that ensures that the screen is on, but the keyboard backlight will be allowed to go off, and the screen backlight will be allowed to go dim.
| Exploring a Wake Lock Example
All power management calls follow the same basic format:
Acquire handle to the PowerManager service.
Create a wake lock and specify the power management flags for screen, timeout, etc.
Acquire wake lock.
Perform operation (play MP3, open HTML page, etc.).
Release wake lock.
The snippet below illustrates this process.
PowerManager pm = (PowerManager)mContext.getSystemService(
Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE,
TAG);
wl.acquire();
// ...
wl.release();
PowerManager class
The Android Framework exposes power management to services and applications through the PowerManager class.
User space native libraries (any hardware function in //device/lib/hardware/ meant to serve as supporting libraries for Android runtime) should never call into Android Power Management directly (see the image above). Bypassing the power management policy in the Android runtime will destabilize the system.
All calls into Power Management should go through the Android runtime PowerManager APIs.
Please visit http://code.google.com/android/reference/android/os/PowerManager.html for a description of the API and examples.
Registering Drivers with the PM Driver
You can register Kernel-level drivers with the Android Power Manager driver so that they're notified immediately before power down or after power up. For example, you might set a display driver to completely power down when a request comes in to power down from the user space (see the Android MSM MDDI display driver for a sample implementation).
To register drivers with the Android PM driver, implement call-back handlers and register them with the Android PM, as illustrated in the snippet below:
android_register_early_suspend(android_early_suspend_t *handler)
android_register_early_resume(android_early_resume_t *handler)
It is critical in a drive to return immediately and not wait for anything to happen in the call back.
Early Suspend
The early-suspend API allows drivers to get notified when user-space writes to /sys/power/request_state to indicate that the user visible sleep state should change. Suspend handlers are called in order of low to high (4 - 1 below) and resume handlers are called in order of high to low (1 - 4 below).
EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
on suspend: the screen should be turned off but the framebuffer must still be accessible.
on resume: the screen can be turned back on.
EARLY_SUSPEND_LEVEL_STOP_DRAWING:
on suspend: this level notifies user-space that it should stop accessing the framebuffer and it waits for it to complete.
on resume: it notifies user-space that it should resume screen access. Two methods are provided, console switch or a sysfs interface.
EARLY_SUSPEND_LEVEL_DISABLE_FB: Turn off the framebuffer
on suspend: turn off the framebuffer
on resume: turn the framebuffer back on.
EARLY_SUSPEND_LEVEL_STOP_INPUT:
on suspend: turn off input devices that are not capable of wakeup or where wakeup is disabled.
on resume: turn the same devices back on.
Sensors
Android defines a user space C abstraction interface for sensor hardware. The interface header is defined in hardware/libhardware/include/hardware/sensors.h. In order to integrate sensors with Android you need to build a shared library that implements this interface. The types of sensors currently supported by Android include:
Accelerometer
Magnetic Field
Orientation
Gyroscope
Light
Pressure
Temperature
Proximity
Building a Sensor Library
To implement a Sensors driver, create a shared library that implements the interface defined in sensors.h. You must name your shared library libsensors.so so that it will get loaded from /system/lib at runtime.
The following stub file, Android.mk, ensures that libsensors compiles and links to the appropriate libraries:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sensors
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
# include any shared library dependencies
LOCAL_SRC_FILES := sensors.c
include $(BUILD_SHARED_LIBRARY)
Interface
sensors.h File Reference
Go to the source code of this file.
|
|
Data Structures
|
struct
|
sensor_t
|
struct
|
sensors_control_device_t
|
|
Every device data structure must begin with hw_device_t followed by module specific public methods and attributes. More...
|
struct
|
sensors_data_device_t
|
struct
|
sensors_data_t
|
|
Union of the various types of sensor data that can be returned. More...
|
struct
|
sensors_module_t
|
|
Every hardware module must have a data structure named HAL_MODULE_INFO_SYM and the fields of this data structure must begin with hw_module_t followed by module specific information. More...
|
struct
|
sensors_vec_t
|
|
Definition of the axis ----------------------. More...
|
Radio Layer Interface
In this document
Android's Radio Interface Layer (RIL) provides an abstraction layer between Android telephony services (android.telephony) and radio hardware. The RIL is radio agnostic, and includes support for Global System for Mobile communication (GSM)-based radios.
The diagram below illustrates the RIL in the context of Android's Telephony system architecture.
Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
The RIL consists of two primary components:
RIL Daemon: The RIL daemon initializes the Vendor RIL, processes all communication from Android telephony services, and dispatches calls to the Vendor RIL as solicited commands.
Vendor RIL: The radio-specific Vendor RIL of ril.h that processes all communication with radio hardware and dispatches calls to the RIL Daemon (rild) through unsolicited commands.
RIL Initialization
Android initializes the telephony stack and the Vendor RIL at startup as described in the sequence below:
RIL daemon reads rild.lib path and rild.libargs system properties to determine the Vendor RIL library to use and any initialization arguments to provide to the Vendor RIL
RIL daemon loads the Vendor RIL library and calls RIL_Init to initialize the RIL and obtain a reference to RIL functions
RIL daemon calls RIL_register on the Android telephony stack, providing a reference to the Vendor RIL functions
See the RIL Daemon source code at //device/commands/rild/rild.c for details.
System Properties
The following RIL-related system properties are set by the RIL library:
ro.ril.ecclist: list of valid Emergency Call Codes, for example, 911. Values are read from EF_ECC on the SIM and possibly supplmented by tables based on operator, network, or manufacturing code.
The following RIL_related system properties are available to the RIL library:
ro.ril.hsxpa: inidcates hsxpa support of target network.
ro.ril.gprsclass: inidcates GPRS class of target network.
ro.ril.enable.3g.prefix=1: adds the 3G prefix to the operator name.
RIL Interaction
There are two forms of communication that the RIL handles:
Solicited commands: Solicited commands originated by RIL lib, such as DIAL and HANGUP.
Unsolicited responses: Unsolicited responses that originate from the baseband, such as CALL_STATE_CHANGED and NEW_SMS.
Solicited
The following snippet illustrates the interface for solicited commands:
void OnRequest (int request_id, void *data, size_t datalen, RIL_Token t);
void OnRequestComplete (RIL_Token t, RIL_Error e, void *response, size_t responselen);
There are over sixty solicited commands grouped by the following families:
SIM PIN, IO, and IMSI/IMEI (11)
Call status and handling (dial, answer, mute…) (16)
Network status query (4)
Network setting (barring, forwarding, selection…) (12)
SMS (3)
PDP connection (4)
Power and reset (2)
Supplementary Services (5)
Vendor defined and support (4)
The following diagram illustrates a solicited call in Android.
Unsolicited
The following snippet illustrates the interface for unsolicited commands:
void OnUnsolicitedResponse (int unsolResponse, void *data, size_t datalen);
There are over ten unsolicited commands grouped by the following families:
Network status changed (4)
New SMS notify (3)
New USSD notify (2)
Signal strength or time changed (2)
The following diagram illustrates an unsolicited call in Android.
Implementing the RIL
To implement a radio-specific RIL, create a shared library that implements a set of functions required by Android to process radio requests. The required functions are defined in the RIL header (/include/telephony/ril.h).
The Android radio interface is radio-agnostic and the Vendor RIL can use any protocol to communicate with the radio. Android provides a reference Vendor RIL, using the Hayes AT command set, that you can use as a quick start for telephony testing and a guide for commercial vendor RILs. The source code for the reference RIL is found at /commands/reference-ril/.
Compile your Vendor RIL as a shared library using the convention libril--.so, for example, libril-acme-124.so, where:
libril: all vendor RIL implementations start with 'libril'
: a company-specific abbreviation
: RIL version number
so: file extension
RIL_Init
Your Vendor RIL must define a RIL_Init function that provides a handle to the functions which will process all radio requests. RIL_Init will be called by the Android RIL Daemon at boot time to initialize the RIL.
RIL_RadioFunctions *RIL_Init (RIL_Env* env, int argc, char **argv);
RIL_Init should return a RIL_RadioFunctions structure containing the handles to the radio functions:
type structure {
int RIL_version;
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
}
RIL_RadioFunctions;
RIL Functions
ril.h defines RIL states and variables, such as RIL_UNSOL_STK_CALL_SETUP, RIL_SIM_READY, RIL_SIM_NOT_READY, as well as the functions described in the tables below. Skim the header file (/device/include/telephony/ril.h) for details.
RIL Solicited Command Requests
The vendor RIL must provide the functions described in the table below to handle solicited commands. The RIL solicited command request types are defined in ril.h with the RIL_REQUEST_ prefix. Check the header file for details.
Name
|
Description
|
void (*RIL_RequestFunc) (int request, void *data, size_t datalen, RIL_Token t);
|
This is the RIL entry point for solicited commands and must be able to handle the various RIL solicited request types defined in ril.h with the RIL_REQUEST_ prefix.
request is one of RIL_REQUEST_*
data is pointer to data defined for that RIL_REQUEST_*
t should be used in subsequent call to RIL_onResponse
datalen is owned by caller, and should not be modified or freed by callee
Must be completed with a call to RIL_onRequestComplete(). RIL_onRequestComplete() may be called from any thread before or after this function returns. This will always be called from the same thread, so returning here implies that the radio is ready to process another command (whether or not the previous command has completed).
|
RIL_RadioState (*RIL_RadioStateRequest)();
|
This function should return the current radio state synchronously.
|
int (*RIL_Supports)(int requestCode);
|
This function returns "1" if the specified RIL_REQUEST code is supported and 0 if it is not.
|
void (*RIL_Cancel)(RIL_Token t);
|
This function is used to indicate that a pending request should be canceled. This function is called from a separate thread--not the thread that calls RIL_RequestFunc.
On cancel, the callee should do its best to abandon the request and call RIL_onRequestComplete with RIL_Errno CANCELLED at some later point.
Subsequent calls to RIL_onRequestComplete for this request with other results will be tolerated but ignored (that is, it is valid to ignore the cancellation request).
RIL_Cancel calls should return immediately and not wait for cancellation.
|
const char * (*RIL_GetVersion) (void);
|
Return a version string for your Vendor RIL
|
The vendor RIL uses the following callback methods to communicate back to the Android RIL daemon.
Name
|
Description
|
void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen);
|
t is parameter passed in on previous call to RIL_Notification routine.
If e != SUCCESS, then response can be null and is ignored
response is owned by caller, and should not be modified or freed by callee
RIL_onRequestComplete will return as soon as possible
|
void RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, const struct timeval *relativeTime);
|
Call user-specified callback function on the same thread that RIL_RequestFunc is called. If relativeTime is specified, then it specifies a relative time value at which the callback is invoked. If relativeTime is NULL or points to a 0-filled structure, the callback will be invoked as soon as possible.
| RIL Unsolicited Commands
The functions listed in the table below are call-back functions used by the Vendor RIL to invoke unsolicited commands on the Android platform. See ril.h for details.
Name
|
Description
|
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data, size_t datalen);
|
unsolResponse is one of RIL_UNSOL_RESPONSE_*
data is pointer to data defined for that RIL_UNSOL_RESPONSE_*
data is owned by caller, and should not be modified or freed by callee
|
|