Chinaunix首页 | 论坛 | 博客
  • 博客访问: 197834
  • 博文数量: 68
  • 博客积分: 529
  • 博客等级: 中士
  • 技术积分: 721
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-10 16:38
文章分类

全部博文(68)

文章存档

2014年(2)

2013年(4)

2012年(16)

2011年(34)

2010年(4)

2009年(8)

分类: LINUX

2011-09-14 18:19:55

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




系统按键的处理:
  1. void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,
  2.         int32_t deviceId, int32_t action, int32_t &flags,
  3.         int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
  4. #if DEBUG_INPUT_DISPATCHER_POLICY
  5.     LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, "
  6.             "keyCode=%d, scanCode=%d, policyFlags=0x%x",
  7.             when, deviceId, action, flags, keyCode, scanCode, policyFlags);
  8. #endif

  9.     if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
  10.         policyFlags |= POLICY_FLAG_VIRTUAL;
  11.         flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
  12.     }

  13.     // Policy:
  14.     // - Ignore untrusted events and pass them along.
  15.     // - Ask the window manager what to do with normal events and trusted injected events.
  16.     // - For normal events wake and brighten the screen if currently off or dim.
  17.     if ((policyFlags & POLICY_FLAG_TRUSTED)) {
  18.         const int32_t WM_ACTION_PASS_TO_USER = 1;
  19.         const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
  20.         const int32_t WM_ACTION_GO_TO_SLEEP = 4;

  21.         bool isScreenOn = this->isScreenOn();
  22.         bool isScreenBright = this->isScreenBright();

  23.         JNIEnv* env = jniEnv();
  24.         jint wmActions = env->CallIntMethod(mCallbacksObj,
  25.                 gCallbacksClassInfo.interceptKeyBeforeQueueing,
  26.                 when, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
  27.         if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
  28.             wmActions = 0;
  29.         }

  30.         if (!(flags & POLICY_FLAG_INJECTED)) {
  31.             if (!isScreenOn) {
  32.                 policyFlags |= POLICY_FLAG_WOKE_HERE;
  33.                 flags |= AKEY_EVENT_FLAG_WOKE_HERE;
  34.             }

  35.             if (!isScreenBright) {
  36.                 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
  37.             }
  38.         }

  39.         if (wmActions & WM_ACTION_GO_TO_SLEEP) {
  40.             android_server_PowerManagerService_goToSleep(when);
  41.         }

  42.         if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
  43.             android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
  44.         }

  45.         if (wmActions & WM_ACTION_PASS_TO_USER) {
  46.             policyFlags |= POLICY_FLAG_PASS_TO_USER;
  47.         }
  48.     } else {
  49.         policyFlags |= POLICY_FLAG_PASS_TO_USER;
  50.     }
  51. }

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;
}
阅读(1588) | 评论(0) | 转发(0) |
0

上一篇:hardware study

下一篇:linux mmc 分析

给主人留下些什么吧!~~