2011年01月11日
AndroidのPower Management (メモ)
状態遷移
通常状態 <-> スリープ <-> サスペンド
スリープ状態ではLCDのバックライトが消えます。
AndroidのSettingsでDisplay > Screen Timeoutの設定でスリープするまでの時間を変更できます。(また、SettingsのApplications > Development でStay awakeを有効にするとACアダプタが接続されている状態ではスリープしなくなります。)
サスペンドはDeep Sleepと表現されることもあります。
KZM-A9-Dualではサスペンド状態ではファイルシステムのSync、2つあるCPUコアのうちのひとつをshutdownします。インターバルタイマー割り込みを停止して割り込み待ち命令(WFI)を実行します。
Wake lock
Wake lockはAndroid特有のカーネルの機能で、サスペンド状態になるのを抑止します。
これのカーネルのソースは
kernel/power/wakelock.c
sysファイルシステムに以下が作られます。
/sys/power/state
/sys/power/wake_lock
/sys/power/wake_unlock
これらをユーザーランド側でさわっているところは
hardware/libhardware_legacy/power/power.c
スリープに入るまでの時間がSettingsのメニューで変更できるので、ここを通じてカーネル側に設定していると思われます。
スリープ、サスペンド時のカーネルログ
しばらく放置するとスリープ状態に遷移します。
request_suspend_state: sleep (0->3) at 330591719902 (2000-01-01 09:13:13.311584446 UTC)
さらに放置するとサスペンドに。
PM: Syncing filesystems ... done. Freezing user space processes ... (elapsed 0.00 seconds) done. Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done. mmc0: card 0001 removed MMC: killing requests for dead queue Disabling non-boot CPUs ... CPU1: shutdown CPU1 is down
これでサスペンド状態になりました。。2個のCPUのうちの1個を止めています。MMCカードは抜かれたという扱いになっているようです。
復帰させるためにプッシュボタン SW2を押して割り込みを発生させます。
wakeup wake lock: key Enabling non-boot CPUs ... CPU1: Booted secondary processor Calibrating delay loop... <7>Switched to high resolution mode on CPU 1 1064.96 BogoMIPS (lpj=5324800) CPU1 is up usb usb2: root hub lost power or was reset mmc0: new high speed MMC card at address 0001 mmc mmc0:0001: parent mmc0 should not be sleeping mmcblk0: mmc0:0001 000000 3.82 GiB mmcblk0: p1 p2 p3 usb 1-1: reset high speed USB device using emxx-ehci-driver and address 2 Restarting tasks ... done. suspend: exit suspend, ret = 0 (2000-01-01 09:16:26.868591313 UTC)
これでサスペンド状態からスリープ状態に戻りました。
CPU1を再スタートさせています。MMCカードも再認識しました。
まだ画面は暗いまま。
ここでLCDボード上のキーを押すと
request_suspend_state: wakeup (3->0) at 369132216726 (2000-01-01 09:16:34.212066644 UTC)
これで通常状態に復帰しました。
今はプッシュボタンSW2はカーネル内でwakelockしているだけですが、ユーザーランド側にキー入力のイベントを発行するようにすれば、一気にサスペンドから通常状態に戻るはずです。
(2011.1.11追記:プッシュボタンSW2でKEY_HOMEイベントを発行するようにしたら、SW2を押すだけでサスペンドから通常状態に戻るようになりました。)
サスペンド中はインターバルタイマーが止まっているのでタイマーによるポーリングはできません。またブロック単位で電源をカットしているので、その部分は働きません。例えばLCDボードの電源を切っているのでタッチスクリーンの割り込みも入ってこなくなります。
最初はこのあたりのことを理解していなかったのでサスペンド状態から復帰することができずに悩みました。
現在のシステムでは動作速度のチューニング以外に電力消費を抑えるためのチューニングも重要です。これに関してはまだまだ勉強中です。何かわかればまた書きます。