Android休眠唤醒和wakeup_source机制的使用(2)

流程相关的代码分析(非wakeup source代码)

这里主要分析当出发power类事件时,android是怎样使用wakeup source机制来实现休眠唤醒的。

关于wakeup source的代码,以后再分析。

当power key按下后,首先是key 驱动里面读取键值,然后上报给系统:

351 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
352 {
353     struct gpio_button_data *bdata = dev_id;
354     struct gpio_keys_button *button = bdata->button;
355 
356     BUG_ON(irq != gpio_to_irq(button->gpio));
357 
358     if (bdata->timer_debounce)
359         mod_timer(&bdata->timer,
360             jiffies + msecs_to_jiffies(bdata->timer_debounce));
361     else
362         schedule_work(&bdata->work);
363 
364     return IRQ_HANDLED;
365 }

我们看到,为了遵循中断函数“快进快出”的原则,中断函数里面做了几件事情:

1、  修改定时器。当定时器超时后,会进入定时器中断,这时在定时器中断里面读取key的按键值,所以定义定时器来读取键值,还有一个功能就是去抖动。

2、  最后执行了调度动作。这是中断“下半部”的功能。也是为了中断快进快退的功能,定义的中断的下半部分来完成后续的工作,有系统来分配下半部分执行的时机。在下半部的执行工作里面,很明显就是对键值的上报了。

当android层面上收到input时间,由kl文件映射为power按键的值:
 

2 key 116    POWER           WAKE

然后有应用程序会保存数据,最后会把所有的wake lock锁清理。

hal代码
115 release_wake_lock(const char* id)
116 {
117     initialize_fds();
118 
119 //    ALOGI("release_wake_lock id='%s'\n", id);
120 
121     if (g_error) return g_error;
122 
123     ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
124     return len >= 0;
125 }
 
 94 acquire_wake_lock(int lock, const char* id)
 95 {
 96     initialize_fds();
 97 
 98 //    ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
 99 
100     if (g_error) return g_error;
101 
102     int fd;
103 
104     if (lock == PARTIAL_WAKE_LOCK) {
105         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
106     }
107     else {
108         return EINVAL;
109     }
110 
111     return write(fd, id, strlen(id));
112 }

上面一段代码其实是做了个事情,把程序里面wakeup的锁写进到 wake_unlock节点里面。当kernel检测到wake_lock 里面为空时,就会自动进入休眠。也就是说,从android进入kernel休眠的过程,也就是清理wake_lock 的过程。

当执行这过程后,内核就正式开始进入休眠模式。休眠模式里面,其中有一个任务就是开启“唤醒中断”,我们来看看内核是怎样处理的。

首先是定义 init_irq :

2281 MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board")
2282     /* Maintainer: Freescale Semiconductor, Inc. */
2283     .boot_params = MX6_PHYS_OFFSET + 0x100,
2284     .fixup = fixup_mxc_board,
2285     .map_io = mx6_map_io,
2286     .init_irq = mx6_init_irq,
2287     .init_machine = mx6_sabresd_board_init,
2288     .timer = &mx6_sabresd_timer,
2289     .reserve = mx6q_sabresd_reserve,
2290 MACHINE_END

然后在 irq.c 里面调用init_irq 函数:

128 void __init init_IRQ(void)
129 {
130     machine_desc->init_irq();
131 }

最后在内核的suspend里面,最后调用到 __enable_irq 函数,使能唤醒中断。

suspend
drivers/base/power/main.c:450:	pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
847 int dpm_suspend_noirq(pm_message_t state)
resume_irqs(true);
kernel_imx/kernel/irq/pm.c
 43 void resume_irqs(bool want_early)
 44 {
 45     struct irq_desc *desc;
 46     int irq;
 47 
 48     for_each_irq_desc(irq, desc) {
 49         unsigned long flags;
 50         bool is_early = desc->action &&
 51             desc->action->flags & IRQF_EARLY_RESUME;
 52 
 53         if (is_early != want_early)
 54             continue;
 55 
 56         raw_spin_lock_irqsave(&desc->lock, flags);
 57         __enable_irq(desc, irq, true);
 58         raw_spin_unlock_irqrestore(&desc->lock, flags);
 59     }
 60 }
 61 EXPORT_SYMBOL_GPL(resume_irqs);
kernel_imx/kernel/power/suspend.c
147 static int suspend_enter(suspend_state_t state)
148 {
149     int error;
150 
151     if (suspend_ops->prepare) {
152         error = suspend_ops->prepare();
153         if (error)
154             goto Platform_finish;
155     }
156 
157     error = dpm_suspend_noirq(PMSG_SUSPEND);
158     if (error) {
159         printk(KERN_ERR "PM: Some devices failed to power down\n");
160         goto Platform_finish;
161     }

以上贴的代码分别是:key驱动对按键的处理,android走完休眠流程后,调用HAL清理 wake_lock 过程,还有内核处理休眠与唤醒 irq的相关代码。按照这个思路,就能把整个休眠跟唤醒的流程分析透彻。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值