PARTIAL_WAKE_LOCK not correctly honored?

159 views
Skip to first unread message

Michael Goffioul

unread,
Nov 11, 2016, 1:06:21 AM11/11/16
to Android-x86
I have an APK that creates a PARTIAL_WAKE_LOCK to keep the CPU alive in stand-by. This works fine on regular Android devices (both ARM and x86), but on Android-x86 the CPU shuts down completely when the POWER key is pressed and the device looses connectivity. Is there a workaround for this, or some kernel command-line flag I can use to change that behavior?

Note: I'm using 4.4-r5

Michael.

Michael Goffioul

unread,
Nov 11, 2016, 9:47:07 AM11/11/16
to andro...@googlegroups.com
I would appreciate if anybody has some pointers about where to look in the source code.

I know that my partial_wake_lock is active, as returned by "dumpsys power". From the same output, I also know that PowerManagerService has acquired mWakeLockSuspendBlocker. "cat /sys/power/wake_lock" shows an entry for my ADB connection (however, it doesn't show an entry for the wakelock installed by PowerManagerService, not sure whether this is expected).

Still, simply executing "input keyevent POWER" turns the device completely OFF.

What I'm not sure is how Android tells the kernel to go into sleep mode. Is it with PowerManagerService.nativeSetAutoSuspend?

Michael.



--
You received this message because you are subscribed to the Google Groups "Android-x86" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-x86+unsubscribe@googlegroups.com.
To post to this group, send email to andro...@googlegroups.com.
Visit this group at https://groups.google.com/group/android-x86.
For more options, visit https://groups.google.com/d/optout.

Michael Goffioul

unread,
Nov 11, 2016, 4:47:24 PM11/11/16
to andro...@googlegroups.com
Answering myself: it seems setting "debug.autosleep=1" in Android solves the problem. From the look at it, the kernel bundled with 4.4-r5 does not have the Android kernel patches for earlysuspend, but Android will use earlysuspend mechanism by default. So the wakelock installed by PowerManagerService is ignored by the kernel. By making Android to use autosleep instead, the wakelock is taken into account and the CPU stays awake.

Michael.

Chih-Wei Huang

unread,
Nov 13, 2016, 12:20:06 PM11/13/16
to Android-x86
2016-11-12 3:30 GMT+08:00 Michael Goffioul <michael....@gmail.com>:
> Answering myself: it seems setting "debug.autosleep=1" in Android solves the
> problem. From the look at it, the kernel bundled with 4.4-r5 does not have
> the Android kernel patches for earlysuspend, but Android will use
> earlysuspend mechanism by default. So the wakelock installed by
> PowerManagerService is ignored by the kernel. By making Android to use
> autosleep instead, the wakelock is taken into account and the CPU stays
> awake.

I'm just going to answer your question.
Fortunately you have found it.
Actually the best way to find the answer
is just read the source code.

Note debug.autosleep is only valid in android-x86 4.4.
For android-x86 6.0 or 7.0 you should use
sleep.earlysuspend=0. Also note the default value
of sleep.earlysuspend is 1 in 6.0.
But in 7.0 it's experimentally changed to 0.

Indeed the suspend/resume support of
android-x86 is still premature.
So don't surprise it is changed or broken
in the future...

Michael Goffioul

unread,
Nov 13, 2016, 6:05:33 PM11/13/16
to andro...@googlegroups.com
On Sun, Nov 13, 2016 at 12:19 PM, Chih-Wei Huang <cwh...@android-x86.org> wrote:
2016-11-12 3:30 GMT+08:00 Michael Goffioul <michael....@gmail.com>:
> Answering myself: it seems setting "debug.autosleep=1" in Android solves the
> problem. From the look at it, the kernel bundled with 4.4-r5 does not have
> the Android kernel patches for earlysuspend, but Android will use
> earlysuspend mechanism by default. So the wakelock installed by
> PowerManagerService is ignored by the kernel. By making Android to use
> autosleep instead, the wakelock is taken into account and the CPU stays
> awake.

I'm just going to answer your question.
Fortunately you have found it.
Actually the best way to find the answer
is just read the source code.

Indeed, and that's how I finally figured it out. But it required to trace the power manager code (both java and native), libsuspend code, and eventually figure out why "echo mem > /sys/power/state" was ignoring the wakelocks (because it relies on an Android-patched kernel, which is not in use anymore in 4.4-r5).

Even though I'm a developer and familiar with various parts of the Android source code, this was not trivial to find. So support from a mailing list like this one is really appreciated.

Thanks for the tips about version 6.0 and 7.0, this will probably save me some time in the future.

Michael.

Michael Goffioul

unread,
Nov 14, 2016, 1:35:46 PM11/14/16
to andro...@googlegroups.com
On Sun, Nov 13, 2016 at 12:19 PM, Chih-Wei Huang <cwh...@android-x86.org> wrote:
Indeed, "debug.autosleep=1" is not enough to make PARTIAL_WAKE_LOCK to work properly. I was fooled by my active ADB session, which installs a wakelock in the kernel (visible with "cat /sys/power/wake_lock").

I guess PowerManagerService is supposed to install a wake_lock too, through the following chain:
  -> PowerManagerService
  -> mWakeLockSuspendBlocker
  -> SuspendBlockerImpl.acquire
  -> nativeAcquireSuspendBlocker
  -> acquire_wake_lock
  -> write into /sys/power/wake_lock

However, this wakelock is not visible in "cat /sys/power/wake_lock". I suspect there's a permission problem and the process system_server is not allowed to write into /sys/power/wake_lock. And the wakelock installed by PowerManagerService is not active ("nativeAcquireSuspendBlocker" happily ignores errors returned by "acquire_wake_lock").

The ownership of /sys/power/wake_lock is radio.system, so I tried to write into it manually from the console:

  su -- radio
  echo "my-lock" > /sys/power/wake_lock

The echo command exited with status 1, so I guess it failed. Executing the same echo command as root works fine.

Does anybody know how this is supposed to work?

Thanks,
Michael.

Michael Goffioul

unread,
Nov 14, 2016, 9:16:46 PM11/14/16
to andro...@googlegroups.com
It appears it is indeed a permission/capability issue. The kernel only allows processes with CAP_BLOCK_SUSPEND capability to write into /sys/power/wake_lock. As it is now in 4.4-r5, system_server doesn't have that capability; hence it's unable to install its wakelock in the kernel.

I tried to add it using the attached patch, but it didn't work. I believe one also has to update external/kernel-headers (to bring it in sync with the kernel actually used) and related auto-generated files like bionic/libc/kernel/common/linux/capability.h. I'd rather leave that to Chih-Wei Huang.

Another/hackier workaround is to disable the use of CAP_BLOCK_SUSPEND in kernel/kernel/power/wakelock.c, which works fine. One then only relies on the filesystem permissions/ownership to restrict usage of /sys/power/wake_lock.

Michael.


0004_add-cap_block_suspend.diff

Chih-Wei Huang

unread,
Nov 15, 2016, 12:52:57 AM11/15/16
to Android-x86
You may need this:

https://android.googlesource.com/platform/frameworks/base/+/49cbafad9beb6041aaee773f75473fdb5022888e%5E!/

This patch should have been applied to 6.0+.


> Another/hackier workaround is to disable the use of CAP_BLOCK_SUSPEND in
> kernel/kernel/power/wakelock.c, which works fine. One then only relies on
> the filesystem permissions/ownership to restrict usage of
> /sys/power/wake_lock.

--
Chih-Wei
Android-x86 project
http://www.android-x86.org

Michael Goffioul

unread,
Nov 15, 2016, 7:08:07 AM11/15/16
to andro...@googlegroups.com
This wasalready part of my attached patch. I'm using branch kittkat-x86. My patch didn't work, because it's not enough. One also need to update external/kernel-headers and various other dependent files. The mismatch between the kernel and the rest of the source tree (external/kernel-headers) is making things more difficult.

Michael.


Reply all
Reply to author
Forward
0 new messages