但是 C program (大部分是 daemon, service),要知道 suspend/wakeup 的時機,好像就沒有 signal 之類的方法。
在
base/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
看到一個方法。
就是去讀 /sys/power/wait_for_fb_sleep, 和 wait_for_fb_wake
這兩個 sysfs 的 node 是 kernel/power/fbearlysuspend.c 提供的:
static ssize_t wait_for_fb_sleep_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *s = buf;
int ret;
ret = wait_event_interruptible(fb_state_wq,
fb_state != FB_STATE_DRAWING_OK);
if (ret && fb_state == FB_STATE_DRAWING_OK)
return ret;
else
s += sprintf(buf, "sleeping");
return s - buf;
}
其中有 wait_event_interruptible( ),
所以在 read /sys/power/wait_for_fb_sleep 時,會被 block 住,直到 fb_state != FB_STATE_DRAWING_OK 時,才會 恢復執行 。
看看 surfaceblinger 的 code:
static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep";
...
...
fd = open(kSleepFileName, O_RDONLY, 0);
do {
err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
if (err >= 0) {
sp<urfaceFlinger> flinger = mFlinger.promote();
LOGD("About to give-up screen, flinger = %p", flinger.get());
if (flinger != 0) {
mBarrier.close();
flinger->screenReleased(0);
mBarrier.wait();
}
}
在 read( wait_for_fb_sleep ) 時,會被 block 住,直到 kernel run 到earlysuspend 後,才會繼續,earlysuspend 的時機是在 call driver suspend 之前,所以在 logcat 可以看到:
InputManager-JNI 在 call android_server_PowerManagerService_goToSleep 後,會有:
libharware jni code, set_screen_state 0
然後就是
/D/SurfaceFlinger(2401): About to give-up screen, flinger = 0x8c830對照上面的 code,就是 read( ) 之後。
SurfaceFlinger 在做完 suspend 要作的事後,就要等 wakeup 了,
所以接著的 code 就是:
static char const * kWakeFileName = "/sys/power/wait_for_fb_wake";
...
...
fd = open(kWakeFileName, O_RDONLY, 0);
do {
err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
if (err >= 0) {
sp<SurfaceFlinger> flinger = mFlinger.promote();
LOGD("Screen about to return, flinger = %p", flinger.get());
if (flinger != 0)
flinger->screenAcquired(0);
}
return true;
馬上 read ( wait_for_fb_wake )
在 kernel 中,這個 attrib 是:
ret = wait_event_interruptible(fb_state_wq,
fb_state == FB_STATE_DRAWING_OK);
if (ret && fb_state != FB_STATE_DRAWING_OK)
return ret;
else
s += sprintf(buf, "awake");
return s - buf;
一樣,是等 fb_state == FB_STATE_DRAWING_OK
所以在 system logcat,libhardware power jni 設完 set_screen_state 1 後,
就是
D/SurfaceFlinger (2401): Screen about to return, flinger = 0x8c830
仿照 Surfaceflinger 的 code,這樣就可以得到 suspend/ wakeup 的時間:
沒有留言:
張貼留言