Skip to content

iusmac/battery-friendly-pocketmode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Battery-friendly Pocket Mode At Kernel Level

GitHub Licence GitHub release (latest SemVer)

Settings › Display › Pocket detection Demo

About

This pocket mode implementation is a fork of Battery-friendly Pocketmode written by Trần Mạnh Cường (Cuong Tran). It's still continues the main idea, which is to run the proximity sensor and checks only on the lock screen, so that deep sleep and battery life aren't affected.

The weaknesses of the previous pocket mode implementation:

  1. Not translated to most spoken languages
  2. The user isn't notified on pocket mode being active
  3. Potential screen on/off loop and undesired bugs when hardware buttons are set to explicitly wake up the screen
  4. No "safe door" to exit pocket mode in case of proximity sensor issues
  5. Unnecessary timeouts that add unpredictable behavior and bad UX like:

    In case the screen automatically turns off after being taken out of the pocket, please wait for a few seconds and everything will work again.

    - Trần Mạnh Cường (Cuong Tran)

So, what's done in this implementation:

  1. The screen isn't turned off when proximity sensor is positive but instead, we tell the kernel to ignore touchscreen, HW buttons, fingerprint, slider etc., as if they are physically absent
  2. Available in 36 languages upon release
  3. Volume keys force wake screen if volume buttons should not seek media tracks (LineageOS-based ROMs only)
  4. The user receives a silent, but a high importance notification on pocket mode being active
  5. Pocket mode can be temporarily suspended until next screen on/off cycle by pressing and holding the power button for at least 2 seconds (by default).
  6. No "sluggish" reaction or unpredictable behavior. High responsiveness and accuracy thanks to the kernel driver
  7. New settings layout, with demo and instructions to improve UX
  8. Minor bug fixes discovered in previous pocket mode implementation

Requirements

(Compile) Android 14 (API level 34) code base

(Launch) Android 12+ (API level 31+)

How to implement

Android-side

  1. Create a directory named PocketJudge (or whatever you want to call it) in your DT (device tree)
  2. Copy the content of java/ directory into newly created directory in step n.1
  3. Add package to your device.mk
    PRODUCT_PACKAGES += \
        PocketJudge
  4. Pick SELinux policies from sepolicy/ directory to your DT sepolicy/ directory.

See implementation example into XiaomiParts: here

Kernel-side

  1. Apply patches for pocket judge and HW buttons (power/GPIO buttons) drivers from kernel/ directory
  2. Add your global enable/disable IRQ callbacks for the desired device components you want to ignore (ex. touchscreen) to pocket_judge_update function in drivers/input/pocket-judge.c file
  3. Enable driver in your defconfig:
    CONFIG_POCKET_JUDGE=y
    
See IRQ callback implementation examples
  • FocalTech (FT5346) & Goodix (GT9xx_v2.8) touchscreen drivers: here
  • Fingerprint Cards (fpc1020) fingerprint driver & Synaptics (S3320) touchscreen driver: here

ROM adaptations

ERROR 'Duplicate declaration of type' at token

Most custom ROMs already have traditional pocket mode implementation and needed sepolicy types/context definitions for pocket bridge sysfs node. In case of "Duplicate declaration of type" error during sepolicy compilation, remove duplicates and leave sepolicy rules from system_app.te file only.

Under the hood: how does pocket bridge works?

In the previous implementation, the service uses proximity sensor to turn off the display once it's covered. In this implementation, the service uses the proximity sensor to comunicate pocket state to the pocket judge kernel driver via sysfs file defined in path: /sys/kernel/pocket_judge/inpocket

Communication in details
  • When IN POCKET (sensor covered), we write 1 to sysfs node to trigger user's callbacks in the pocket judge driver, which should disable IRQ interruptions for desired device components (touchscreen, HW buttons, fingerprint, slider etc.).

  • When NOT IN POCKET (sensor uncovered), we write 0 to sysfs node, which does the opposite effect of IN POCKET state.

  • When POWER BUTTON IS PRESSED for n seconds (2s by default), the pocket judge driver will output 2 when reading sysfs node and all IRQ interruptions will be enabled immediately; this state is called "safe door". In our java app, we run a thread to listen for "safe door" state if proximity sensor was positive (covered) at least ones.

    Note: to properly enter the "safe door" state, the power button must be released, so that the driver can calculate elapsed time between "press" and "release" events.

  • When IN "SAFE DOOR" state, we temporarily suspend proximity sensor reading until next screen on/off cycle and write 0 to sysfs node to inform the pocket judge driver that we are aware of "safe door" state.

Contributing

Contributions are welcome! Fixes, improvements and implementations for different kernel versions, SoCs, touchscreens, fingerprints etc., are highly appreciated. Share your patches via PR!

Authors

Trần Mạnh Cường (Cuong Tran)

iusmac (Max)