1) power management api :
WakeLock: 用两个函数来来操作
acquire release , 最终这两个函数将调用 power management 的service .
userActivity: 这个函数让设备回到full on 的状态
public void goToSleep(long time) |
强制设备进入sleep状态!
public void setBacklightBrightness(int brightness)
|
设置屏幕的亮度
public int getSupportedWakeLockFlags()
|
public boolean isScreenOn()
|
public void reboot(String reason)
|
2) power management service 的启动
在systemserver.java run 函数中调用
power = new PowerManagerService();
|
ServiceManager.addService(Context.POWER_SERVICE, power);
|
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
power.init(context, lights, ActivityManagerService.getDefault(), battery);
|
powermanagementservice init:
1) 创建PowerManagerService.mScreenOffThread , 其中在handler 中将要创建looper
a) BrightnessState 的创建
private final BrightnessState mScreenBrightness
= new BrightnessState(SCREEN_BRIGHT_BIT); |
目前设置的mask 为SCREEN_BRIGHT_BIT
b) 通过调用 BrightnessState 的run 函数, 然后调用
--> boolean stepLocked() 这个函数没1000/60 毫秒调用一次,并设置相应的亮度。
如果亮度是screen off, 也就是0, 将调用finishAnimationLocked
关闭 button keypad 的led.
b) setTargetLocked
这个函数将去除以前的动画, 并开始新的亮度设置的动画。
systemReady 当系统service 都设置好后,调用powermanager service systemReady
系统按键的处理:
- void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,
-
int32_t deviceId, int32_t action, int32_t &flags,
-
int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
-
#if DEBUG_INPUT_DISPATCHER_POLICY
-
LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, "
-
"keyCode=%d, scanCode=%d, policyFlags=0x%x",
-
when, deviceId, action, flags, keyCode, scanCode, policyFlags);
-
#endif
-
-
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
-
policyFlags |= POLICY_FLAG_VIRTUAL;
-
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-
}
-
-
// Policy:
-
// - Ignore untrusted events and pass them along.
-
// - Ask the window manager what to do with normal events and trusted injected events.
-
// - For normal events wake and brighten the screen if currently off or dim.
-
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
-
const int32_t WM_ACTION_PASS_TO_USER = 1;
-
const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
-
const int32_t WM_ACTION_GO_TO_SLEEP = 4;
-
-
bool isScreenOn = this->isScreenOn();
-
bool isScreenBright = this->isScreenBright();
-
-
JNIEnv* env = jniEnv();
-
jint wmActions = env->CallIntMethod(mCallbacksObj,
-
gCallbacksClassInfo.interceptKeyBeforeQueueing,
-
when, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
-
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
-
wmActions = 0;
-
}
-
-
if (!(flags & POLICY_FLAG_INJECTED)) {
-
if (!isScreenOn) {
-
policyFlags |= POLICY_FLAG_WOKE_HERE;
-
flags |= AKEY_EVENT_FLAG_WOKE_HERE;
-
}
-
-
if (!isScreenBright) {
-
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
-
}
-
}
-
-
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
-
android_server_PowerManagerService_goToSleep(when);
-
}
-
-
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
-
android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
-
}
-
-
if (wmActions & WM_ACTION_PASS_TO_USER) {
-
policyFlags |= POLICY_FLAG_PASS_TO_USER;
-
}
-
} else {
-
policyFlags |= POLICY_FLAG_PASS_TO_USER;
-
}
-
}
linux process freeze!
pm_suspend() 虽然会调用enter_state()来进入标准的Linux休眠流程,但是还 是有一些区别:
- 当进入冻结进程的时候, android首先会检查有没有wake lock,如果没有, 才会停止这些进程, 因为在开始suspend和冻结进程期间有可能有人申请了 wake lock,如果是这样, 冻结进程会被中断.
- 在suspend_late()中, 会最后检查一次有没有wake lock, 这有可能是某种快速申请wake lock,并且快速释放这个锁的进程导致的,如果有这种情况, 这里会返回错误, 整个suspend就会全部放弃.如果pm_suspend()成功了,LOG的输出可以通过在kernel cmd里面增加 "no_console_suspend" 来看到suspend和resume过程中的log输出。
linux suspend:
linux 设备的注册管理
注册:函数调用
设备挂到电源管理的函数调用关系是(依次往下调用)
audio_card_init (函数类型包含__init 初始化调用)
platform_device_add
device_add
device_pm_add
list_add_tail(最直接的链表添加操作)
cpu freq and oop
1) cpu freq 频率的变化将影响 oop的变化
static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
调用set rate 来改变mpu的频率
if (opp_find_freq_ceil(mpu_dev, &freq))
omap_device_set_rate(mpu_dev, mpu_dev, freq);
int omap_device_set_rate(struct device *req_dev, struct device *dev,
unsigned long rate)
{
/* Do the actual scaling */
ret = omap_voltage_scale(voltdm);
int omap_voltage_scale(struct voltagedomain *voltdm)
{
unsigned long curr_volt;
int is_volt_scaled = 0, i;
bool is_sr_disabled = false;
struct omap_vdd_info *vdd;
struct plist_node *node;
unsigned long volt;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return -EINVAL;
}
vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
mutex_lock(&vdd->scaling_mutex);
curr_volt = omap_get_operation_voltage(
omap_voltage_get_nom_volt(voltdm));
/* Find the highest voltage for this vdd */
node = plist_last(&vdd->user_list);
volt = node->prio;
/* Disable smartreflex module across voltage and frequency scaling */
if (curr_volt != volt) {
omap_smartreflex_disable_reset_volt(voltdm);
is_sr_disabled = true;
}
if (curr_volt == volt) {
is_volt_scaled = 1;
} else if (curr_volt < volt) {
omap_voltage_scale_vdd(voltdm,
omap_voltage_get_voltdata(voltdm, volt));
is_volt_scaled = 1;
}
for (i = 0; i < vdd->dev_count; i++) {
struct omap_opp *opp;
unsigned long freq;
根据电压获取oop
opp = opp_find_voltage(vdd->dev_list[i], volt, true);
if (IS_ERR(opp)) {
dev_err(vdd->dev_list[i], "%s: Unable to find OPP for"
"volt%ld\n", __func__, volt);
continue;
}
根据opp 获取 freq
freq = opp_get_freq(opp);
if (freq == opp_get_rate(vdd->dev_list[i]))
continue;
然后设置频率
opp_set_rate(vdd->dev_list[i], freq);
}
if (!is_volt_scaled)
omap_voltage_scale_vdd(voltdm,
omap_voltage_get_voltdata(voltdm, volt));
/* Enable Smartreflex module */
if (is_sr_disabled)
omap_smartreflex_enable(voltdm);
mutex_unlock(&vdd->scaling_mutex);
/* calculate the voltages for dependent vdd's */
if (calc_dep_vdd_volt(&vdd->vdd_device, vdd, volt)) {
pr_warning("%s: Error in calculating dependent vdd voltages"
"for vdd_%s\n", __func__, voltdm->name);
return -EINVAL;
}
/* Scale dependent vdds */
scale_dep_vdd(vdd);
return 0;
}
阅读(1694) | 评论(0) | 转发(0) |