76 Commits

Author SHA1 Message Date
LuK1337
10586a9d4a sm7125-common: Opt out of speaker_layout_channel_mask field
Required for ABI compatibility with audio HAL compiled before 15 QPR2.

Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/9426
Change-Id: Ic910f0634ee0707c21dad77f5264fd89fb33f1c0
2026-01-09 23:19:50 +05:30
theshaenix
213053b2e3 sm7125-common : fine tuned the post boot script
- Improved the overall script behaviour
2026-01-09 22:26:35 +05:30
theshaenix
ce5d0c333f sm7125-common:migrate recovery init rc files to Soong
Move init.recovery.qcom.rc and init.recovery.usb.rc from
PRODUCT_COPY_FILES to proper prebuilt_etc modules.

This aligns recovery configuration with Soong-only builds,
ensures correct installation under /recovery/root, and
improves maintainability going forward.
2026-01-09 22:26:21 +05:30
aminfauzi
e8da85fd96 sm7125-common: Fix for aux camera lens missing in Aperture
Signed-off-by: aminfauzi <aremean0107@gmail.com>
2026-01-09 22:26:21 +05:30
theshaenix
34d8554510 Revert "sm7125-common: overlay: Enable BoostFramework support"
This reverts commit 2a5f329dcdbd63684e8d33ee2827df64b3b93783.
2026-01-09 22:26:21 +05:30
me-cafebabe
b277f8c03e sm7125-common: overlay: Disable high performance transitions
Change-Id: I70c593a8efe1499f8e0917b4e80652b7f3d71198
2026-01-09 22:26:21 +05:30
Pranav Vashi
7b575ce1eb sm7125-common: Update pinner files
Change-Id: Ibec6b6d6d1689fde16837ca526cb245cd5f9711c
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
2026-01-09 22:26:21 +05:30
Edgar Arriaga
37a7dd6cfb sm7125-common: overlay: Set default pin amount for home app
Bug: 288900050
Test: dumpsys pinner
Flag: EXEMPT refactor

Change-Id: Ieed912786ce51f420da9b0e96ea5d93c22244176
2026-01-09 22:26:20 +05:30
theshaenix
f03e83d1e1 sm7125-common: Drop zram writeback 2026-01-09 22:26:18 +05:30
Cassie
c1b0ecc377 sm7125-common: overlay: Use the new auto network selection UI
Change-Id: I76698911103601d5f3ad67e1099790af8c2fdc18
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
2026-01-09 22:25:47 +05:30
Georg Veichtlbauer
7aa4220185 sm7125-common: Drop config_setColorTransformAccelerated
It's now enabled by default

Change-Id: I57f059c872fc2ad2fd15e788b1391eeebaff9bde
2026-01-09 22:25:47 +05:30
Sebastiano Barezzi
7c63bfebaa sm7125-common: overlay: Enable config_dozePulsePickup
Change-Id: Ice5cd780eb77e2ae78a3a84a0140c321ad84f143
2026-01-09 22:25:47 +05:30
Bruno Martins
c4e96fd547 sm7125-common: overlay: Remove obsolete config_keyboardTapVibePattern
Change-Id: Ic89566183d2cdc4a20ea83f462c56a14184621ae
2026-01-09 22:25:46 +05:30
x0x00044
129fdb00e4 sm7125-common: overlay: Remove config_cellBroadcastAppLinks
- This is true by default.

Change-Id: I9f91f4bf49995975d434ad8b74b175693409862a
2026-01-09 22:25:46 +05:30
minaripenguin
b44aed089a sm7125-common: prop: Tune lmkd system properties
Signed-off-by: Mayur <ultramayur123@gmail.com>
2026-01-06 00:00:50 +05:30
Andrzej Perczak
afef2a1d6f Import lmkd props from google gki
Reference: https://github.com/LineageOS/android_hardware_google_pixel/blob/lineage-19.1/mm/device_gki.mk
Signed-off-by: Mayur <ultramayur123@gmail.com>
2026-01-06 00:00:50 +05:30
Tim Murray
d70d2d17d3 sm7125-common: prop: Set lmkd's swap_free_low_percentage to 100
Ref: 5f975896d4

Signed-off-by: Mayur <ultramayur123@gmail.com>
2026-01-06 00:00:49 +05:30
Mayur
b6efc02294 sm7125-common: prop: set lmk to kill heaviest task
Signed-off-by: Mayur <ultramayur123@gmail.com>
2026-01-06 00:00:49 +05:30
nullxception
5d82c74ffb sm7125-common: props: Disable LMKD log stats
TARGET_LMKD_STATS_LOG is not used anymore and log stats is enabled by
default, so we have to explicitly disable it from runtime.

Signed-off-by: Mayur <ultramayur123@gmail.com>
2026-01-06 00:00:49 +05:30
890393a955 Revert "sm7125-common: Update some soong config variables to bool type"
This reverts commit e4e29defad.
2025-12-30 09:20:19 +01:00
Yumi Yukimura
e4e29defad sm7125-common: Update some soong config variables to bool type 2025-12-30 13:18:17 +05:30
LuK1337
b0a455e0b8 sm7125-common: Remove vendor/lineage device framework matrix inclusion
See: I78da6340f38b93fdc4c3694cb8f431f387d16c0d
Change-Id: I0b9f527de50ca02082be9b92375559f4893b2688
2025-12-30 13:18:05 +05:30
Sourajit Karmakar
3967a9b37f sm7125-common: Disable FRP
* This should really be disabled after unlocking the bootloader.

Change-Id: Icf5305cba66e9e613000a6ef53b32fa59760a7f2
2025-12-30 13:17:35 +05:30
Kelvin Zhang
b9551ec7b2 sm7125-common: Allow to access bootable/deprecated-ota targets
Sm7125-common is still using non-AB update.
non-AB code will be moved to a separated namespace, add
deprecated-ota to sm6150-common namespace list ahead of time to avoid
breakage.

Test: th
Bug: 324360816
Change-Id: I909064be36e8febe80492cf010eb6eac3d6bc33d
2025-11-30 12:19:40 +05:30
Michael Bestas
9839b86f36 sm7125-common: Build recovery QTI health AIDL service
We have a recovery partition.

Change-Id: I10841b26feea3c214349a20b2eedec74924f993a
2025-11-30 12:19:40 +05:30
theshaenix
3728b1aea2 sm7125-common: Drop the unused android.hardware.power@1.2.vendor 2025-11-30 12:19:40 +05:30
Bruno Martins
5e170e74b3 sm7125-common: Move to QTI health AIDL service
The health AIDL HAL service provides functionalities of charger,
therefore system charger at /system/bin/charger is deprecated.
On top of that, QTI health AIDL HAL service enables suspend by
default, the equivalent of setting ro.charger.enable_suspend
for legacy charger.

Change-Id: I59c23e7974cea1174b0161f31a535fa3afa1e5c9
2025-11-30 12:19:39 +05:30
theshaenix
d7b1c2071f sm7125-common: Cleanup 2025-11-30 12:19:39 +05:30
aminfauzi
d1362347cd sm7125-common: fingerprint: preload HAL early for first-boot SetupWizard
Add an  trigger to start the fingerprint HAL immediately
after /data is mounted. Keeps  to avoid race
conditions, but ensures the HAL is available early enough for
first-boot SetupWizard enrollment.

This fixes the issue where fingerprint setup fails during initial
device setup but works after skipping and opening Settings.

Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-30 12:19:39 +05:30
theshaenix
e86c2261b6 sm7125-common: Enable EPPE 2025-11-30 12:19:39 +05:30
theshaenix
740b46504e sm7125-common: migrate to Adil MultiHAL 2025-11-30 12:19:39 +05:30
Omkar Chandorkar
3fcf8d108e sm7125-common: overlay: Steal CarrierConfig from phone1
* From Nothing OS 2.0.4

Change-Id: I8b761a30c86d72d6bd454332ec3042a22c1a7aac
Signed-off-by: Omkar Chandorkar <gotenksIN@aospa.co>
Signed-off-by: Adithya R <gh0strider.2k18.reborn@gmail.com>
Signed-off-by: Mayur <ultramayur123@gmail.com>
2025-11-21 16:56:35 +05:30
aminfauzi
bccfa62cd8 sm7125-common: prop: Improve signal strength with missing optimization properties
Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-09 19:50:54 +05:30
aminfauzi
9cbeaf7f9a sm7125-common: prop: Clean up network mode conflict - keep only vendor.prop definition
Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-09 19:50:46 +05:30
1xtAsh
a8876fd7e7 sm7125-common: Disable default framerate for games
This props fixes frame rate restrictions in games

Signed-off-by: 1xtAsh <ashraykrsingh321@gmail.com>
2025-11-09 19:50:37 +05:30
ahmedtohamy1
bfa2e40a46 sm7125-common: Compile HWUI for performance
optimizing compiler flags for HWUI. * -fno-omit-frame-pointer, -marm, -mapcs

Signed-off-by: JaswalAshish <ashish@m.ms.evolution-x.org>
Change-Id: Ia141b59cd1334eede94cfbec5a66c2d0d7784cd4
2025-11-09 19:29:34 +05:30
helliscloser
c997706fe1 sm7125-common: Explicitly disable "Enable GL comp backpressure"
When blur is enabled,
There is severe lag in; Launcher3 while scrolling apps in App drawer, Scrolling through recents and occasionally on QS pull down.

Explicitly disabling the "Enable GL comp backpressure" prop seems to slove the issue.

Lag & janks are gone now, even with blur.

Change-Id: Ia82d84d6ee867caa52ae93b72fbff132070bf808
Signed-off-by: helliscloser <mrumais@gmail.com>
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
2025-11-09 19:29:06 +05:30
TheMysticle
7bca1e3cbd sm7125-common: Enable ADPF CPU hints for improved UI performance
Turns on `debug.sf.enable_adpf_cpu_hint` to allow SurfaceFlinger to utilize Android Dynamic Performance Framework CPU hints, improving overall UI responsiveness and frame pacing on Snapdragon devices.

Change-Id: Ia715ab89ffc8a18130904e5588f9e4b487a20faa
2025-11-09 19:28:48 +05:30
Ghosuto
eae47e3ba2 sm7125-common: Enable Client Composition Cache
- All latest soc use it by default. with this cache can improve performance by reusing composition, This can result in smoother UI performance and potentially lower power consumption

- cons: It does increase memory usage because the system needs to store these results, but its not a big issue cause most devices are 12gb ver. and fine for 8gb also

Signed-off-by: Ghosuto <clash.raja10@gmail.com>
2025-11-09 19:28:36 +05:30
johnmart19
3b12dc0491 sm7125-common: Enable full ART optimizations with VDEX/ODEX
Enable comprehensive ART optimizations including VDEX and ODEX
generation for all system components to improve first-boot
performance and reduce application startup latency.

Configuration:
- WITH_DEXPREOPT := true          # Global dexpreopt enable
- DEX_PREOPT_DEFAULT := generate-vdex-and-image  # VDEX+ODEX gen
- WITH_DEXPREOPT_DEBUG_INFO := false  # Exclude debug symbols

Results:
- Verified generation of .odex files (optimized dex)
- Verified generation of .vdex files (verification dex)
- ART images created for core system components
- First boot time significantly reduced
- Application startup latency improved

Test procedure:
1. Full system build with 'm evolution' command
2. Verified artifacts in:
   - system/framework/oat/arm64/*.odex
   - system/framework/oat/arm64/*.vdex
   - system/app/*/oat/arm64/*.odex
   - system/priv-app/*/oat/arm64/*.vdex
3. Confirmed valid ART runtime loading during boot

Signed-off-by: johnmart19 <johnivan19999@gmail.com>
Signed-off-by: Quince <quinceroms@gmail.com>
2025-11-09 19:28:23 +05:30
Rve27
b9141a9f34 sm7125-common: Enable ScrollOptimizer
Change-Id: I1d415521e3e10839afb87f1c6691a6057deab797
Signed-off-by: Rve27 <rve27github@gmail.com>
Signed-off-by: Quince <quinceroms@gmail.com>
2025-11-09 19:28:11 +05:30
theshaenix
d5b0780c14 sm7125-common: rootdir: kang post_boot from miatolls common tree
* Synced post_boot script from Evolution-X miatolls common tree
  https://github.com/Evolution-X-Devices/device_xiaomi_sm6250-common/blob/bka/rootdir/bin/init.qcom.post_boot-atoll.sh
2025-11-09 19:26:16 +05:30
someone5678
51e6b220d3 sm7125-common: Build vendor.qti.hardware.capabilityconfigstore@1.0
Log:
07-08 14:11:18.637  1300  1300 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
07-08 14:11:18.724  1366  1366 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/vppservice": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by /vendor/lib64/libvpplibrary.so in namespace (default)
07-08 14:11:23.638  3100  3100 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
07-08 14:11:28.644  3177  3177 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
07-08 14:11:33.651  3194  3194 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
07-08 14:11:28.395  5816  5816 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
07-08 14:11:45.348  7112  7112 F linker  : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.qti.hardware.capabilityconfigstore@1.0-service": library "vendor.qti.hardware.capabilityconfigstore@1.0.so" not found: needed by main executable
2025-11-09 19:26:15 +05:30
theshaenix
1990a776fb sm7125-common: overlay: Aperture: Ignore redundant aux camera IDs
- Hide camera ID 6 (duplicate 1x lens)
- Hide camera ID 7 (logical/composite stub)
- Prevents duplicate selector and crash when switching lenses
2025-11-09 19:25:33 +05:30
theshaenix
3b20b70f4d sm7125-common: overlay: Allow aux camera package allowlist
- Add config_cameraAuxPackageAllowlist overlay
- Ensures Aperture can access auxiliary lenses
  when vendor aux camera whitelist is present
2025-11-09 19:25:33 +05:30
aminfauzi
3e49ec97fe sm7125-common: prop: Allow camera apps to access auxiliary camera
This enables camera apps (and other whitelisted apps) to use auxiliary sensors without HAL restrictions, preventing crashes when switching lenses.

Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-09 19:25:32 +05:30
aminfauzi
028c7ee1bd sm7125-common: overlay: Configure aux camera for Aperture
overlay from rmx2061 repo

Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-09 19:25:32 +05:30
theshaenix
631486dfff sm7125-common: prop: drop legacy camera EIS prop
- Set EIS enable and type using vendor props only
2025-11-09 19:22:09 +05:30
theshaenix
f8d7219744 sm7125-common: prop: set camera EIS type to 2
From dumpsys media.camera, the vendor tag showed EIS type = 2, which corresponds to:

0 → None
1 → EIS v2
2 → EIS v3
3 → OIS
4 → OIS + EIS

So your blobs natively support EIS v3 (type 2).
If you force is_type=4 (OIS+EIS) but your device only has EIS (no OIS hardware), the HAL may either:
silently fall back to EIS v3 (type 2), or misbehave / crash in certain modes
2025-11-09 19:22:09 +05:30
theshaenix
d852fdcb29 sm7125-common:Initialize EvolutionX 2025-11-09 19:22:09 +05:30
theshaenix
1e298d14a6 sm7125-common: fine tuned the zram 2025-11-09 19:22:09 +05:30
theshaenix
cfba3aaf95 Revert "sm7125-common : integrate Oplus camera vendor blobs"
This reverts commit ecff11a1d3.
2025-11-09 19:22:09 +05:30
theshaenix
8f96a9bf71 sm7125-common: rootdir : bin : Aggressive performance & boot optimization for RMX2061
- Fine-tuned GPU devfreq governors and frequencies for dynamic performance
  - Added support for simple_ondemand and msm-adreno-tz
  - AdrenoBoost handling for performance/battery modes
  - Dynamic min/max frequency assignment without killing idle sleep
- Improved ZRAM configuration
  - Auto-sized based on available RAM
  - Multi-threaded compression enabled
  - Aggressive memory management (swappiness 90, vfs_cache_pressure 80)
- VM and memory tweaks
  - Optimized dirty ratios, writeback intervals, overcommit, and compaction
  - Transparent HugePage disabled for faster memory reclaim
  - NUMA balancing disabled for unified memory efficiency
- LMK / RAM management updates
  - Preserves recent apps longer with custom minfree values
  - Extra free memory and watermark tuning
  - CPU cgroup tuning for foreground/background prioritization
- Thermal and network optimizations
  - Conservative thermal trip points to reduce throttling
  - TCP/IP stack and buffer tuning for low latency
- Bootspeed improvements
  - Suppressed printk, RCU and debug overhead
  - Disabled NMI watchdog and tracing for faster initialization
- Overall: Enhanced user experience for both gaming and everyday usage
  - Aggressive memory & GPU management without sacrificing idle or background tasks
2025-11-09 19:22:09 +05:30
theshaenix
a54e5c546c sm7125-common: ship excluded-input-devices.xml
- Add PRODUCT_COPY_FILES entry to install excluded-input-devices.xml
  into /vendor/etc
- Ensures vibrator HAL ignores blacklisted input devices
- Prevents duplicate or unintended haptic feedback
- Improves consistency of vibration across UI and apps
2025-11-09 19:22:08 +05:30
theshaenix
35b87f7c6d sm7125-common: configs: raise min blocks-per-second limit
- Increase blocks-per-second range from 24–979200 to 36–979200
- Prevents codec operation at extremely low block rates
- Reduces risk of underruns and playback instability
- Improves scheduling efficiency and smoother video performance

Trade-off: drops support for extreme low-FPS edge cases, but ensures
better stability across typical playback/recording scenarios.
2025-11-09 19:22:08 +05:30
theshaenix
0684cf355a sm7125-common: Switch to dot product CPU variant
* sm7125:/ $ cat /proc/cpuinfo | grep -m 1 Features
   Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
   atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp

 * From this, it's evident that our CPU (Snapdragon 720G)
   supports all the features of ARMv8.2-DotProd [1].
   Moreover AOSP sets this arch variant in their generic
   cortex-a55 ART target as well [2]. This should unlock
   some optimizations in different code paths.
[1]:
https://en.wikichip.org/wiki/arm/armv8#ARMv8_Extensions_and_Processor_Features
[2]:
https://android.googlesource.com/device/generic/art/+/refs/heads/master/armv8_cortex_a55/BoardConfig.mk#23
2025-11-09 19:22:08 +05:30
theshaenix
ffd1ddfbf9 sm7125-common : integrate Oplus camera vendor blobs
- Cloned proprietary_vendor_oplus_camera repo by pjgowtham
  (https://gitlab.com/pjgowtham/proprietary_vendor_oplus_camera.git)
- Added vendor/oplus/camera directory
- Updated device tree to include
2025-11-09 19:22:08 +05:30
theshaenix
e005ad2aa1 sm7125-common: rootdir : bin: tune CPU, scheduler and memory
- Enable ZRAM with LZ4 compression and tuned swappiness
- Adjust CPU hispeed freqs and minimums for better responsiveness
- Configure schedutil governor for both clusters
- Lower migration thresholds for smoother task distribution
- Tune core_ctl for balanced performance vs. idle drain
- Re-enable sleep states for improved standby battery
- Set up bw_hwmon and mem_latency governors on interconnects
- Cleaned out unnecessary/duplicate entries from script

Overall effect: smoother UI, faster app response, and better
multitasking with minimal idle power impact.
2025-11-09 19:22:07 +05:30
theshaenix
a8c5e9bdd5 sm7125-common:Switch to android.hardware.sensors@2.1 multihal
The legacy 2.0 multihal does not support ScopedWakelock handling,
causing non-wakeup sensors (e.g. BMI160 gyroscope) to stall unless
the screen is actively touched.

Migrate to android.hardware.sensors@2.1-service.multihal_realme_sm7125
to properly integrate ScopedWakelock and per-event wakelock tracking.

This resolves issues where the gyroscope only reported data
while the device was awake, ensuring continuous event delivery
even when idle.

Tested:
- Gyroscope events stream without requiring screen touches
- dumpsys sensorservice shows correct flags and batching
- No regressions observed in other HAL sensors
2025-11-09 19:22:07 +05:30
theshaenix
5a2b337dbc sm7125-common: reduced the status bar padding top 2025-11-09 19:22:07 +05:30
anhdat1024
8e19cbb0a5 sm7125-common: overlay: Adjust status bar height 2025-11-09 19:22:07 +05:30
theshaenix
c5ea61e49f sm7125-common: props: Use EIS for camera
* Fixes gcam video stabilization
2025-11-09 19:22:07 +05:30
theshaenix
be8403dea6 sm7125-common : rootdir: Optimize CPU governor, sched, and core control for Snapdragon 720G
- Replaced static performance governor with dynamic schedutil for all cores
    - Tuned up_rate_limit_us and down_rate_limit_us for smooth everyday performance
    - Set scaling_min and scaling_max frequencies according to Kryo 465 Gold/Silver cores
    - Configured core_ctl for little cluster (min_cpus, busy thresholds, offline delay)
    - Disabled core_ctl on big cluster to let scheduler manage ramp-up efficiently
    - Adjusted b.L scheduler parameters (sched_downmigrate, sched_upmigrate, group migrate)
    - Set sched_little_cluster_coloc_fmin_khz for smoother colocation
    - Applied sched_load_boost per CPU for better responsiveness
    - Configured input boost frequency and duration for UI snappiness
    - Updated memory and bus DCVS parameters for balanced performance/power
    - Maintained conservative power optimizations (cpusets, sleep modes, kswapd, I/O scheduler)

    This commit ensures a universal setup for normal daily use and gaming while
    avoiding overheating and maintaining high FPS
2025-11-09 19:22:06 +05:30
aminfauzi
bccca041aa sm7125-common:audio: Sync with Spatial Audio
Signed-off-by: aminfauzi <aremean0107@gmail.com>
2025-11-09 19:22:06 +05:30
theshaenix
4f22c6fe43 sm7125-common: overlay: Enable Wifi display 2025-11-09 19:22:06 +05:30
theshaenix
025b4df531 sm7125-common: sm7125-common: overlay: Speed up animations
On low powered, legacy devices, the animations are a bit sluggish. Set the animation scales to 50% to make the UI feel snappier.
2025-11-09 19:22:06 +05:30
Skyblueborb
195e21ae45 sm7125-common: Label cust partition
Fixes flashing `cust` through fastbootd.

Change-Id: I1a950037dafa99c5e7b4305dda4aa8d35fce143b
Signed-off-by: Skyblueborb <tomaszborbely0710@gmail.com>
2025-11-09 19:22:06 +05:30
theshaenix
57f7fb9151 sm7125-common: Disable scudo to save ram 2025-11-09 19:22:06 +05:30
theshaenix
e5405be694 sm7125-common: Switch to AIDL LiveDisplay HAL 2025-11-09 19:22:05 +05:30
LuK1337
e455368c95 sm7125-common: Set SSR restart_level in init.qcom.rc
Change-Id: I31e174f8c3647c17152a2b225b1bb524e22e07aa
2025-11-09 19:22:05 +05:30
theshaenix
0a8fe4c93c Revert "sm7125--common: Commonize schedtune and cpuset configuration"
This reverts commit 13f221fb28.
2025-11-09 19:22:05 +05:30
theshaenix
0b3cef643a sm7125-common: Disable EPPE targets 2025-11-09 19:22:05 +05:30
theshaenix
a31601d296 sm7125-common: Added new allow rules to sepolicy 2025-11-09 19:22:05 +05:30
theshaenix
0de72b411d sm7125-common: overlay: Enable BoostFramework support 2025-11-09 19:22:04 +05:30
theshaenix
d94aacfeb1 sm7125-common: switch to AIDL fingerprint HAL 2025-11-09 19:22:04 +05:30
Arian
98dd114623 sm7125-common: rootdir: Enable PowerHAL hint processing
Change-Id: I4de6ec81eaf002c094df53ff26ed24db02972dfe
2025-11-09 19:22:00 +05:30
67 changed files with 350 additions and 5419 deletions

View File

@@ -45,6 +45,11 @@ TARGET_2ND_CPU_ABI2 := armeabi
TARGET_2ND_CPU_VARIANT := cortex-a76
TARGET_2ND_CPU_VARIANT_RUNTIME := cortex-a76
# ART
WITH_DEXPREOPT := true
DEX_PREOPT_DEFAULT := generate-vdex-and-image
WITH_DEXPREOPT_DEBUG_INFO := false
# Audio
AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true
AUDIO_FEATURE_ENABLED_HDMI_SPK := true
@@ -96,7 +101,6 @@ BOARD_HAVE_QCOM_FM := true
DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE := \
hardware/qcom-caf/common/vendor_framework_compatibility_matrix.xml \
hardware/qcom-caf/common/vendor_framework_compatibility_matrix_legacy.xml \
vendor/lineage/config/device_framework_matrix.xml \
$(COMMON_PATH)/framework_compatibility_matrix.xml
DEVICE_MANIFEST_FILE := \
@@ -108,6 +112,9 @@ DEVICE_MATRIX_FILE := \
ODM_MANIFEST_SKUS := nfc
ODM_MANIFEST_NFC_FILES := $(COMMON_PATH)/manifest_nfc.xml
# HWUI
HWUI_COMPILE_FOR_PERF := true
# Kernel
BOARD_KERNEL_BASE := 0x00000000
BOARD_KERNEL_IMAGE_NAME := Image.gz

View File

@@ -22,6 +22,9 @@ $(call inherit-product, hardware/qcom-caf/common/common.mk)
# UDFPS
$(call soong_config_set,surfaceflinger,udfps_lib,//$(LOCAL_PATH):libudfps_extension.realme_sm7125)
# speaker layout channel mask
$(call soong_config_set,android_hardware_audio,skip_speaker_layout_channel_mask_field,true)
# Partitions
PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_BOARD_PLATFORM := atoll
@@ -99,10 +102,6 @@ PRODUCT_COPY_FILES += \
#CertifiedProps
$(call inherit-product-if-exists, vendor/certprops/Android.mk)
# Core Packages
PRODUCT_PACKAGES += \
Parts
# Config Store
PRODUCT_PACKAGES += \
disable_configstore \
@@ -231,9 +230,11 @@ PRODUCT_PACKAGES += \
init.qcom.usb.rc \
init.sm7125.rc
# Recovery init script
# Recovery
PRODUCT_PACKAGES += \
init.recovery.qcom.sh
init.recovery.qcom.sh \
init.recovery.qcom.rc \
init.recovery.usb.rc
# Vendor shell scripts
PRODUCT_PACKAGES += \

View File

@@ -1,17 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (C) 2022-2024 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
autodetected from the Configuration. -->
@@ -21,9 +13,6 @@
<!-- The restoring is handled by modem if it is true-->
<bool name="skip_restoring_network_selection">true</bool>
<!-- Set to true to add links to Cell Broadcast app from Settings and MMS app. -->
<bool name="config_cellBroadcastAppLinks">true</bool>
<!-- M user agent string -->
<string name="config_mms_user_agent">Android-Mms/2.0</string>
@@ -161,6 +150,9 @@
Doze dreams will run whenever the power manager is in a dozing state. -->
<string name="config_dozeComponent">com.android.systemui/com.android.systemui.doze.DozeService</string>
<!-- Doze: should the TYPE_PICK_UP_GESTURE sensor be used as a pulse signal. -->
<bool name="config_dozePulsePickup">true</bool>
<!-- If true, the doze component is not started until after the screen has been
turned off and the screen off animation has been performed. -->
<bool name="config_dozeAfterScreenOffByDefault">true</bool>
@@ -218,10 +210,6 @@
on the headphone/microphone jack. When false use the older uevent framework. -->
<bool name="config_useDevInputEventForAudioJack">true</bool>
<!-- Boolean indicating whether the HWC setColorTransform function can be performed efficiently
in hardware. -->
<bool name="config_setColorTransformAccelerated">true</bool>
<!-- Flag indicating whether the we should enable the automatic brightness in Settings.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">true</bool>
@@ -366,11 +354,6 @@
Equivalent to 67/255 (default for this device) -->
<integer name="config_screenBrightnessSettingDefault">45</integer>
<!-- Vibrator pattern for a very short but reliable vibration for soft keyboard tap -->
<integer-array name="config_keyboardTapVibePattern">
<item>40</item>
</integer-array>
<!-- Vibrator pattern for feedback about a long screen/key press -->
<integer-array name="config_longPressVibePattern">
<item>0</item>
@@ -434,22 +417,58 @@
<!-- Default list of files pinned by the Pinner Service -->
<string-array translatable="false" name="config_defaultPinnerServiceFiles">
<item>"/apex/com.android.art/javalib/core-libart.jar"</item>
<item>"/apex/com.android.art/javalib/core-oj.jar"</item>
<item>"/apex/com.android.art/javalib/core-libart.jar"</item>
<item>"/system_ext/priv-app/SystemUI/SystemUI.apk"</item>
<item>"/system/bin/surfaceflinger"</item>
<item>"/system/framework/boot-framework.vdex"</item>
<item>"/system/framework/ext.jar"</item>
<item>"/system/framework/framework-res.apk"</item>
<item>"/system/framework/framework.jar"</item>
<item>"/system/framework/services.jar"</item>
<item>"/system/framework/ext.jar"</item>
<item>"/system/framework/telephony-common.jar"</item>
<item>"/system/lib/libEGL.so"</item>
<item>"/system/lib/libGLESv1_CM.so"</item>
<item>"/system/lib/libGLESv2.so"</item>
<item>"/system/lib/libGLESv3.so"</item>
<item>"/system/lib/libgui.so"</item>
<item>"/system/lib/libhwui.so"</item>
<item>"/system/lib/libui.so"</item>
<item>"/system/lib/libvulkan.so"</item>
<item>"/system/lib64/libEGL.so"</item>
<item>"/system/lib64/libGLESv1_CM.so"</item>
<item>"/system/lib64/libGLESv2.so"</item>
<item>"/system/lib64/libGLESv3.so"</item>
<item>"/system/lib64/libgui.so"</item>
<item>"/system/lib64/libhwui.so"</item>
<item>"/system_ext/priv-app/SystemUI/SystemUI.apk"</item>
<item>"/system/lib64/libui.so"</item>
<item>"/system/lib64/libvulkan.so"</item>
<item>"/vendor/lib/egl/eglSubDriverAndroid.so"</item>
<item>"/vendor/lib/egl/libEGL_adreno.so"</item>
<item>"/vendor/lib/egl/libGLESv1_CM_adreno.so"</item>
<item>"/vendor/lib/egl/libGLESv2_adreno.so"</item>
<item>"/vendor/lib/hw/vulkan.adreno.so"</item>
<item>"/vendor/lib/libCB.so"</item>
<item>"/vendor/lib/libOpenCL.so"</item>
<item>"/vendor/lib/libadreno_utils.so"</item>
<item>"/vendor/lib/libgsl.so"</item>
<item>"/vendor/lib/libllvm-glnext.so"</item>
<item>"/vendor/lib/libllvm-qcom.so"</item>
<item>"/vendor/lib64/egl/eglSubDriverAndroid.so"</item>
<item>"/vendor/lib64/egl/libEGL_adreno.so"</item>
<item>"/vendor/lib64/egl/libGLESv1_CM_adreno.so"</item>
<item>"/vendor/lib64/egl/libGLESv2_adreno.so"</item>
<item>"/vendor/lib64/hw/vulkan.adreno.so"</item>
<item>"/vendor/lib64/libCB.so"</item>
<item>"/vendor/lib64/libOpenCL.so"</item>
<item>"/vendor/lib64/libadreno_utils.so"</item>
<item>"/vendor/lib64/libgsl.so"</item>
<item>"/vendor/lib64/libllvm-qgl.so"</item>
<item>"/vendor/lib64/libllvm-glnext.so"</item>
<item>"/vendor/lib64/libllvm-qcom.so"</item>
</string-array>
<!-- Should the pinner service pin the Home application? -->
<bool name="config_pinnerHomeApp">true</bool>
<!-- Bytes that the PinnerService will pin for Home app -->
<integer name="config_pinnerHomePinBytes">6291456</integer>
<!-- List of files pinned by the Pinner Service with the JIT Zygote boot image b/119800099 -->
<string-array translatable="false" name="config_jitzygoteBootImagePinnerServiceFiles">
@@ -502,9 +521,6 @@
available on some devices. -->
<bool name="config_enableHapticTextHandle">true</bool>
<!-- Enable Zram writeback feature to allow unused pages in zram be written to flash. -->
<bool name="config_zramWriteback">true</bool>
<!-- Whether to post reset runnable for all clients. Needed for some older
vendor fingerprint HAL implementations. -->
<bool name="config_fingerprintPostResetRunnableForAllClients">true</bool>
@@ -565,6 +581,8 @@
manager will disable alpha trasformation in animations where not
strictly needed. -->
<bool name="config_sf_limitedAlpha">true</bool>
<!-- Whether the new Auto Selection Network UI should be shown -->
<bool name="config_enableNewAutoSelectNetworkUI">true</bool>
<!-- Package name of a telephony-related system app, such as an IMS service.
Exempted from privacy indicators. -->
@@ -589,9 +607,7 @@
<!-- Whether we use large screen shade header which takes only one row compared to QS header -->
<bool name="config_use_large_screen_shade_header">true</bool>
<!-- Boost Framework -->
<bool name="config_supportsBoostFramework">true</bool>
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
@@ -606,4 +622,8 @@
* The device must be provisioned with HDCP keys (for protected content).
-->
<bool name="config_enableWifiDisplay">true</bool>
</resources>
<!-- Whether WM DisplayContent supports high performance transitions
(lower-end devices may want to disable) -->
<bool name="config_deviceSupportsHighPerfTransitions">false</bool>
</resources>

View File

@@ -1,43 +0,0 @@
//
// Copyright (C) 2017-2020 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
android_app {
name: "Parts",
defaults: [
"SettingsLibDefaults",
],
srcs: [
"src/**/*.kt",
"src/**/*.java"
],
certificate: "platform",
resource_dirs: ["res"],
platform_apis: true,
system_ext_specific: true,
privileged: true,
static_libs: [
"androidx.core_core",
"org.lineageos.settings.resources"
],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
required: [
"privapp_whitelist_org.lineageos.settings.xml",
],
}
prebuilt_etc {
name: "privapp_whitelist_org.lineageos.settings.xml",
src: "permissions/privapp_whitelist_org.lineageos.settings.xml",
sub_dir: "permissions",
system_ext_specific: true,
}

View File

@@ -1,210 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-2016 The CyanogenMod Project
2017-2018 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.lineageos.settings"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="30"/>
<application
android:label="@string/app_title"
android:persistent="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:theme="@style/Theme.SubSettingsBase">
<receiver
android:name=".BootCompletedReceiver"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:replace="android:authorities"/>
<receiver
android:name=".Startup"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- TileHandler activity -->
<activity
android:name=".TileHandlerActivity"
android:exported="true"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
</intent-filter>
</activity>
<!-- Charging Bypass Activity -->
<activity
android:name=".charge.ChargeActivity"
android:label="@string/charge_bypass_title"
android:exported="true">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.battery" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/charge_bypass_summary" />
</activity>
<!-- Charging Bypass Monitoring Service -->
<service
android:name=".charge.ChargeBatteryMonitorService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="battery_optimization" />
</service>
<!-- Charging Bypass Boot Receiver -->
<receiver
android:name=".charge.ChargeReceiver"
android:enabled="true"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- Charging Bypass Quick Settings Tile -->
<service
android:name=".charge.ChargeQSTile"
android:enabled="true"
android:exported="true"
android:icon="@drawable/ic_charge_bypass"
android:label="@string/charge_bypass_qs_tile_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data
android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="false" />
</service>
<!-- Charging information tile service -->
<service
android:name=".charginginfo.ChargingInfoTileService"
android:icon="@drawable/ic_charging_speed"
android:label="@string/charging_tile_label"
android:exported="true"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
<meta-data
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="false" />
</service>
<!-- GameBar Overlay -->
<activity
android:name=".gamebar.GameBarSettingsActivity"
android:label="@string/game_bar_title"
android:theme="@style/Theme.SubSettingsBase"
android:exported="true">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.apps" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/game_bar_summary" />
</activity>
<!-- GameBar AppSelector -->
<activity android:name=".gamebar.GameBarAppSelectorActivity" />
<activity android:name=".gamebar.GameBarAppRemoverActivity" />
<!-- GameBar Overlay Tile Service -->
<service
android:name=".gamebar.GameBarTileService"
android:label="@string/game_bar_tile_label"
android:icon="@drawable/ic_gamebar"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />
</service>
<!-- GameBar Overlay Monitor Service -->
<service
android:name=".gamebar.GameBarMonitorService"
android:exported="false" />
<!-- GameBar BootReceiver -->
<receiver
android:name=".gamebar.GameBarBootReceiver"
android:exported="true"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 Paranoid Android
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<permissions>
<privapp-permissions package="org.lineageos.settings">
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
</permissions>

View File

View File

@@ -1,13 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4zM15,20H9V6h6V20z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M9,8h6v2H9z"/>
</vector>

View File

@@ -1,16 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4zM15,20H9V6h6V20z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M13,13a1,1 0 1,1 -2,0a1,1 0 1,1 2,0"/>
<path
android:fillColor="@android:color/white"
android:pathData="M12,10.5c-0.83,0 -1.5,0.67 -1.5,1.5h1c0,-0.28 0.22,-0.5 0.5,-0.5s0.5,0.22 0.5,0.5c0,0.5 -0.75,0.75 -0.75,1.5h1c0,-0.38 0.75,-0.75 0.75,-1.5C13.5,11.17 12.83,10.5 12,10.5z"/>
</vector>

View File

@@ -1,26 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorOnSurface">
<!-- Battery outline -->
<path
android:fillColor="@android:color/white"
android:pathData="M15.67,4H14V2c0,-0.55 -0.45,-1 -1,-1h-2c-0.55,0 -1,0.45 -1,1v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4z"/>
<!-- Bypass indicator (diagonal line) -->
<path
android:fillColor="@android:color/black"
android:pathData="M6,6l12,12"
android:strokeColor="@android:color/white"
android:strokeWidth="1.5"
android:strokeLineCap="round"/>
<!-- Lightning bolt (partially visible) -->
<path
android:fillColor="@android:color/black"
android:pathData="M11,9l1.5,0l-1.5,3l1,0l-1.5,3l-1.5,0l1.5,-3l-1,0z"/>
</vector>

View File

@@ -1,13 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4z"/>
<path
android:fillColor="@android:color/black"
android:pathData="M11,20v-5.5H9L13,7v5.5h2L11,20z"/>
</vector>

View File

@@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"/>
</vector>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M7,6H17A6,6 0 0,1 23,12A6,6 0 0,1 17,18C15.22,18 13.63,17.23 12.53,16H11.47C10.37,17.23 8.78,18 7,18A6,6 0 0,1 1,12A6,6 0 0,1 7,6M6,9V11H4V13H6V15H8V13H10V11H8V9H6M15.5,12A1.5,1.5 0 0,0 14,13.5A1.5,1.5 0 0,0 15.5,15A1.5,1.5 0 0,0 17,13.5A1.5,1.5 0 0,0 15.5,12M18.5,9A1.5,1.5 0 0,0 17,10.5A1.5,1.5 0 0,0 18.5,12A1.5,1.5 0 0,0 20,10.5A1.5,1.5 0 0,0 18.5,9Z" />
</vector>

View File

@@ -1,9 +0,0 @@
<!-- drawable/music_clef_bass.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="#000" android:pathData="M18.5 5A1.5 1.5 0 1 1 17 6.5A1.5 1.5 0 0 1 18.5 5M18.5 11A1.5 1.5 0 1 1 17 12.5A1.5 1.5 0 0 1 18.5 11M10 4A5 5 0 0 0 5 9V10A2 2 0 1 0 7.18 8A3 3 0 0 1 10 6A4 4 0 0 1 14 10C14 13.59 11.77 16.19 7 18.2L7.76 20.04C13.31 17.72 16 14.43 16 10A6 6 0 0 0 10 4Z" />
</vector>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/game_bar_fragment"
android:name="org.lineageos.settings.gamebar.GameBarFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/game_bar_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#80000000"
android:padding="8dp"
android:orientation="vertical">
</LinearLayout>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="8dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="16sp" />
<TextView
android:id="@+id/app_package"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>

View File

@@ -1,108 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2025 The Android Open Source Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- FPS Overlay -->
<string-array name="game_bar_fps_method_entries">
<item>New API (Default)</item>
<item>Legacy Sysfs</item>
</string-array>
<string-array name="game_bar_fps_method_values">
<item>new</item>
<item>legacy</item>
</string-array>
<!-- Update Interval -->
<string-array name="fps_overlay_update_interval_entries">
<item>Every 500ms</item>
<item>Every second</item>
<item>Every 2 seconds</item>
<item>Every 5 seconds</item>
</string-array>
<string-array name="fps_overlay_update_interval_values">
<item>500</item>
<item>1000</item>
<item>2000</item>
<item>5000</item>
</string-array>
<!-- Position -->
<string-array name="fps_overlay_position_entries">
<item>Top Left</item>
<item>Top Center</item>
<item>Top Right</item>
<item>Bottom Left</item>
<item>Bottom Center</item>
<item>Bottom Right</item>
<item>Custom Draggable</item>
</string-array>
<string-array name="fps_overlay_position_values">
<item>top_left</item>
<item>top_center</item>
<item>top_right</item>
<item>bottom_left</item>
<item>bottom_center</item>
<item>bottom_right</item>
<item>draggable</item>
</string-array>
<!-- Overlay color -->
<string-array name="fps_overlay_color_entries">
<item>White</item>
<item>Crimson</item>
<item>Fruit Salad</item>
<item>Royal Blue</item>
<item>Amber</item>
<item>Teal</item>
<item>Electric Violet</item>
<item>Magenta</item>
</string-array>
<string-array name="fps_overlay_color_values">
<item>#FFFFFF</item>
<item>#DC143C</item>
<item>#4CAF50</item>
<item>#4169E1</item>
<item>#FFBF00</item>
<item>#008080</item>
<item>#8A2BE2</item>
<item>#FF1493</item>
</string-array>
<!-- Overlay format -->
<string-array name="game_bar_format_entries">
<item>Full</item>
<item>Minimal</item>
</string-array>
<string-array name="game_bar_format_values">
<item>full</item>
<item>minimal</item>
</string-array>
<!-- Split Mode -->
<string-array name="game_bar_split_mode_entries">
<item>Side-by-Side</item>
<item>Stacked</item>
</string-array>
<string-array name="game_bar_split_mode_values">
<item>side_by_side</item>
<item>stacked</item>
</string-array>
<!-- Long press timeouts -->
<string-array name="game_bar_longpress_entries">
<item>1 second</item>
<item>3 seconds</item>
<item>5 seconds</item>
<item>10 seconds</item>
</string-array>
<string-array name="game_bar_longpress_values">
<item>1000</item>
<item>3000</item>
<item>5000</item>
<item>10000</item>
</string-array>
</resources>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MinMaxSeekBarPreference">
<attr name="minValue" format="integer" />
<attr name="maxValue" format="integer" />
</declare-styleable>
</resources>

View File

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Core Settings -->
<string name="app_title">Core Settings</string>
<string name="tile_add">Add tile</string>
<string name="tile_added">Tile added</string>
<string name="tile_not_added">Tile not added</string>
<string name="tile_already_added">Tile already added</string>
<string name="tile_on">On</string>
<string name="tile_off">Off</string>
<!-- GameBar Overlay -->
<string name="game_bar_title">GameBar</string>
<string name="game_bar_summary">Enable the system overlay (FPS, Temp, etc.)</string>
<string name="overlay_permission_required">Overlay permission is required</string>
<string name="overlay_permission_granted">Overlay permission granted</string>
<string name="overlay_permission_denied">Overlay permission denied</string>
<string name="game_bar_tile_label">GameBar</string>
<string name="game_bar_tile_description">Toggle the game overlay</string>
<!-- Charging information tile -->
<string name="charging_tile_label">Charging Speed</string>
<string name="charging_tile_information">Shows real-time charging/discharging power</string>
<!-- Tile states -->
<string name="charging_tile_charging">Charging</string>
<string name="charging_tile_discharging">Discharging</string>
<string name="charging_tile_not_charging">Not Charging</string>
<string name="charging_tile_error">Error</string>
<!-- Content descriptions for accessibility -->
<string name="charging_tile_desc_charging">Charging at %1$s watts, %2$s amps, %3$s volts</string>
<string name="charging_tile_desc_discharging">Discharging at %1$s watts</string>
<string name="charging_tile_desc_not_charging">Battery not charging or discharging</string>
<string name="charging_tile_desc_error">Unable to read charging information</string>
<!-- Charge bypass strings -->
<string name="charge_bypass_title">Charging Bypass</string>
<string name="charge_bypass_summary">Configure charging bypass settings</string>
<string name="charge_bypass_warning">Enabling charging bypass will prevent the battery from charging while plugged in. This may affect battery longevity if used incorrectly.</string>
<string name="charge_bypass_unavailable">Charging bypass is not supported on this device</string>
<!-- Master toggle strings -->
<string name="charge_bypass_master_title">Enable Charging Bypass</string>
<string name="charge_bypass_master_summary">Allow charging bypass based on selected configuration</string>
<!-- Configuration category -->
<string name="charge_bypass_configuration_title">Bypass Configuration</string>
<!-- Manual mode strings -->
<string name="charge_bypass_manual_title">Manual Control</string>
<string name="charge_bypass_manual_summary">Control charging bypass through Quick Settings tile</string>
<!-- Smart mode strings -->
<string name="charge_bypass_smart_title">Smart Control</string>
<string name="charge_bypass_smart_summary">Automatically manage charging bypass based on battery level</string>
<!-- Battery target strings -->
<string name="charge_bypass_battery_target_title">Battery Target</string>
<string name="charge_bypass_battery_target_summary">Bypass charging when battery reaches this level (%d%%)</string>
<!-- QS Tile strings -->
<string name="charge_bypass_qs_tile_label">Charging Bypass</string>
<string name="charge_bypass_qs_active">Bypass Active</string>
<string name="charge_bypass_qs_inactive">Bypass Inactive</string>
<string name="charge_bypass_qs_disabled">Bypass Disabled</string>
<!-- Notification strings -->
<string name="charge_bypass_notification_title">Charging Bypass Active</string>
<string name="charge_bypass_notification_text">Battery charging is currently bypassed</string>
<string name="charge_bypass_smart_enabled">Smart charging bypass enabled at %d%%</string>
<string name="charge_bypass_smart_disabled">Smart charging bypass disabled</string>
</resources>

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Main bypass toggle -->
<SwitchPreference
android:key="bypass_charge_master"
android:title="@string/charge_bypass_master_title"
android:summary="@string/charge_bypass_master_summary"
android:defaultValue="false" />
<!-- Configuration category -->
<PreferenceCategory
android:key="bypass_configuration_category"
android:title="@string/charge_bypass_configuration_title">
<!-- Manual bypass option -->
<CheckBoxPreference
android:key="bypass_mode_manual"
android:title="@string/charge_bypass_manual_title"
android:summary="@string/charge_bypass_manual_summary"
android:defaultValue="true" />
<!-- Smart bypass option -->
<CheckBoxPreference
android:key="bypass_mode_smart"
android:title="@string/charge_bypass_smart_title"
android:summary="@string/charge_bypass_smart_summary"
android:defaultValue="false" />
</PreferenceCategory>
<!-- Battery target slider (only visible in smart mode) -->
<org.lineageos.settings.charge.MinMaxSeekBarPreference
android:key="battery_target_slider"
android:title="@string/charge_bypass_battery_target_title"
android:summary="@string/charge_bypass_battery_target_summary"
android:min="50"
android:max="100"
android:defaultValue="80"
android:dependency="bypass_mode_smart" />
</PreferenceScreen>

View File

@@ -1,252 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto">
<com.android.settingslib.widget.MainSwitchPreference
android:key="game_bar_enable"
android:title="Enable GameBar Overlay"
android:summary="@string/game_bar_summary"
android:defaultValue="false" />
<PreferenceCategory
android:title="Overlay Features"
android:dependency="game_bar_enable">
<SwitchPreferenceCompat
android:key="game_bar_fps_enable"
android:title="FPS Overlay"
android:summary="Show current FPS on screen"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_temp_enable"
android:title="Device Temperature"
android:summary="Show device (battery) temperature"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_cpu_usage_enable"
android:title="CPU Usage"
android:summary="Show current CPU usage percentage"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_cpu_clock_enable"
android:title="CPU Clock Speeds"
android:summary="Show current CPU clock speeds for each core"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_cpu_temp_enable"
android:title="CPU Temperature"
android:summary="Show CPU temperature (thermal_zone0)"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_ram_enable"
android:title="RAM Usage"
android:summary="Show current RAM usage in MB"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_gpu_usage_enable"
android:title="GPU Usage"
android:summary="Show GPU usage percentage"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_gpu_clock_enable"
android:title="GPU Clock Speed"
android:summary="Show current GPU clock frequency"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_gpu_temp_enable"
android:title="GPU Temperature"
android:summary="Show current GPU temperature"
android:defaultValue="false" />
</PreferenceCategory>
<PreferenceCategory
android:title="FPS Measurement Method"
android:dependency="game_bar_fps_enable">
<ListPreference
android:key="game_bar_fps_method"
android:title="Select FPS Method"
android:summary="Choose between the New API method (default) and Legacy Sysfs"
android:defaultValue="new"
android:entries="@array/game_bar_fps_method_entries"
android:entryValues="@array/game_bar_fps_method_values" />
</PreferenceCategory>
<PreferenceCategory
android:title="Customization"
android:dependency="game_bar_enable">
<SeekBarPreference
android:key="game_bar_text_size"
android:title="Text Size"
android:summary="Adjust the size of overlay text"
android:defaultValue="16"
android:max="32"
android:min="12" />
<SeekBarPreference
android:key="game_bar_background_alpha"
android:title="Background Transparency"
android:summary="Adjust the transparency of the background"
android:defaultValue="128"
android:max="255"
android:min="0" />
<SeekBarPreference
android:key="game_bar_corner_radius"
android:title="Overlay Corner Radius"
android:summary="Adjust how rounded the overlay corners should be"
android:defaultValue="16"
android:max="100"
android:min="0" />
<SeekBarPreference
android:key="game_bar_padding"
android:title="Overlay Padding"
android:summary="Adjust the space around the stats"
android:defaultValue="12"
android:max="64"
android:min="0" />
<SeekBarPreference
android:key="game_bar_item_spacing"
android:title="Item Spacing"
android:summary="Adjust spacing between overlay lines"
android:defaultValue="8"
android:max="50"
android:min="0" />
<ListPreference
android:key="game_bar_update_interval"
android:title="Update Interval"
android:summary="Set how often the overlay values update"
android:defaultValue="1000"
android:entries="@array/fps_overlay_update_interval_entries"
android:entryValues="@array/fps_overlay_update_interval_values" />
<ListPreference
android:key="game_bar_title_color"
android:title="Stat Title Color"
android:summary="Color for 'FPS', 'Temp', 'CPU', etc. text"
android:defaultValue="#FFFFFF"
android:entries="@array/fps_overlay_color_entries"
android:entryValues="@array/fps_overlay_color_values" />
<ListPreference
android:key="game_bar_value_color"
android:title="Stat Value Color"
android:summary="Color for numeric stats (e.g., '29', '32.0°C')"
android:defaultValue="#4CAF50"
android:entries="@array/fps_overlay_color_entries"
android:entryValues="@array/fps_overlay_color_values" />
<ListPreference
android:key="game_bar_position"
android:title="Overlay Position"
android:summary="Select the position of the overlay on screen"
android:defaultValue="top_left"
android:entries="@array/fps_overlay_position_entries"
android:entryValues="@array/fps_overlay_position_values" />
<ListPreference
android:key="game_bar_format"
android:title="Overlay Format"
android:summary="Choose between Full or Minimal display"
android:defaultValue="full"
android:entries="@array/game_bar_format_entries"
android:entryValues="@array/game_bar_format_values" />
</PreferenceCategory>
<PreferenceCategory
android:title="Split Config"
android:dependency="game_bar_enable">
<ListPreference
android:key="game_bar_split_mode"
android:title="Split Mode"
android:summary="Choose Side-by-Side or Stacked arrangement"
android:defaultValue="stacked"
android:entries="@array/game_bar_split_mode_entries"
android:entryValues="@array/game_bar_split_mode_values" />
</PreferenceCategory>
<PreferenceCategory
android:title="Overlay Gesture Controls"
android:dependency="game_bar_enable">
<SwitchPreferenceCompat
android:key="game_bar_single_tap_toggle"
android:title="Enable Single Tap to Toggle"
android:summary="Tap once to switch between full and minimal overlay formats"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_doubletap_capture"
android:title="Enable Double Tap to Capture"
android:summary="Double-tap overlay to start/stop capture logs"
android:defaultValue="false" />
<SwitchPreferenceCompat
android:key="game_bar_longpress_enable"
android:title="Enable Long Press"
android:summary="Long-press overlay to access GameBar settings"
android:defaultValue="false" />
<ListPreference
android:key="game_bar_longpress_timeout"
android:title="Long Press Duration"
android:summary="Set the duration required to long-press the overlay"
android:defaultValue="1000"
android:entries="@array/game_bar_longpress_entries"
android:entryValues="@array/game_bar_longpress_values"
android:dependency="game_bar_longpress_enable" />
</PreferenceCategory>
<PreferenceCategory
android:title="Capture Logs"
android:dependency="game_bar_enable">
<Preference
android:key="game_bar_capture_start"
android:title="Start Logging"
android:summary="Begin capturing FPS and performance data in real-time" />
<Preference
android:key="game_bar_capture_stop"
android:title="Stop Logging"
android:summary="Stop capturing FPS and performance data in real-time" />
<Preference
android:key="game_bar_capture_export"
android:title="Export GameBar Log Data"
android:summary="Save the captured FPS and performance data as a CSV file" />
</PreferenceCategory>
<PreferenceCategory
android:title="Auto Enable GameBar">
<SwitchPreferenceCompat
android:key="game_bar_auto_enable"
android:title="Auto-Enable GameBar for Selected Apps"
android:summary="If turned on, selected apps will auto-enable GameBar even if the main switch is off"
android:defaultValue="false" />
<Preference
android:key="game_bar_app_selector"
android:title="Select Apps"
android:summary="Add apps that should auto-enable GameBar" />
<Preference
android:key="game_bar_app_remover"
android:title="Remove Selected Apps"
android:summary="Remove apps from the auto-enable list" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -1,71 +0,0 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2019 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
public class BootCompletedReceiver extends BroadcastReceiver {
private static final String TAG = "Parts";
private static final boolean DEBUG = true;
@Override
public void onReceive(final Context context, Intent intent) {
if (DEBUG) Log.i(TAG, "Received intent: " + intent.getAction());
switch (intent.getAction()) {
case Intent.ACTION_LOCKED_BOOT_COMPLETED:
handleLockedBootCompleted(context);
break;
case Intent.ACTION_BOOT_COMPLETED:
handleBootCompleted(context);
break;
}
}
private void handleLockedBootCompleted(Context context) {
if (DEBUG) Log.i(TAG, "Handling locked boot completed.");
try {
// Start necessary services
startServices(context);
} catch (Exception e) {
Log.e(TAG, "Error during locked boot completed processing", e);
}
}
private void handleBootCompleted(Context context) {
if (DEBUG) Log.i(TAG, "Handling boot completed.");
// Add additional boot-completed actions if needed
}
private void startServices(Context context) {
if (DEBUG) Log.i(TAG, "Starting services...");
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.service.quicksettings.TileService;
import android.util.Log;
import java.util.HashMap;
import java.util.Map;
import org.lineageos.settings.gamebar.GameBarSettingsActivity;
import org.lineageos.settings.gamebar.GameBarTileService;
import org.lineageos.settings.charge.ChargeActivity;
import org.lineageos.settings.charge.ChargeQSTile;
import org.lineageos.settings.charginginfo.ChargingInfoTileService;
public final class TileHandlerActivity extends Activity {
private static final String TAG = "TileHandlerActivity";
// Map QS Tile services to their corresponding activity
private static final Map<String, Class<?>> TILE_ACTIVITY_MAP = new HashMap<>();
static {
TILE_ACTIVITY_MAP.put(GameBarTileService.class.getName(), GameBarSettingsActivity.class);
TILE_ACTIVITY_MAP.put(ChargeQSTile.class.getName(), ChargeActivity.class);
TILE_ACTIVITY_MAP.put(ChargingInfoTileService.class.getName(), ChargeActivity.class);
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
if (intent == null || !TileService.ACTION_QS_TILE_PREFERENCES.equals(intent.getAction())) {
Log.e(TAG, "Invalid or null intent received");
finish();
return;
}
final ComponentName qsTile = intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME);
if (qsTile == null) {
Log.e(TAG, "No QS tile component found in intent");
finish();
return;
}
final String qsName = qsTile.getClassName();
final Intent targetIntent = new Intent();
// Check if the tile is mapped to an activity
if (TILE_ACTIVITY_MAP.containsKey(qsName)) {
targetIntent.setClass(this, TILE_ACTIVITY_MAP.get(qsName));
Log.d(TAG, "Launching settings activity for QS tile: " + qsName);
} else {
// Default: Open app settings for the QS tile's package
final String packageName = qsTile.getPackageName();
if (packageName == null) {
Log.e(TAG, "QS tile package name is null");
finish();
return;
}
targetIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
targetIntent.setData(Uri.fromParts("package", packageName, null));
Log.d(TAG, "Opening app info for package: " + packageName);
}
// Ensure proper navigation behavior
targetIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(targetIntent);
finish();
}
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.os.Bundle;
import android.view.MenuItem;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
public class ChargeActivity extends CollapsingToolbarBaseActivity {
private static final String TAG_BYPASS_CHARGE = "bypass_charge";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportFragmentManager().beginTransaction().replace(
com.android.settingslib.collapsingtoolbar.R.id.content_frame,
new ChargeSettingsFragment(), TAG_BYPASS_CHARGE).commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return false;
}
}

View File

@@ -1,209 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.util.Log;
import org.lineageos.settings.R;
public class ChargeBatteryMonitorService extends Service {
private static final String TAG = "ChargeBatteryMonitorService";
private static final String NOTIFICATION_CHANNEL_ID = "charge_bypass_channel";
private static final int NOTIFICATION_ID = 1001;
private ChargeUtils mChargeUtils;
private BatteryReceiver mBatteryReceiver;
private NotificationManager mNotificationManager;
private boolean mIsMonitoring = false;
@Override
public void onCreate() {
super.onCreate();
mChargeUtils = new ChargeUtils(this);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
createNotificationChannel();
Log.d(TAG, "Service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mChargeUtils.isMasterToggleEnabled()) {
Log.d(TAG, "Master toggle disabled, stopping service");
stopSelf();
return START_NOT_STICKY;
}
if (!mIsMonitoring) {
startMonitoring();
}
return START_STICKY; // Restart service if killed
}
@Override
public void onDestroy() {
super.onDestroy();
stopMonitoring();
Log.d(TAG, "Service destroyed");
}
@Override
public IBinder onBind(Intent intent) {
return null; // We don't provide binding
}
private void startMonitoring() {
if (mIsMonitoring) return;
mBatteryReceiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
registerReceiver(mBatteryReceiver, filter);
mIsMonitoring = true;
// Initial check
mChargeUtils.updateBypassState();
updateNotification();
Log.d(TAG, "Started battery monitoring");
}
private void stopMonitoring() {
if (!mIsMonitoring) return;
if (mBatteryReceiver != null) {
unregisterReceiver(mBatteryReceiver);
mBatteryReceiver = null;
}
mIsMonitoring = false;
stopForeground(true);
Log.d(TAG, "Stopped battery monitoring");
}
private void createNotificationChannel() {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Charging Bypass",
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Charging bypass monitoring service");
channel.setShowBadge(false);
mNotificationManager.createNotificationChannel(channel);
}
private void updateNotification() {
if (!mIsMonitoring) return;
boolean bypassActive = mChargeUtils.isBypassChargeEnabled();
int batteryLevel = mChargeUtils.getCurrentBatteryLevel();
int mode = mChargeUtils.getBypassMode();
// If bypass is not active, hide notification completely regardless of mode
if (!bypassActive) {
stopForeground(true);
mNotificationManager.cancel(NOTIFICATION_ID);
return;
}
String title = getString(R.string.charge_bypass_notification_title);
String text;
if (mode == ChargeUtils.MODE_SMART) {
int target = mChargeUtils.getBatteryTarget();
if (bypassActive) {
text = getString(R.string.charge_bypass_smart_enabled, target);
} else {
text = "Smart mode active - Target: " + target + "% (Current: " + batteryLevel + "%)";
}
} else {
text = getString(R.string.charge_bypass_notification_text);
}
// Create a simple settings intent instead of ChargeActivity
Intent settingsIntent = new Intent(android.provider.Settings.ACTION_SETTINGS);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, settingsIntent, PendingIntent.FLAG_IMMUTABLE
);
Notification notification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setContentTitle(title)
.setContentText(text)
.setSmallIcon(android.R.drawable.ic_menu_manage) // Use system icon as fallback
.setContentIntent(pendingIntent)
.setOngoing(true)
.setShowWhen(false)
.build();
if (bypassActive) {
startForeground(NOTIFICATION_ID, notification);
}
}
private class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BATTERY_CHANGED.equals(action) ||
Intent.ACTION_POWER_CONNECTED.equals(action) ||
Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
Log.d(TAG, "Battery state changed: " + action);
// Check if we should still be running
if (!mChargeUtils.isMasterToggleEnabled()) {
Log.d(TAG, "Master toggle disabled, stopping service");
stopSelf();
return;
}
// Update bypass state based on current conditions
boolean wasActive = mChargeUtils.isBypassChargeEnabled();
mChargeUtils.updateBypassState();
boolean isActive = mChargeUtils.isBypassChargeEnabled();
// Update notification
updateNotification();
// Log state changes
if (wasActive != isActive) {
int batteryLevel = mChargeUtils.getCurrentBatteryLevel();
Log.d(TAG, "Bypass state changed: " + isActive +
" (Battery: " + batteryLevel + "%)");
}
}
}
}
}

View File

@@ -1,121 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import org.lineageos.settings.R;
public class ChargeQSTile extends TileService {
private static final String TAG = "ChargeQSTile";
private ChargeUtils mChargeUtils;
@Override
public void onCreate() {
super.onCreate();
mChargeUtils = new ChargeUtils(this);
}
@Override
public void onStartListening() {
super.onStartListening();
updateTile();
}
@Override
public void onStopListening() {
super.onStopListening();
}
@Override
public void onClick() {
super.onClick();
if (!mChargeUtils.canToggleManually()) {
// Show inactive state if not in manual mode or master toggle is off
updateTile();
return;
}
// Toggle manual bypass state
boolean currentState = mChargeUtils.getManualBypassState();
mChargeUtils.setManualBypassState(!currentState);
// Update tile immediately
updateTile();
Log.d(TAG, "Manual bypass toggled to: " + !currentState);
}
private void updateTile() {
Tile tile = getQsTile();
if (tile == null) return;
boolean masterEnabled = mChargeUtils.isMasterToggleEnabled();
boolean isManualMode = mChargeUtils.getBypassMode() == ChargeUtils.MODE_MANUAL;
boolean canToggle = masterEnabled && isManualMode;
boolean bypassActive = mChargeUtils.isBypassChargeEnabled();
// Set tile icon
Icon icon = Icon.createWithResource(this, R.drawable.ic_charge_bypass);
tile.setIcon(icon);
// Set tile label
tile.setLabel(getString(R.string.charge_bypass_qs_tile_label));
if (!masterEnabled) {
// Master toggle is off
tile.setState(Tile.STATE_UNAVAILABLE);
tile.setSubtitle(getString(R.string.charge_bypass_qs_disabled));
} else if (!isManualMode) {
// In smart mode
tile.setState(Tile.STATE_UNAVAILABLE);
tile.setSubtitle("Smart Mode");
} else if (canToggle) {
// Manual mode and can toggle
if (bypassActive) {
tile.setState(Tile.STATE_ACTIVE);
tile.setSubtitle(getString(R.string.charge_bypass_qs_active));
} else {
tile.setState(Tile.STATE_INACTIVE);
tile.setSubtitle(getString(R.string.charge_bypass_qs_inactive));
}
} else {
// Fallback state
tile.setState(Tile.STATE_UNAVAILABLE);
tile.setSubtitle(getString(R.string.charge_bypass_qs_disabled));
}
tile.updateTile();
}
@Override
public void onTileAdded() {
super.onTileAdded();
updateTile();
}
@Override
public void onTileRemoved() {
super.onTileRemoved();
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ChargeReceiver extends BroadcastReceiver {
private static final String TAG = "ChargeReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BOOT_COMPLETED.equals(action) ||
Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)) {
Log.d(TAG, "Boot completed, restoring charge bypass settings");
ChargeUtils chargeUtils = new ChargeUtils(context);
// Check if bypass is supported on this device
if (!chargeUtils.isBypassChargeSupported()) {
Log.d(TAG, "Bypass not supported on this device");
return;
}
// Restore bypass state based on saved preferences
if (chargeUtils.isMasterToggleEnabled()) {
Log.d(TAG, "Master toggle enabled, restoring bypass state");
// Reset bypass to disabled state first
chargeUtils.enableBypassCharge(false);
// Start monitoring service if needed
int mode = chargeUtils.getBypassMode();
if (mode == ChargeUtils.MODE_SMART) {
Intent serviceIntent = new Intent(context, ChargeBatteryMonitorService.class);
context.startService(serviceIntent);
Log.d(TAG, "Started battery monitoring service for smart mode");
} else if (mode == ChargeUtils.MODE_MANUAL) {
// In manual mode, respect the saved manual state
// but don't automatically enable bypass on boot for safety
chargeUtils.setManualBypassState(false);
Log.d(TAG, "Manual mode restored, bypass disabled for safety");
}
// Update bypass state based on current conditions
chargeUtils.updateBypassState();
} else {
Log.d(TAG, "Master toggle disabled, ensuring bypass is off");
chargeUtils.enableBypassCharge(false);
}
}
}
}

View File

@@ -1,203 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.CheckBoxPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
import org.lineageos.settings.R;
import androidx.preference.PreferenceFragmentCompat;
public class ChargeSettingsFragment extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener {
private static final String TAG = "ChargeSettingsFragment";
// Preference keys
private static final String KEY_BYPASS_CHARGE_MASTER = "bypass_charge_master";
private static final String KEY_BYPASS_MODE_MANUAL = "bypass_mode_manual";
private static final String KEY_BYPASS_MODE_SMART = "bypass_mode_smart";
private static final String KEY_BATTERY_TARGET_SLIDER = "battery_target_slider";
private static final String KEY_BYPASS_CONFIGURATION_CATEGORY = "bypass_configuration_category";
// Preferences
private SwitchPreference mMasterToggle;
private CheckBoxPreference mManualMode;
private CheckBoxPreference mSmartMode;
private MinMaxSeekBarPreference mBatteryTarget;
private PreferenceCategory mConfigurationCategory;
private ChargeUtils mChargeUtils;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.charge_settings, rootKey);
mChargeUtils = new ChargeUtils(getActivity());
// Initialize preferences
mMasterToggle = (SwitchPreference) findPreference(KEY_BYPASS_CHARGE_MASTER);
mManualMode = (CheckBoxPreference) findPreference(KEY_BYPASS_MODE_MANUAL);
mSmartMode = (CheckBoxPreference) findPreference(KEY_BYPASS_MODE_SMART);
mBatteryTarget = (MinMaxSeekBarPreference) findPreference(KEY_BATTERY_TARGET_SLIDER);
mConfigurationCategory = (PreferenceCategory) findPreference(KEY_BYPASS_CONFIGURATION_CATEGORY);
boolean bypassSupported = mChargeUtils.isBypassChargeSupported();
if (!bypassSupported) {
// Disable all preferences if bypass is not supported
mMasterToggle.setEnabled(false);
mMasterToggle.setSummary(R.string.charge_bypass_unavailable);
mConfigurationCategory.setEnabled(false);
return;
}
// Set up master toggle
mMasterToggle.setChecked(mChargeUtils.isMasterToggleEnabled());
mMasterToggle.setOnPreferenceChangeListener(this);
// Set up mode preferences
int currentMode = mChargeUtils.getBypassMode();
mManualMode.setChecked(currentMode == ChargeUtils.MODE_MANUAL);
mSmartMode.setChecked(currentMode == ChargeUtils.MODE_SMART);
mManualMode.setOnPreferenceChangeListener(this);
mSmartMode.setOnPreferenceChangeListener(this);
// Set up battery target slider - Let the preference handle all mapping internally
int batteryTarget = mChargeUtils.getBatteryTarget();
mBatteryTarget.setBatteryTarget(batteryTarget); // Use the new method from MinMaxSeekBarPreference
mBatteryTarget.setOnPreferenceChangeListener(this);
updateBatteryTargetSummary(batteryTarget);
Log.d(TAG, "Initial battery target: " + batteryTarget + "%");
// Update UI state based on master toggle
updateConfigurationVisibility(mChargeUtils.isMasterToggleEnabled());
updateBatteryTargetVisibility(currentMode == ChargeUtils.MODE_SMART);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String key = preference.getKey();
switch (key) {
case KEY_BYPASS_CHARGE_MASTER:
boolean masterEnabled = (Boolean) newValue;
if (masterEnabled) {
showMasterToggleWarning(() -> {
mChargeUtils.setMasterToggleEnabled(true);
updateConfigurationVisibility(true);
startBatteryMonitorService();
});
return false; // Don't update UI until user confirms
} else {
mChargeUtils.setMasterToggleEnabled(false);
mChargeUtils.enableBypassCharge(false); // Disable bypass immediately
updateConfigurationVisibility(false);
stopBatteryMonitorService();
return true;
}
case KEY_BYPASS_MODE_MANUAL:
if ((Boolean) newValue) {
mSmartMode.setChecked(false);
mChargeUtils.setBypassMode(ChargeUtils.MODE_MANUAL);
updateBatteryTargetVisibility(false);
stopBatteryMonitorService();
return true;
}
return false; // Don't allow unchecking without selecting another mode
case KEY_BYPASS_MODE_SMART:
if ((Boolean) newValue) {
mManualMode.setChecked(false);
mChargeUtils.setBypassMode(ChargeUtils.MODE_SMART);
updateBatteryTargetVisibility(true);
startBatteryMonitorService();
return true;
}
return false; // Don't allow unchecking without selecting another mode
case KEY_BATTERY_TARGET_SLIDER:
// FIXED: Calculate the battery target based on the new slider value
int sliderValue = (Integer) newValue;
// Create a temporary preference object to calculate the mapped value
// since the preference hasn't been updated yet
int actualBatteryTarget = mBatteryTarget.calculateBatteryTargetFromSlider(sliderValue);
Log.d(TAG, "Slider changed - Position: " + sliderValue + "%, Battery target: " + actualBatteryTarget + "%");
mChargeUtils.setBatteryTarget(actualBatteryTarget);
updateBatteryTargetSummary(actualBatteryTarget);
return true;
}
return false;
}
private void showMasterToggleWarning(Runnable onConfirm) {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.charge_bypass_master_title)
.setMessage(R.string.charge_bypass_warning)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
mMasterToggle.setChecked(true);
if (onConfirm != null) {
onConfirm.run();
}
})
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
mMasterToggle.setChecked(false);
})
.show();
}
private void updateConfigurationVisibility(boolean visible) {
mConfigurationCategory.setVisible(visible);
if (visible) {
int currentMode = mChargeUtils.getBypassMode();
updateBatteryTargetVisibility(currentMode == ChargeUtils.MODE_SMART);
} else {
updateBatteryTargetVisibility(false);
}
}
private void updateBatteryTargetVisibility(boolean visible) {
mBatteryTarget.setVisible(visible);
}
private void updateBatteryTargetSummary(int value) {
String summaryText = getString(R.string.charge_bypass_battery_target_summary, value);
mBatteryTarget.setSummary(summaryText);
}
private void startBatteryMonitorService() {
Intent serviceIntent = new Intent(getActivity(), ChargeBatteryMonitorService.class);
getActivity().startService(serviceIntent);
}
private void stopBatteryMonitorService() {
Intent serviceIntent = new Intent(getActivity(), ChargeBatteryMonitorService.class);
getActivity().stopService(serviceIntent);
}
}

View File

@@ -1,239 +0,0 @@
/*
* Copyright (C) 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.charge;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.util.Log;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.utils.FileUtils;
public class ChargeUtils {
private static final String TAG = "ChargeUtils";
// Sysfs node for bypass control
public static final String BYPASS_CHARGE_NODE = "/sys/class/power_supply/battery/input_suspend";
// Bypass modes
public static final int MODE_MANUAL = 0;
public static final int MODE_SMART = 1;
// Bypass states
public static final int BYPASS_DISABLED = 0;
public static final int BYPASS_ENABLED = 1;
// SharedPreferences keys
private static final String PREF_MASTER_TOGGLE = "bypass_charge_master";
private static final String PREF_BYPASS_MODE = "bypass_mode";
private static final String PREF_BATTERY_TARGET = "battery_target";
private static final String PREF_MANUAL_BYPASS_STATE = "manual_bypass_state";
// Default values
private static final int DEFAULT_BATTERY_TARGET = 80;
private static final int BATTERY_HYSTERESIS = 5; // 5% hysteresis for smart mode
private Context mContext;
private SharedPreferences mSharedPrefs;
public ChargeUtils(Context context) {
mContext = context;
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
}
// Master toggle methods
public boolean isMasterToggleEnabled() {
return mSharedPrefs.getBoolean(PREF_MASTER_TOGGLE, false);
}
public void setMasterToggleEnabled(boolean enabled) {
mSharedPrefs.edit().putBoolean(PREF_MASTER_TOGGLE, enabled).apply();
if (!enabled) {
// Disable bypass immediately when master toggle is turned off
enableBypassCharge(false);
}
}
// Mode management methods
public int getBypassMode() {
return mSharedPrefs.getInt(PREF_BYPASS_MODE, MODE_MANUAL);
}
public void setBypassMode(int mode) {
mSharedPrefs.edit().putInt(PREF_BYPASS_MODE, mode).apply();
// Reset bypass state when changing modes
if (mode == MODE_MANUAL) {
setManualBypassState(false);
}
// Update bypass state based on new mode
updateBypassState();
}
// Battery target methods (for smart mode)
public int getBatteryTarget() {
return mSharedPrefs.getInt(PREF_BATTERY_TARGET, DEFAULT_BATTERY_TARGET);
}
public void setBatteryTarget(int target) {
mSharedPrefs.edit().putInt(PREF_BATTERY_TARGET, target).apply();
// Immediately update bypass state if we're in smart mode
if (getBypassMode() == MODE_SMART) {
updateBypassState();
}
}
// Manual bypass state methods
public boolean getManualBypassState() {
return mSharedPrefs.getBoolean(PREF_MANUAL_BYPASS_STATE, false);
}
public void setManualBypassState(boolean enabled) {
mSharedPrefs.edit().putBoolean(PREF_MANUAL_BYPASS_STATE, enabled).apply();
if (getBypassMode() == MODE_MANUAL) {
updateBypassState();
}
}
// Core bypass control methods
public boolean isBypassChargeEnabled() {
try {
String value = FileUtils.readOneLine(BYPASS_CHARGE_NODE);
return value != null && value.equals("1");
} catch (Exception e) {
Log.e(TAG, "Failed to read bypass charge status", e);
return false;
}
}
public void enableBypassCharge(boolean enable) {
try {
FileUtils.writeLine(BYPASS_CHARGE_NODE, enable ? "1" : "0");
Log.d(TAG, "Bypass charge " + (enable ? "enabled" : "disabled"));
} catch (Exception e) {
Log.e(TAG, "Failed to write bypass charge status", e);
}
}
// Support check methods
public boolean isNodeAccessible(String node) {
try {
FileUtils.readOneLine(node);
return true;
} catch (Exception e) {
Log.e(TAG, "Node " + node + " not accessible", e);
return false;
}
}
public boolean isBypassChargeSupported() {
return isNodeAccessible(BYPASS_CHARGE_NODE);
}
// Main logic for updating bypass state
public void updateBypassState() {
if (!isMasterToggleEnabled()) {
enableBypassCharge(false);
return;
}
int mode = getBypassMode();
boolean shouldBypass = false;
switch (mode) {
case MODE_MANUAL:
shouldBypass = getManualBypassState();
break;
case MODE_SMART:
shouldBypass = shouldBypassInSmartMode();
break;
}
enableBypassCharge(shouldBypass);
}
// Smart mode logic
private boolean shouldBypassInSmartMode() {
int currentBattery = getCurrentBatteryLevel();
int target = getBatteryTarget();
boolean currentlyBypassed = isBypassChargeEnabled();
if (currentBattery >= target && !currentlyBypassed) {
// Enable bypass when we reach target
return true;
} else if (currentBattery <= (target - BATTERY_HYSTERESIS) && currentlyBypassed) {
// Disable bypass when we drop below target minus hysteresis
return false;
}
// Keep current state if we're between thresholds
return currentlyBypassed;
}
// Battery level helper
public int getCurrentBatteryLevel() {
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = mContext.registerReceiver(null, ifilter);
if (batteryStatus != null) {
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
if (level != -1 && scale != -1) {
return (int) ((level / (float) scale) * 100);
}
}
return -1; // Unknown battery level
}
// Charging state helper
public boolean isCharging() {
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = mContext.registerReceiver(null, ifilter);
if (batteryStatus != null) {
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
}
return false;
}
// Utility methods for external components
public String getBypassModeString() {
switch (getBypassMode()) {
case MODE_MANUAL:
return "Manual";
case MODE_SMART:
return "Smart";
default:
return "Unknown";
}
}
public boolean canToggleManually() {
return isMasterToggleEnabled() && getBypassMode() == MODE_MANUAL;
}
}

View File

@@ -1,225 +0,0 @@
package org.lineageos.settings.charginginfo
import org.lineageos.settings.R
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.drawable.Icon
import android.os.BatteryManager
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import android.util.Log
import java.io.File
import java.util.Timer
import java.util.TimerTask
class ChargingInfoTileService : TileService() {
private var updateTimer: Timer? = null
private var batteryReceiver: BroadcastReceiver? = null
private var isCharging = false
companion object {
private const val TAG = "ChargingTileService"
private const val UPDATE_INTERVAL = 2000L // Update every 2 seconds
// Battery sysfs paths
private const val CURRENT_NOW_PATH = "/sys/class/power_supply/battery/current_now"
private const val VOLTAGE_NOW_PATH = "/sys/class/power_supply/battery/voltage_now"
private const val STATUS_PATH = "/sys/class/power_supply/battery/status"
}
override fun onStartListening() {
super.onStartListening()
Log.d(TAG, "Tile started listening")
// Register battery receiver
registerBatteryReceiver()
// Start periodic updates
startPeriodicUpdates()
// Initial update
updateTile()
}
override fun onStopListening() {
super.onStopListening()
Log.d(TAG, "Tile stopped listening")
// Stop updates
stopPeriodicUpdates()
// Unregister receiver
unregisterBatteryReceiver()
}
override fun onClick() {
super.onClick()
// Force update when clicked
updateTile()
}
private fun registerBatteryReceiver() {
if (batteryReceiver == null) {
batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
Intent.ACTION_BATTERY_CHANGED,
Intent.ACTION_POWER_CONNECTED,
Intent.ACTION_POWER_DISCONNECTED -> {
updateChargingStatus(intent)
updateTile()
}
}
}
}
val filter = IntentFilter().apply {
addAction(Intent.ACTION_BATTERY_CHANGED)
addAction(Intent.ACTION_POWER_CONNECTED)
addAction(Intent.ACTION_POWER_DISCONNECTED)
}
registerReceiver(batteryReceiver, filter)
}
}
private fun unregisterBatteryReceiver() {
batteryReceiver?.let {
try {
unregisterReceiver(it)
} catch (e: IllegalArgumentException) {
Log.w(TAG, "Receiver not registered")
}
batteryReceiver = null
}
}
private fun startPeriodicUpdates() {
stopPeriodicUpdates()
updateTimer = Timer().apply {
scheduleAtFixedRate(object : TimerTask() {
override fun run() {
if (isCharging) {
updateTile()
}
}
}, 0, UPDATE_INTERVAL)
}
}
private fun stopPeriodicUpdates() {
updateTimer?.cancel()
updateTimer = null
}
private fun updateChargingStatus(intent: Intent) {
val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
}
private fun updateTile() {
val tile = qsTile ?: return
try {
val chargingInfo = getChargingInfo()
tile.apply {
when {
chargingInfo.isCharging -> {
state = Tile.STATE_ACTIVE
label = "Charging"
subtitle = "${chargingInfo.power}W"
contentDescription = "Charging at ${chargingInfo.power}W (${chargingInfo.current}A, ${chargingInfo.voltage}V)"
icon = Icon.createWithResource(this@ChargingInfoTileService,
R.drawable.ic_charging_speed)
}
chargingInfo.isDischarging -> {
state = Tile.STATE_INACTIVE
label = "Discharging"
subtitle = "${chargingInfo.power}W"
contentDescription = "Discharging at ${chargingInfo.power}W"
icon = Icon.createWithResource(this@ChargingInfoTileService,
R.drawable.ic_battery_discharge)
}
else -> {
state = Tile.STATE_UNAVAILABLE
label = "Not Charging"
subtitle = "0W"
contentDescription = "Battery not charging or discharging"
icon = Icon.createWithResource(this@ChargingInfoTileService,
R.drawable.ic_battery_unknown)
}
}
}
tile.updateTile()
} catch (e: Exception) {
Log.e(TAG, "Error updating tile", e)
// Fallback tile state
tile.apply {
state = Tile.STATE_UNAVAILABLE
label = "Error"
subtitle = "N/A"
contentDescription = "Unable to read charging information"
icon = Icon.createWithResource(this@ChargingInfoTileService,
R.drawable.ic_error)
}
tile.updateTile()
}
}
private fun getChargingInfo(): ChargingInfo {
val currentNow = readSysfsValue(CURRENT_NOW_PATH)
val voltageNow = readSysfsValue(VOLTAGE_NOW_PATH)
val status = readSysfsString(STATUS_PATH)
// Convert from milliamps to amps and microvolts to volts
val currentA = currentNow / 1000.0 // mA → A
val voltageV = voltageNow / 1000000.0 // µV → V
// Calculate power in watts
val powerW = Math.abs(currentA * voltageV)
val isCharging = status.equals("Charging", ignoreCase = true) && currentNow > 0
val isDischarging = currentNow < 0
return ChargingInfo(
current = String.format("%.1f", Math.abs(currentA)),
voltage = String.format("%.1f", voltageV),
power = String.format("%.1f", powerW),
isCharging = isCharging,
isDischarging = isDischarging
)
}
private fun readSysfsValue(path: String): Long {
return try {
File(path).readText().trim().toLong()
} catch (e: Exception) {
Log.w(TAG, "Failed to read $path", e)
0L
}
}
private fun readSysfsString(path: String): String {
return try {
File(path).readText().trim()
} catch (e: Exception) {
Log.w(TAG, "Failed to read $path", e)
"Unknown"
}
}
data class ChargingInfo(
val current: String,
val voltage: String,
val power: String,
val isCharging: Boolean,
val isDischarging: Boolean
)
}

View File

@@ -1,96 +0,0 @@
package org.lineageos.settings.charge;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import androidx.preference.SeekBarPreference;
public class MinMaxSeekBarPreference extends SeekBarPreference {
private static final String TAG = "MinMaxSeekBarPreference";
private int mMinValue = 0;
private int mMaxValue = 100;
public MinMaxSeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
// Get min/max values from XML attributes
if (attrs != null) {
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attrName = attrs.getAttributeName(i);
if ("min".equals(attrName)) {
mMinValue = attrs.getAttributeIntValue(i, 0);
} else if ("max".equals(attrName)) {
mMaxValue = attrs.getAttributeIntValue(i, 100);
}
}
}
// Set the SeekBar to use full 0-100 range for UI, but map values internally
setMin(0);
setMax(100);
Log.d(TAG, "MinMaxSeekBarPreference initialized - Min: " + mMinValue + ", Max: " + mMaxValue);
}
@Override
protected void onSetInitialValue(Object defaultValue) {
int value = defaultValue == null ? 80 : (Integer) defaultValue;
// Ensure value is within bounds
value = Math.max(mMinValue, Math.min(mMaxValue, value));
// Convert the actual battery target value to slider position
int sliderPosition = valueToSliderPosition(value);
super.setValue(sliderPosition);
Log.i(TAG, "Battery target initial value set: " + value + "% (Slider position: " + sliderPosition + "%)");
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
int defaultValue = a.getInt(index, 80);
Log.d(TAG, "Getting default battery target value: " + defaultValue + "%");
return defaultValue;
}
@Override
public void setValue(int seekBarValue) {
// seekBarValue here is the slider position (0-100)
// Just store it as-is since the slider represents the UI position
super.setValue(seekBarValue);
// Calculate and log the actual mapped battery target
int mappedValue = sliderPositionToValue(seekBarValue);
Log.i(TAG, "Battery target changed - Slider: " + seekBarValue + "%, Actual target: " + mappedValue + "% (Range: " + mMinValue + "-" + mMaxValue + "%)");
}
// Convert slider position (0-100) to actual battery target value
private int sliderPositionToValue(int sliderPosition) {
return mMinValue + ((sliderPosition * (mMaxValue - mMinValue)) / 100);
}
// Convert actual battery target value to slider position (0-100)
private int valueToSliderPosition(int value) {
if (mMaxValue == mMinValue) return 0; // Avoid division by zero
return ((value - mMinValue) * 100) / (mMaxValue - mMinValue);
}
// Get the actual mapped battery target value
public int getBatteryTarget() {
int sliderValue = getValue();
return sliderPositionToValue(sliderValue);
}
// Set the battery target value (converts to appropriate slider position)
public void setBatteryTarget(int targetValue) {
targetValue = Math.max(mMinValue, Math.min(mMaxValue, targetValue));
int sliderPosition = valueToSliderPosition(targetValue);
setValue(sliderPosition);
}
// Calculate battery target from a given slider position (used during preference change)
public int calculateBatteryTargetFromSlider(int sliderPosition) {
return sliderPositionToValue(sliderPosition);
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
import java.util.List;
public class ForegroundAppDetector {
private static final String TAG = "ForegroundAppDetector";
public static String getForegroundPackageName(Context context) {
String pkg = tryGetRunningTasks(context);
if (pkg != null) {
return pkg;
}
pkg = tryReflectActivityTaskManager();
if (pkg != null) {
return pkg;
}
return "Unknown";
}
private static String tryGetRunningTasks(Context context) {
try {
if (context.checkSelfPermission("android.permission.GET_TASKS")
== PackageManager.PERMISSION_GRANTED) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
if (tasks != null && !tasks.isEmpty()) {
ActivityManager.RunningTaskInfo top = tasks.get(0);
if (top.topActivity != null) {
return top.topActivity.getPackageName();
}
}
} else {
Log.w(TAG, "GET_TASKS permission not granted to this system app?");
}
} catch (Exception e) {
Log.e(TAG, "tryGetRunningTasks error: ", e);
}
return null;
}
private static String tryReflectActivityTaskManager() {
try {
Class<?> atmClass = Class.forName("android.app.ActivityTaskManager");
Method getServiceMethod = atmClass.getDeclaredMethod("getService");
getServiceMethod.setAccessible(true);
Object atmService = getServiceMethod.invoke(null);
Method getTasksMethod = atmService.getClass().getMethod("getTasks", int.class);
@SuppressWarnings("unchecked")
List<?> taskList = (List<?>) getTasksMethod.invoke(atmService, 1);
if (taskList != null && !taskList.isEmpty()) {
Object firstTask = taskList.get(0);
Class<?> rtiClass = firstTask.getClass();
Method getTopActivityMethod = rtiClass.getDeclaredMethod("getTopActivity");
Object compName = getTopActivityMethod.invoke(firstTask);
if (compName != null) {
Method getPackageNameMethod = compName.getClass().getMethod("getPackageName");
String pkgName = (String) getPackageNameMethod.invoke(compName);
return pkgName;
}
}
} catch (Exception e) {
Log.e(TAG, "tryReflectActivityTaskManager error: ", e);
}
return null;
}
}

View File

@@ -1,774 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.GradientDrawable;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.R;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class GameBar {
private static GameBar sInstance;
public static synchronized GameBar getInstance(Context context) {
if (sInstance == null) {
sInstance = new GameBar(context.getApplicationContext());
}
return sInstance;
}
private static final String FPS_PATH = "/sys/class/drm/sde-crtc-0/measured_fps";
private static final String BATTERY_TEMP_PATH= "/sys/class/thermal/thermal_zone78/temp";
private static final String PREF_KEY_X = "game_bar_x";
private static final String PREF_KEY_Y = "game_bar_y";
private final Context mContext;
private final WindowManager mWindowManager;
private final Handler mHandler;
private View mOverlayView;
private LinearLayout mRootLayout;
private WindowManager.LayoutParams mLayoutParams;
private boolean mIsShowing = false;
private int mTextSizeSp = 16;
private int mBackgroundAlpha = 128;
private int mCornerRadius = 16;
private int mPaddingDp = 12;
private String mTitleColorHex = "#FFFFFF";
private String mValueColorHex = "#FFFFFF";
private String mOverlayFormat = "full";
private String mPosition = "top_left";
private String mSplitMode = "stacked";
private int mUpdateIntervalMs = 1000;
private boolean mDraggable = false;
private boolean mShowBatteryTemp = false;
private boolean mShowCpuUsage = false;
private boolean mShowCpuClock = false;
private boolean mShowCpuTemp = false;
private boolean mShowRam = false;
private boolean mShowFps = false;
private boolean mShowGpuUsage = false;
private boolean mShowGpuClock = false;
private boolean mShowGpuTemp = false;
private boolean mLongPressEnabled = false;
private long mLongPressThresholdMs = 1000;
private boolean mPressActive = false;
private float mDownX, mDownY;
private static final float TOUCH_SLOP = 20f;
private GestureDetector mGestureDetector;
private boolean mDoubleTapCaptureEnabled = false;
private boolean mSingleTapToggleEnabled = false;
private GradientDrawable mBgDrawable;
private int mItemSpacingDp = 8;
private final Runnable mLongPressRunnable = new Runnable() {
@Override
public void run() {
if (mPressActive) {
openOverlaySettings();
mPressActive = false;
}
}
};
private final Runnable mUpdateRunnable = new Runnable() {
@Override
public void run() {
if (mIsShowing) {
updateStats();
mHandler.postDelayed(this, mUpdateIntervalMs);
}
}
};
private GameBar(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mHandler = new Handler(Looper.getMainLooper());
mBgDrawable = new GradientDrawable();
applyBackgroundStyle();
mGestureDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mDoubleTapCaptureEnabled) {
if (GameDataExport.getInstance().isCapturing()) {
GameDataExport.getInstance().stopCapture();
Toast.makeText(mContext, "Capture Stopped", Toast.LENGTH_SHORT).show();
} else {
GameDataExport.getInstance().startCapture();
Toast.makeText(mContext, "Capture Started", Toast.LENGTH_SHORT).show();
}
return true;
}
return super.onDoubleTap(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mSingleTapToggleEnabled) {
mOverlayFormat = "full".equals(mOverlayFormat) ? "minimal" : "full";
PreferenceManager.getDefaultSharedPreferences(mContext)
.edit()
.putString("game_bar_format", mOverlayFormat)
.apply();
Toast.makeText(mContext, "Overlay Format: " + mOverlayFormat, Toast.LENGTH_SHORT).show();
updateStats();
return true;
}
return super.onSingleTapConfirmed(e);
}
});
}
public void applyPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mShowFps = prefs.getBoolean("game_bar_fps_enable", false);
mShowBatteryTemp = prefs.getBoolean("game_bar_temp_enable", false);
mShowCpuUsage = prefs.getBoolean("game_bar_cpu_usage_enable", false);
mShowCpuClock = prefs.getBoolean("game_bar_cpu_clock_enable", false);
mShowCpuTemp = prefs.getBoolean("game_bar_cpu_temp_enable", false);
mShowRam = prefs.getBoolean("game_bar_ram_enable", false);
mShowGpuUsage = prefs.getBoolean("game_bar_gpu_usage_enable", false);
mShowGpuClock = prefs.getBoolean("game_bar_gpu_clock_enable", false);
mShowGpuTemp = prefs.getBoolean("game_bar_gpu_temp_enable", false);
mDoubleTapCaptureEnabled = prefs.getBoolean("game_bar_doubletap_capture", false);
mSingleTapToggleEnabled = prefs.getBoolean("game_bar_single_tap_toggle", false);
updateSplitMode(prefs.getString("game_bar_split_mode", "stacked"));
updateTextSize(prefs.getInt("game_bar_text_size", 16));
updateBackgroundAlpha(prefs.getInt("game_bar_background_alpha", 128));
updateCornerRadius(prefs.getInt("game_bar_corner_radius", 16));
updatePadding(prefs.getInt("game_bar_padding", 12));
updateTitleColor(prefs.getString("game_bar_title_color", "#FFFFFF"));
updateValueColor(prefs.getString("game_bar_value_color", "#4CAF50"));
updateOverlayFormat(prefs.getString("game_bar_format", "full"));
updateUpdateInterval(prefs.getString("game_bar_update_interval", "1000"));
updatePosition(prefs.getString("game_bar_position", "top_left"));
int spacing = prefs.getInt("game_bar_item_spacing", 8);
updateItemSpacing(spacing);
mLongPressEnabled = prefs.getBoolean("game_bar_longpress_enable", false);
String lpTimeoutStr = prefs.getString("game_bar_longpress_timeout", "1000");
try {
long lpt = Long.parseLong(lpTimeoutStr);
setLongPressThresholdMs(lpt);
} catch (NumberFormatException ignored) {}
}
public void show() {
if (mIsShowing) return;
applyPreferences();
mLayoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
if ("draggable".equals(mPosition)) {
mDraggable = true;
loadSavedPosition(mLayoutParams);
if (mLayoutParams.x == 0 && mLayoutParams.y == 0) {
mLayoutParams.gravity = Gravity.TOP | Gravity.START;
mLayoutParams.x = 0;
mLayoutParams.y = 100;
}
} else {
mDraggable = false;
applyPosition(mLayoutParams, mPosition);
}
mOverlayView = new LinearLayout(mContext);
mOverlayView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
));
mRootLayout = (LinearLayout) mOverlayView;
applySplitMode();
applyBackgroundStyle();
applyPadding();
mOverlayView.setOnTouchListener((v, event) -> {
if (mGestureDetector != null && mGestureDetector.onTouchEvent(event)) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mDraggable) {
initialX = mLayoutParams.x;
initialY = mLayoutParams.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
}
if (mLongPressEnabled) {
mPressActive = true;
mDownX = event.getRawX();
mDownY = event.getRawY();
mHandler.postDelayed(mLongPressRunnable, mLongPressThresholdMs);
}
return true;
case MotionEvent.ACTION_MOVE:
if (mLongPressEnabled && mPressActive) {
float dx = Math.abs(event.getRawX() - mDownX);
float dy = Math.abs(event.getRawY() - mDownY);
if (dx > TOUCH_SLOP || dy > TOUCH_SLOP) {
mPressActive = false;
mHandler.removeCallbacks(mLongPressRunnable);
}
}
if (mDraggable) {
int deltaX = (int) (event.getRawX() - initialTouchX);
int deltaY = (int) (event.getRawY() - initialTouchY);
mLayoutParams.x = initialX + deltaX;
mLayoutParams.y = initialY + deltaY;
mWindowManager.updateViewLayout(mOverlayView, mLayoutParams);
}
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mLongPressEnabled && mPressActive) {
mPressActive = false;
mHandler.removeCallbacks(mLongPressRunnable);
}
if (mDraggable) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
prefs.edit()
.putInt(PREF_KEY_X, mLayoutParams.x)
.putInt(PREF_KEY_Y, mLayoutParams.y)
.apply();
}
return true;
}
return false;
});
mWindowManager.addView(mOverlayView, mLayoutParams);
mIsShowing = true;
startUpdates();
// Start the FPS meter if using the new API method.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
GameBarFpsMeter.getInstance(mContext).start();
}
}
private int initialX, initialY;
private float initialTouchX, initialTouchY;
public void hide() {
if (!mIsShowing) return;
mHandler.removeCallbacksAndMessages(null);
if (mOverlayView != null) {
mWindowManager.removeView(mOverlayView);
mOverlayView = null;
}
mIsShowing = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
GameBarFpsMeter.getInstance(mContext).stop();
}
}
private void updateStats() {
if (!mIsShowing || mRootLayout == null) return;
mRootLayout.removeAllViews();
List<View> statViews = new ArrayList<>();
// 1) FPS
float fpsVal = GameBarFpsMeter.getInstance(mContext).getFps();
String fpsStr = fpsVal >= 0 ? String.format(Locale.getDefault(), "%.0f", fpsVal) : "N/A";
if (mShowFps) {
statViews.add(createStatLine("FPS", fpsStr));
}
// 2) Battery temp
String batteryTempStr = "N/A";
if (mShowBatteryTemp) {
String tmp = readLine(BATTERY_TEMP_PATH);
if (tmp != null && !tmp.isEmpty()) {
try {
int raw = Integer.parseInt(tmp.trim());
float c = raw / 1000f;
batteryTempStr = String.format(Locale.getDefault(), "%.1f", c);
} catch (NumberFormatException ignored) {}
}
statViews.add(createStatLine("Temp", batteryTempStr + "°C"));
}
// 3) CPU usage
String cpuUsageStr = "N/A";
if (mShowCpuUsage) {
cpuUsageStr = GameBarCpuInfo.getCpuUsage();
String display = "N/A".equals(cpuUsageStr) ? "N/A" : cpuUsageStr + "%";
statViews.add(createStatLine("CPU", display));
}
// 4) CPU freq
if (mShowCpuClock) {
List<String> freqs = GameBarCpuInfo.getCpuFrequencies();
if (!freqs.isEmpty()) {
statViews.add(buildCpuFreqView(freqs));
}
}
// 5) CPU temp
String cpuTempStr = "N/A";
if (mShowCpuTemp) {
cpuTempStr = GameBarCpuInfo.getCpuTemp();
statViews.add(createStatLine("CPU Temp", "N/A".equals(cpuTempStr) ? "N/A" : cpuTempStr + "°C"));
}
// 6) RAM usage
String ramStr = "N/A";
if (mShowRam) {
ramStr = GameBarMemInfo.getRamUsage();
statViews.add(createStatLine("RAM", "N/A".equals(ramStr) ? "N/A" : ramStr + " MB"));
}
// 7) GPU usage
String gpuUsageStr = "N/A";
if (mShowGpuUsage) {
gpuUsageStr = GameBarGpuInfo.getGpuUsage();
statViews.add(createStatLine("GPU", "N/A".equals(gpuUsageStr) ? "N/A" : gpuUsageStr + "%"));
}
// 8) GPU clock
String gpuClockStr = "N/A";
if (mShowGpuClock) {
gpuClockStr = GameBarGpuInfo.getGpuClock();
statViews.add(createStatLine("GPU Freq", "N/A".equals(gpuClockStr) ? "N/A" : gpuClockStr + "MHz"));
}
// 9) GPU temp
String gpuTempStr = "N/A";
if (mShowGpuTemp) {
gpuTempStr = GameBarGpuInfo.getGpuTemp();
statViews.add(createStatLine("GPU Temp", "N/A".equals(gpuTempStr) ? "N/A" : gpuTempStr + "°C"));
}
if ("side_by_side".equals(mSplitMode)) {
mRootLayout.setOrientation(LinearLayout.HORIZONTAL);
if ("minimal".equals(mOverlayFormat)) {
for (int i = 0; i < statViews.size(); i++) {
mRootLayout.addView(statViews.get(i));
if (i < statViews.size() - 1) {
mRootLayout.addView(createDotView());
}
}
} else {
for (View view : statViews) {
mRootLayout.addView(view);
}
}
} else {
mRootLayout.setOrientation(LinearLayout.VERTICAL);
for (View view : statViews) {
mRootLayout.addView(view);
}
}
if (GameDataExport.getInstance().isCapturing()) {
String dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
String pkgName = ForegroundAppDetector.getForegroundPackageName(mContext);
GameDataExport.getInstance().addOverlayData(
dateTime,
pkgName,
fpsStr,
batteryTempStr,
cpuUsageStr,
cpuTempStr,
gpuUsageStr,
gpuClockStr,
gpuTempStr
);
}
if (mLayoutParams != null) {
mWindowManager.updateViewLayout(mOverlayView, mLayoutParams);
}
}
private View buildCpuFreqView(List<String> freqs) {
LinearLayout freqContainer = new LinearLayout(mContext);
freqContainer.setOrientation(LinearLayout.HORIZONTAL);
int spacingPx = dpToPx(mContext, mItemSpacingDp);
LinearLayout.LayoutParams outerLp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
outerLp.setMargins(spacingPx, spacingPx / 2, spacingPx, spacingPx / 2);
freqContainer.setLayoutParams(outerLp);
if ("full".equals(mOverlayFormat)) {
TextView labelTv = new TextView(mContext);
labelTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
labelTv.setTextColor(Color.parseColor(mTitleColorHex));
} catch (Exception e) {
labelTv.setTextColor(Color.WHITE);
}
labelTv.setText("CPU Freq ");
freqContainer.addView(labelTv);
}
LinearLayout verticalFreqs = new LinearLayout(mContext);
verticalFreqs.setOrientation(LinearLayout.VERTICAL);
for (String freqLine : freqs) {
LinearLayout lineLayout = new LinearLayout(mContext);
lineLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView freqTv = new TextView(mContext);
freqTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
freqTv.setTextColor(Color.parseColor(mValueColorHex));
} catch (Exception e) {
freqTv.setTextColor(Color.WHITE);
}
freqTv.setText(freqLine);
lineLayout.addView(freqTv);
LinearLayout.LayoutParams lineLp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
lineLp.setMargins(spacingPx, spacingPx / 4, spacingPx, spacingPx / 4);
lineLayout.setLayoutParams(lineLp);
verticalFreqs.addView(lineLayout);
}
freqContainer.addView(verticalFreqs);
return freqContainer;
}
private LinearLayout createStatLine(String title, String rawValue) {
LinearLayout lineLayout = new LinearLayout(mContext);
lineLayout.setOrientation(LinearLayout.HORIZONTAL);
if ("full".equals(mOverlayFormat)) {
TextView tvTitle = new TextView(mContext);
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
tvTitle.setTextColor(Color.parseColor(mTitleColorHex));
} catch (Exception e) {
tvTitle.setTextColor(Color.WHITE);
}
tvTitle.setText(title.isEmpty() ? "" : title + " ");
TextView tvValue = new TextView(mContext);
tvValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
tvValue.setTextColor(Color.parseColor(mValueColorHex));
} catch (Exception e) {
tvValue.setTextColor(Color.WHITE);
}
tvValue.setText(rawValue);
lineLayout.addView(tvTitle);
lineLayout.addView(tvValue);
} else {
TextView tvMinimal = new TextView(mContext);
tvMinimal.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
tvMinimal.setTextColor(Color.parseColor(mValueColorHex));
} catch (Exception e) {
tvMinimal.setTextColor(Color.WHITE);
}
tvMinimal.setText(rawValue);
lineLayout.addView(tvMinimal);
}
int spacingPx = dpToPx(mContext, mItemSpacingDp);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
lp.setMargins(spacingPx, spacingPx / 2, spacingPx, spacingPx / 2);
lineLayout.setLayoutParams(lp);
return lineLayout;
}
private View createDotView() {
TextView dotView = new TextView(mContext);
dotView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeSp);
try {
dotView.setTextColor(Color.parseColor(mValueColorHex));
} catch (Exception e) {
dotView.setTextColor(Color.WHITE);
}
dotView.setText(" . ");
return dotView;
}
public void setShowBatteryTemp(boolean show) { mShowBatteryTemp = show; }
public void setShowCpuUsage(boolean show) { mShowCpuUsage = show; }
public void setShowCpuClock(boolean show) { mShowCpuClock = show; }
public void setShowCpuTemp(boolean show) { mShowCpuTemp = show; }
public void setShowRam(boolean show) { mShowRam = show; }
public void setShowFps(boolean show) { mShowFps = show; }
public void setShowGpuUsage(boolean show) { mShowGpuUsage = show; }
public void setShowGpuClock(boolean show) { mShowGpuClock = show; }
public void setShowGpuTemp(boolean show) { mShowGpuTemp = show; }
public void updateTextSize(int sp) {
mTextSizeSp = sp;
}
public void updateCornerRadius(int radius) {
mCornerRadius = radius;
applyBackgroundStyle();
}
public void updateBackgroundAlpha(int alpha) {
mBackgroundAlpha = alpha;
applyBackgroundStyle();
}
public void updatePadding(int dp) {
mPaddingDp = dp;
applyPadding();
}
public void updateTitleColor(String hex) {
mTitleColorHex = hex;
}
public void updateValueColor(String hex) {
mValueColorHex = hex;
}
public void updateOverlayFormat(String format) {
mOverlayFormat = format;
if (mIsShowing) {
updateStats();
}
}
public void updateItemSpacing(int dp) {
mItemSpacingDp = dp;
if (mIsShowing) {
updateStats();
}
}
private void applyBackgroundStyle() {
int color = Color.argb(mBackgroundAlpha, 0, 0, 0);
mBgDrawable.setColor(color);
mBgDrawable.setCornerRadius(mCornerRadius);
if (mOverlayView != null) {
mOverlayView.setBackground(mBgDrawable);
}
}
private void applyPadding() {
if (mRootLayout != null) {
int px = dpToPx(mContext, mPaddingDp);
mRootLayout.setPadding(px, px, px, px);
}
}
public void updatePosition(String pos) {
mPosition = pos;
if (mIsShowing && mOverlayView != null && mLayoutParams != null) {
if ("draggable".equals(mPosition)) {
mDraggable = true;
loadSavedPosition(mLayoutParams);
if (mLayoutParams.x == 0 && mLayoutParams.y == 0) {
mLayoutParams.gravity = Gravity.TOP | Gravity.START;
mLayoutParams.x = 0;
mLayoutParams.y = 100;
}
} else {
mDraggable = false;
applyPosition(mLayoutParams, mPosition);
}
mWindowManager.updateViewLayout(mOverlayView, mLayoutParams);
}
}
public void updateSplitMode(String mode) {
mSplitMode = mode;
if (mIsShowing && mOverlayView != null) {
applySplitMode();
updateStats();
}
}
public void updateUpdateInterval(String intervalStr) {
try {
mUpdateIntervalMs = Integer.parseInt(intervalStr);
} catch (NumberFormatException e) {
mUpdateIntervalMs = 1000;
}
if (mIsShowing) {
startUpdates();
}
}
public void setLongPressEnabled(boolean enabled) {
mLongPressEnabled = enabled;
}
public void setLongPressThresholdMs(long ms) {
mLongPressThresholdMs = ms;
}
public void setDoubleTapCaptureEnabled(boolean enabled) {
mDoubleTapCaptureEnabled = enabled;
}
public void setSingleTapToggleEnabled(boolean enabled) {
mSingleTapToggleEnabled = enabled;
}
private void startUpdates() {
mHandler.removeCallbacksAndMessages(null);
mHandler.post(mUpdateRunnable);
}
private void applySplitMode() {
if (mRootLayout == null) return;
if ("side_by_side".equals(mSplitMode)) {
mRootLayout.setOrientation(LinearLayout.HORIZONTAL);
} else {
mRootLayout.setOrientation(LinearLayout.VERTICAL);
}
}
private void loadSavedPosition(WindowManager.LayoutParams lp) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
int savedX = prefs.getInt(PREF_KEY_X, Integer.MIN_VALUE);
int savedY = prefs.getInt(PREF_KEY_Y, Integer.MIN_VALUE);
if (savedX != Integer.MIN_VALUE && savedY != Integer.MIN_VALUE) {
lp.gravity = Gravity.TOP | Gravity.START;
lp.x = savedX;
lp.y = savedY;
}
}
private void applyPosition(WindowManager.LayoutParams lp, String pos) {
switch (pos) {
case "top_left":
lp.gravity = Gravity.TOP | Gravity.START;
lp.x = 0;
lp.y = 100;
break;
case "top_center":
lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
lp.y = 100;
break;
case "top_right":
lp.gravity = Gravity.TOP | Gravity.END;
lp.x = 0;
lp.y = 100;
break;
case "bottom_left":
lp.gravity = Gravity.BOTTOM | Gravity.START;
lp.x = 0;
lp.y = 100;
break;
case "bottom_center":
lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
lp.y = 100;
break;
case "bottom_right":
lp.gravity = Gravity.BOTTOM | Gravity.END;
lp.x = 0;
lp.y = 100;
break;
default:
lp.gravity = Gravity.TOP | Gravity.START;
lp.x = 0;
lp.y = 100;
break;
}
}
private String readLine(String path) {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return null;
}
}
private void openOverlaySettings() {
try {
Intent intent = new Intent(mContext, GameBarSettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} catch (Exception e) {
// Exception ignored
}
}
private static int dpToPx(Context context, int dp) {
float scale = context.getResources().getDisplayMetrics().density;
return Math.round(dp * scale);
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.os.Bundle;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
import org.lineageos.settings.R;
public class GameBarAppRemoverActivity extends CollapsingToolbarBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_bar_app_selector);
setTitle("Remove Auto-Enable Apps");
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, new GameBarAppRemoverFragment())
.commit();
}
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import org.lineageos.settings.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class GameBarAppRemoverFragment extends Fragment {
private RecyclerView recyclerView;
private GameBarAutoAppsAdapter adapter;
private PackageManager packageManager;
private List<ApplicationInfo> autoAppsList;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.game_bar_app_selector, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
recyclerView = view.findViewById(R.id.app_list);
packageManager = getContext().getPackageManager();
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
loadAutoApps();
}
private void loadAutoApps() {
Set<String> autoAppsSet = getSavedAutoApps();
autoAppsList = new ArrayList<>();
for (String pkg : autoAppsSet) {
try {
ApplicationInfo info = packageManager.getApplicationInfo(pkg, 0);
autoAppsList.add(info);
} catch (PackageManager.NameNotFoundException e) {
}
}
adapter = new GameBarAutoAppsAdapter(packageManager, autoAppsList, new GameBarAutoAppsAdapter.OnAppRemoveListener() {
@Override
public void onAppRemove(ApplicationInfo appInfo) {
removeAppFromAutoList(appInfo.packageName);
Toast.makeText(getContext(), appInfo.loadLabel(packageManager) + " removed.", Toast.LENGTH_SHORT).show();
autoAppsList.remove(appInfo);
adapter.notifyDataSetChanged();
}
});
recyclerView.setAdapter(adapter);
}
private Set<String> getSavedAutoApps() {
return PreferenceManager.getDefaultSharedPreferences(getContext())
.getStringSet(GameBarAppSelectorFragment.PREF_AUTO_APPS, new HashSet<>());
}
private void removeAppFromAutoList(String packageName) {
Set<String> autoApps = new HashSet<>(getSavedAutoApps());
autoApps.remove(packageName);
PreferenceManager.getDefaultSharedPreferences(getContext())
.edit().putStringSet(GameBarAppSelectorFragment.PREF_AUTO_APPS, autoApps).apply();
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.os.Bundle;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
import org.lineageos.settings.R;
public class GameBarAppSelectorActivity extends CollapsingToolbarBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_bar_app_selector);
setTitle("Select Apps for GameBar");
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, new GameBarAppSelectorFragment())
.commit();
}
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import org.lineageos.settings.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class GameBarAppSelectorFragment extends Fragment {
public static final String PREF_AUTO_APPS = "game_bar_auto_apps";
private RecyclerView recyclerView;
private GameBarAppsAdapter adapter;
private PackageManager packageManager;
private List<ApplicationInfo> allApps;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.game_bar_app_selector, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
recyclerView = view.findViewById(R.id.app_list);
packageManager = getContext().getPackageManager();
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
loadApps();
}
private void loadApps() {
allApps = new ArrayList<>();
List<ApplicationInfo> installedApps = packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
Set<String> autoApps = getSavedAutoApps();
for (ApplicationInfo appInfo : installedApps) {
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 &&
!appInfo.packageName.equals(getContext().getPackageName()) &&
!autoApps.contains(appInfo.packageName)) {
allApps.add(appInfo);
}
}
adapter = new GameBarAppsAdapter(packageManager, allApps, new GameBarAppsAdapter.OnAppClickListener() {
@Override
public void onAppClick(ApplicationInfo appInfo) {
addAppToAutoList(appInfo.packageName);
Toast.makeText(getContext(), appInfo.loadLabel(packageManager) + " added.", Toast.LENGTH_SHORT).show();
allApps.remove(appInfo);
adapter.notifyDataSetChanged();
}
});
recyclerView.setAdapter(adapter);
}
private Set<String> getSavedAutoApps() {
return PreferenceManager.getDefaultSharedPreferences(getContext())
.getStringSet(PREF_AUTO_APPS, new HashSet<>());
}
private void addAppToAutoList(String packageName) {
Set<String> autoApps = new HashSet<>(getSavedAutoApps());
autoApps.add(packageName);
PreferenceManager.getDefaultSharedPreferences(getContext())
.edit().putStringSet(PREF_AUTO_APPS, autoApps).apply();
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.lineageos.settings.R;
import java.util.List;
public class GameBarAppsAdapter extends RecyclerView.Adapter<GameBarAppsAdapter.ViewHolder> {
public interface OnAppClickListener {
void onAppClick(ApplicationInfo appInfo);
}
private PackageManager packageManager;
private List<ApplicationInfo> apps;
private OnAppClickListener listener;
public GameBarAppsAdapter(PackageManager packageManager, List<ApplicationInfo> apps, OnAppClickListener listener) {
this.packageManager = packageManager;
this.apps = apps;
this.listener = listener;
}
@NonNull
@Override
public GameBarAppsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.game_bar_app_selector_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull GameBarAppsAdapter.ViewHolder holder, int position) {
final ApplicationInfo appInfo = apps.get(position);
holder.appName.setText(appInfo.loadLabel(packageManager));
holder.appPackage.setText(appInfo.packageName);
holder.appIcon.setImageDrawable(appInfo.loadIcon(packageManager));
holder.itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onAppClick(appInfo);
}
});
}
@Override
public int getItemCount() {
return apps.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView appName;
TextView appPackage;
ImageView appIcon;
public ViewHolder(@NonNull View itemView) {
super(itemView);
appName = itemView.findViewById(R.id.app_name);
appPackage = itemView.findViewById(R.id.app_package);
appIcon = itemView.findViewById(R.id.app_icon);
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.lineageos.settings.R;
import java.util.List;
public class GameBarAutoAppsAdapter extends RecyclerView.Adapter<GameBarAutoAppsAdapter.ViewHolder> {
public interface OnAppRemoveListener {
void onAppRemove(ApplicationInfo appInfo);
}
private PackageManager packageManager;
private List<ApplicationInfo> apps;
private OnAppRemoveListener listener;
public GameBarAutoAppsAdapter(PackageManager packageManager, List<ApplicationInfo> apps, OnAppRemoveListener listener) {
this.packageManager = packageManager;
this.apps = apps;
this.listener = listener;
}
@NonNull
@Override
public GameBarAutoAppsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.game_bar_app_selector_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull GameBarAutoAppsAdapter.ViewHolder holder, int position) {
final ApplicationInfo appInfo = apps.get(position);
holder.appName.setText(appInfo.loadLabel(packageManager));
holder.appPackage.setText(appInfo.packageName);
holder.appIcon.setImageDrawable(appInfo.loadIcon(packageManager));
holder.itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onAppRemove(appInfo);
}
});
}
@Override
public int getItemCount() {
return apps.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView appName;
TextView appPackage;
ImageView appIcon;
public ViewHolder(@NonNull View itemView) {
super(itemView);
appName = itemView.findViewById(R.id.app_name);
appPackage = itemView.findViewById(R.id.app_package);
appIcon = itemView.findViewById(R.id.app_icon);
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.preference.PreferenceManager;
public class GameBarBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|| Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)) {
restoreOverlayState(context);
}
}
private void restoreOverlayState(Context context) {
var prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean mainEnabled = prefs.getBoolean("game_bar_enable", false);
boolean autoEnabled = prefs.getBoolean("game_bar_auto_enable", false);
if (mainEnabled) {
GameBar.getInstance(context).applyPreferences();
GameBar.getInstance(context).show();
}
if (autoEnabled) {
Intent monitorIntent = new Intent(context, GameBarMonitorService.class);
context.startService(monitorIntent);
}
}
}

View File

@@ -1,130 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GameBarCpuInfo {
private static long sPrevIdle = -1;
private static long sPrevTotal = -1;
private static final String CPU_TEMP_PATH = "/sys/class/thermal/thermal_zone19/temp";
public static String getCpuUsage() {
String line = readLine("/proc/stat");
if (line == null || !line.startsWith("cpu ")) return "N/A";
String[] parts = line.split("\\s+");
if (parts.length < 8) return "N/A";
try {
long user = Long.parseLong(parts[1]);
long nice = Long.parseLong(parts[2]);
long system = Long.parseLong(parts[3]);
long idle = Long.parseLong(parts[4]);
long iowait = Long.parseLong(parts[5]);
long irq = Long.parseLong(parts[6]);
long softirq = Long.parseLong(parts[7]);
long steal = parts.length > 8 ? Long.parseLong(parts[8]) : 0;
long total = user + nice + system + idle + iowait + irq + softirq + steal;
if (sPrevTotal != -1 && total != sPrevTotal) {
long diffTotal = total - sPrevTotal;
long diffIdle = idle - sPrevIdle;
long usage = 100 * (diffTotal - diffIdle) / diffTotal;
sPrevTotal = total;
sPrevIdle = idle;
return String.valueOf(usage);
} else {
sPrevTotal = total;
sPrevIdle = idle;
return "N/A";
}
} catch (NumberFormatException e) {
return "N/A";
}
}
public static List<String> getCpuFrequencies() {
List<String> result = new ArrayList<>();
String cpuDirPath = "/sys/devices/system/cpu/";
java.io.File cpuDir = new java.io.File(cpuDirPath);
java.io.File[] files = cpuDir.listFiles((dir, name) -> name.matches("cpu\\d+"));
if (files == null || files.length == 0) {
return result;
}
List<java.io.File> cpuFolders = new ArrayList<>();
Collections.addAll(cpuFolders, files);
cpuFolders.sort(Comparator.comparingInt(GameBarCpuInfo::extractCpuNumber));
for (java.io.File cpu : cpuFolders) {
String freqPath = cpu.getAbsolutePath() + "/cpufreq/scaling_cur_freq";
String freqStr = readLine(freqPath);
if (freqStr != null && !freqStr.isEmpty()) {
try {
int khz = Integer.parseInt(freqStr.trim());
int mhz = khz / 1000;
result.add(cpu.getName() + ": " + mhz + " MHz");
} catch (NumberFormatException e) {
result.add(cpu.getName() + ": N/A");
}
} else {
result.add(cpu.getName() + ": offline or frequency not available");
}
}
return result;
}
public static String getCpuTemp() {
String line = readLine(CPU_TEMP_PATH);
if (line == null) return "N/A";
line = line.trim();
try {
float raw = Float.parseFloat(line);
float c = raw / 1000f;
return String.format("%.1f", c);
} catch (NumberFormatException e) {
return "N/A";
}
}
private static int extractCpuNumber(java.io.File cpuFolder) {
String name = cpuFolder.getName().replace("cpu", "");
try {
return Integer.parseInt(name);
} catch (NumberFormatException e) {
return -1;
}
}
private static String readLine(String path) {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return null;
}
}
}

View File

@@ -1,187 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.view.WindowManager;
import android.window.TaskFpsCallback;
import androidx.preference.PreferenceManager;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class GameBarFpsMeter {
private static final float TOLERANCE = 0.1f;
private static final long STALENESS_THRESHOLD_MS = 2000;
private static final long TASK_CHECK_INTERVAL_MS = 1000;
private static GameBarFpsMeter sInstance;
private final Context mContext;
private final WindowManager mWindowManager;
private final SharedPreferences mPrefs;
private float mCurrentFps = 0f;
private TaskFpsCallback mTaskFpsCallback;
private boolean mCallbackRegistered = false;
private int mCurrentTaskId = -1;
private long mLastFpsUpdateTime = System.currentTimeMillis();
private final android.os.Handler mHandler = new android.os.Handler();
public static synchronized GameBarFpsMeter getInstance(Context context) {
if (sInstance == null) {
sInstance = new GameBarFpsMeter(context.getApplicationContext());
}
return sInstance;
}
private GameBarFpsMeter(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
mTaskFpsCallback = new TaskFpsCallback() {
@Override
public void onFpsReported(float fps) {
if (fps > 0) {
mCurrentFps = fps;
mLastFpsUpdateTime = System.currentTimeMillis();
}
}
};
}
}
public void start() {
String method = mPrefs.getString("game_bar_fps_method", "new");
if (!"new".equals(method)) return;
stop();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
int taskId = getFocusedTaskId();
if (taskId <= 0) {
return;
}
mCurrentTaskId = taskId;
try {
mWindowManager.registerTaskFpsCallback(mCurrentTaskId, Runnable::run, mTaskFpsCallback);
mCallbackRegistered = true;
} catch (Exception e) {
}
mLastFpsUpdateTime = System.currentTimeMillis();
mHandler.postDelayed(mTaskCheckRunnable, TASK_CHECK_INTERVAL_MS);
}
}
public void stop() {
String method = mPrefs.getString("game_bar_fps_method", "new");
if ("new".equals(method) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (mCallbackRegistered) {
try {
mWindowManager.unregisterTaskFpsCallback(mTaskFpsCallback);
} catch (Exception e) {
}
mCallbackRegistered = false;
}
mHandler.removeCallbacks(mTaskCheckRunnable);
}
}
public float getFps() {
String method = mPrefs.getString("game_bar_fps_method", "new");
if ("legacy".equals(method)) {
return readLegacyFps();
} else {
return mCurrentFps;
}
}
private float readLegacyFps() {
try (BufferedReader br = new BufferedReader(new FileReader("/sys/class/drm/sde-crtc-0/measured_fps"))) {
String line = br.readLine();
if (line != null && line.startsWith("fps:")) {
String[] parts = line.split("\\s+");
if (parts.length >= 2) {
return Float.parseFloat(parts[1].trim());
}
}
} catch (IOException | NumberFormatException e) {
}
return -1f;
}
private final Runnable mTaskCheckRunnable = new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
int newTaskId = getFocusedTaskId();
if (newTaskId > 0 && newTaskId != mCurrentTaskId) {
reinitCallback();
} else {
long now = System.currentTimeMillis();
if (now - mLastFpsUpdateTime > STALENESS_THRESHOLD_MS) {
reinitCallback();
}
}
mHandler.postDelayed(this, TASK_CHECK_INTERVAL_MS);
}
}
};
private int getFocusedTaskId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return -1;
}
try {
Class<?> atmClass = Class.forName("android.app.ActivityTaskManager");
Method getServiceMethod = atmClass.getDeclaredMethod("getService");
Object atmService = getServiceMethod.invoke(null);
Method getFocusedRootTaskInfoMethod = atmService.getClass().getMethod("getFocusedRootTaskInfo");
Object taskInfo = getFocusedRootTaskInfoMethod.invoke(atmService);
if (taskInfo != null) {
try {
Field taskIdField = taskInfo.getClass().getField("taskId");
return taskIdField.getInt(taskInfo);
} catch (NoSuchFieldException nsfe) {
try {
Field taskIdField = taskInfo.getClass().getField("mTaskId");
return taskIdField.getInt(taskInfo);
} catch (NoSuchFieldException nsfe2) {
}
}
}
} catch (Exception e) {
}
return -1;
}
private void reinitCallback() {
stop();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
start();
}
}, 500);
}
}

View File

@@ -1,394 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SeekBarPreference;
import androidx.preference.SwitchPreference;
import androidx.preference.SwitchPreferenceCompat;
import com.android.settingslib.widget.MainSwitchPreference;
import org.lineageos.settings.R;
public class GameBarFragment extends PreferenceFragmentCompat {
private GameBar mGameBar;
private MainSwitchPreference mMasterSwitch;
private SwitchPreferenceCompat mAutoEnableSwitch;
private SwitchPreferenceCompat mFpsSwitch;
private SwitchPreferenceCompat mBatteryTempSwitch;
private SwitchPreferenceCompat mCpuUsageSwitch;
private SwitchPreferenceCompat mCpuClockSwitch;
private SwitchPreferenceCompat mCpuTempSwitch;
private SwitchPreferenceCompat mRamSwitch;
private SwitchPreferenceCompat mGpuUsageSwitch;
private SwitchPreferenceCompat mGpuClockSwitch;
private SwitchPreferenceCompat mGpuTempSwitch;
private Preference mCaptureStartPref;
private Preference mCaptureStopPref;
private Preference mCaptureExportPref;
private SwitchPreferenceCompat mDoubleTapCapturePref;
private SwitchPreferenceCompat mSingleTapTogglePref;
private SwitchPreferenceCompat mLongPressEnablePref;
private ListPreference mLongPressTimeoutPref;
private SeekBarPreference mTextSizePref;
private SeekBarPreference mBgAlphaPref;
private SeekBarPreference mCornerRadiusPref;
private SeekBarPreference mPaddingPref;
private SeekBarPreference mItemSpacingPref;
private ListPreference mUpdateIntervalPref;
private ListPreference mTextColorPref;
private ListPreference mTitleColorPref;
private ListPreference mValueColorPref;
private ListPreference mPositionPref;
private ListPreference mSplitModePref;
private ListPreference mOverlayFormatPref;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.game_bar_preferences, rootKey);
mGameBar = GameBar.getInstance(getContext());
// Initialize all preferences.
mMasterSwitch = findPreference("game_bar_enable");
mAutoEnableSwitch = findPreference("game_bar_auto_enable");
mFpsSwitch = findPreference("game_bar_fps_enable");
mBatteryTempSwitch = findPreference("game_bar_temp_enable");
mCpuUsageSwitch = findPreference("game_bar_cpu_usage_enable");
mCpuClockSwitch = findPreference("game_bar_cpu_clock_enable");
mCpuTempSwitch = findPreference("game_bar_cpu_temp_enable");
mRamSwitch = findPreference("game_bar_ram_enable");
mGpuUsageSwitch = findPreference("game_bar_gpu_usage_enable");
mGpuClockSwitch = findPreference("game_bar_gpu_clock_enable");
mGpuTempSwitch = findPreference("game_bar_gpu_temp_enable");
mCaptureStartPref = findPreference("game_bar_capture_start");
mCaptureStopPref = findPreference("game_bar_capture_stop");
mCaptureExportPref = findPreference("game_bar_capture_export");
mDoubleTapCapturePref = findPreference("game_bar_doubletap_capture");
mSingleTapTogglePref = findPreference("game_bar_single_tap_toggle");
mLongPressEnablePref = findPreference("game_bar_longpress_enable");
mLongPressTimeoutPref = findPreference("game_bar_longpress_timeout");
mTextSizePref = findPreference("game_bar_text_size");
mBgAlphaPref = findPreference("game_bar_background_alpha");
mCornerRadiusPref = findPreference("game_bar_corner_radius");
mPaddingPref = findPreference("game_bar_padding");
mItemSpacingPref = findPreference("game_bar_item_spacing");
mUpdateIntervalPref = findPreference("game_bar_update_interval");
mTextColorPref = findPreference("game_bar_text_color");
mTitleColorPref = findPreference("game_bar_title_color");
mValueColorPref = findPreference("game_bar_value_color");
mPositionPref = findPreference("game_bar_position");
mSplitModePref = findPreference("game_bar_split_mode");
mOverlayFormatPref = findPreference("game_bar_format");
Preference appSelectorPref = findPreference("game_bar_app_selector");
if (appSelectorPref != null) {
appSelectorPref.setOnPreferenceClickListener(pref -> {
Intent intent = new Intent(getContext(), GameBarAppSelectorActivity.class);
startActivity(intent);
return true;
});
}
Preference appRemoverPref = findPreference("game_bar_app_remover");
if (appRemoverPref != null) {
appRemoverPref.setOnPreferenceClickListener(pref -> {
Intent intent = new Intent(getContext(), GameBarAppRemoverActivity.class);
startActivity(intent);
return true;
});
}
if (mMasterSwitch != null) {
mMasterSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
boolean enabled = (boolean) newValue;
if (enabled) {
if (Settings.canDrawOverlays(getContext())) {
mGameBar.applyPreferences();
mGameBar.show();
getContext().startService(new Intent(getContext(), GameBarMonitorService.class));
} else {
Toast.makeText(getContext(), R.string.overlay_permission_required, Toast.LENGTH_SHORT).show();
return false;
}
} else {
mGameBar.hide();
if (mAutoEnableSwitch == null || !mAutoEnableSwitch.isChecked()) {
getContext().stopService(new Intent(getContext(), GameBarMonitorService.class));
}
}
return true;
});
}
if (mAutoEnableSwitch != null) {
mAutoEnableSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
boolean autoEnabled = (boolean) newValue;
if (autoEnabled) {
getContext().startService(new Intent(getContext(), GameBarMonitorService.class));
} else {
if (mMasterSwitch == null || !mMasterSwitch.isChecked()) {
getContext().stopService(new Intent(getContext(), GameBarMonitorService.class));
}
}
return true;
});
}
if (mFpsSwitch != null) {
mFpsSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowFps((boolean) newValue);
return true;
});
}
if (mBatteryTempSwitch != null) {
mBatteryTempSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowBatteryTemp((boolean) newValue);
return true;
});
}
if (mCpuUsageSwitch != null) {
mCpuUsageSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowCpuUsage((boolean) newValue);
return true;
});
}
if (mCpuClockSwitch != null) {
mCpuClockSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowCpuClock((boolean) newValue);
return true;
});
}
if (mCpuTempSwitch != null) {
mCpuTempSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowCpuTemp((boolean) newValue);
return true;
});
}
if (mRamSwitch != null) {
mRamSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowRam((boolean) newValue);
return true;
});
}
if (mGpuUsageSwitch != null) {
mGpuUsageSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowGpuUsage((boolean) newValue);
return true;
});
}
if (mGpuClockSwitch != null) {
mGpuClockSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowGpuClock((boolean) newValue);
return true;
});
}
if (mGpuTempSwitch != null) {
mGpuTempSwitch.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setShowGpuTemp((boolean) newValue);
return true;
});
}
if (mCaptureStartPref != null) {
mCaptureStartPref.setOnPreferenceClickListener(pref -> {
GameDataExport.getInstance().startCapture();
Toast.makeText(getContext(), "Started logging Data", Toast.LENGTH_SHORT).show();
return true;
});
}
if (mCaptureStopPref != null) {
mCaptureStopPref.setOnPreferenceClickListener(pref -> {
GameDataExport.getInstance().stopCapture();
Toast.makeText(getContext(), "Stopped logging Data", Toast.LENGTH_SHORT).show();
return true;
});
}
if (mCaptureExportPref != null) {
mCaptureExportPref.setOnPreferenceClickListener(pref -> {
GameDataExport.getInstance().exportDataToCsv();
Toast.makeText(getContext(), "Exported log data to file", Toast.LENGTH_SHORT).show();
return true;
});
}
if (mDoubleTapCapturePref != null) {
mDoubleTapCapturePref.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setDoubleTapCaptureEnabled((boolean) newValue);
return true;
});
}
if (mSingleTapTogglePref != null) {
mSingleTapTogglePref.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setSingleTapToggleEnabled((boolean) newValue);
return true;
});
}
if (mLongPressEnablePref != null) {
mLongPressEnablePref.setOnPreferenceChangeListener((pref, newValue) -> {
mGameBar.setLongPressEnabled((boolean) newValue);
return true;
});
}
if (mLongPressTimeoutPref != null) {
mLongPressTimeoutPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
long ms = Long.parseLong((String) newValue);
mGameBar.setLongPressThresholdMs(ms);
}
return true;
});
}
if (mTextSizePref != null) {
mTextSizePref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof Integer) {
mGameBar.updateTextSize((Integer) newValue);
}
return true;
});
}
if (mBgAlphaPref != null) {
mBgAlphaPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof Integer) {
mGameBar.updateBackgroundAlpha((Integer) newValue);
}
return true;
});
}
if (mCornerRadiusPref != null) {
mCornerRadiusPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof Integer) {
mGameBar.updateCornerRadius((Integer) newValue);
}
return true;
});
}
if (mPaddingPref != null) {
mPaddingPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof Integer) {
mGameBar.updatePadding((Integer) newValue);
}
return true;
});
}
if (mItemSpacingPref != null) {
mItemSpacingPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof Integer) {
mGameBar.updateItemSpacing((Integer) newValue);
}
return true;
});
}
if (mUpdateIntervalPref != null) {
mUpdateIntervalPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updateUpdateInterval((String) newValue);
}
return true;
});
}
if (mTextColorPref != null) {
mTextColorPref.setOnPreferenceChangeListener((pref, newValue) -> true);
}
if (mTitleColorPref != null) {
mTitleColorPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updateTitleColor((String) newValue);
}
return true;
});
}
if (mValueColorPref != null) {
mValueColorPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updateValueColor((String) newValue);
}
return true;
});
}
if (mPositionPref != null) {
mPositionPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updatePosition((String) newValue);
}
return true;
});
}
if (mSplitModePref != null) {
mSplitModePref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updateSplitMode((String) newValue);
}
return true;
});
}
if (mOverlayFormatPref != null) {
mOverlayFormatPref.setOnPreferenceChangeListener((pref, newValue) -> {
if (newValue instanceof String) {
mGameBar.updateOverlayFormat((String) newValue);
}
return true;
});
}
}
@Override
public void onResume() {
super.onResume();
if (!hasUsageStatsPermission(requireContext())) {
requestUsageStatsPermission();
}
Context context = getContext();
if (context != null) {
if ((mMasterSwitch != null && mMasterSwitch.isChecked()) ||
(mAutoEnableSwitch != null && mAutoEnableSwitch.isChecked())) {
context.startService(new Intent(context, GameBarMonitorService.class));
} else {
context.stopService(new Intent(context, GameBarMonitorService.class));
}
}
}
private boolean hasUsageStatsPermission(Context context) {
android.app.AppOpsManager appOps = (android.app.AppOpsManager)
context.getSystemService(Context.APP_OPS_SERVICE);
if (appOps == null) return false;
int mode = appOps.checkOpNoThrow(
android.app.AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(),
context.getPackageName()
);
return (mode == android.app.AppOpsManager.MODE_ALLOWED);
}
private void requestUsageStatsPermission() {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class GameBarGpuInfo {
private static final String GPU_USAGE_PATH = "/sys/class/kgsl/kgsl-3d0/gpu_busy_percentage";
private static final String GPU_CLOCK_PATH = "/sys/class/kgsl/kgsl-3d0/gpuclk";
private static final String GPU_TEMP_PATH = "/sys/class/kgsl/kgsl-3d0/temp";
public static String getGpuUsage() {
String line = readLine(GPU_USAGE_PATH);
if (line == null) {
return "N/A";
}
line = line.replace("%", "").trim();
try {
int val = Integer.parseInt(line);
return String.valueOf(val);
} catch (NumberFormatException e) {
return "N/A";
}
}
public static String getGpuClock() {
String line = readLine(GPU_CLOCK_PATH);
if (line == null) {
return "N/A";
}
line = line.trim();
try {
long hz = Long.parseLong(line);
long mhz = hz / 1_000_000;
return String.valueOf(mhz);
} catch (NumberFormatException e) {
return "N/A";
}
}
public static String getGpuTemp() {
String line = readLine(GPU_TEMP_PATH);
if (line == null) {
return "N/A";
}
line = line.trim();
try {
float raw = Float.parseFloat(line);
float c = raw / 1000f;
return String.format("%.1f", c);
} catch (NumberFormatException e) {
return "N/A";
}
}
private static String readLine(String path) {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return null;
}
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class GameBarMemInfo {
public static String getRamUsage() {
long memTotal = 0;
long memAvailable = 0;
try (BufferedReader br = new BufferedReader(new FileReader("/proc/meminfo"))) {
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("MemTotal:")) {
memTotal = parseMemValue(line);
} else if (line.startsWith("MemAvailable:")) {
memAvailable = parseMemValue(line);
}
if (memTotal > 0 && memAvailable > 0) {
break;
}
}
} catch (IOException e) {
return "N/A";
}
if (memTotal == 0) {
return "N/A";
}
long usedKb = (memTotal - memAvailable);
long usedMb = usedKb / 1024;
return String.valueOf(usedMb);
}
private static long parseMemValue(String line) {
String[] parts = line.split("\\s+");
if (parts.length < 3) {
return 0;
}
try {
return Long.parseLong(parts[1]);
} catch (NumberFormatException e) {
return 0;
}
}
}

View File

@@ -1,82 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import androidx.preference.PreferenceManager;
import java.util.HashSet;
import java.util.Set;
public class GameBarMonitorService extends Service {
private Handler mHandler;
private Runnable mMonitorRunnable;
private static final long MONITOR_INTERVAL = 2000; // 2 seconds
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
mMonitorRunnable = new Runnable() {
@Override
public void run() {
monitorForegroundApp();
mHandler.postDelayed(this, MONITOR_INTERVAL);
}
};
mHandler.post(mMonitorRunnable);
}
private void monitorForegroundApp() {
var prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean masterEnabled = prefs.getBoolean("game_bar_enable", false);
if (masterEnabled) {
GameBar.getInstance(this).applyPreferences();
GameBar.getInstance(this).show();
return;
}
boolean autoEnabled = prefs.getBoolean("game_bar_auto_enable", false);
if (!autoEnabled) {
GameBar.getInstance(this).hide();
return;
}
String foreground = ForegroundAppDetector.getForegroundPackageName(this);
Set<String> autoApps = prefs.getStringSet(GameBarAppSelectorFragment.PREF_AUTO_APPS, new HashSet<>());
if (autoApps.contains(foreground)) {
GameBar.getInstance(this).applyPreferences();
GameBar.getInstance(this).show();
} else {
GameBar.getInstance(this).hide();
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mMonitorRunnable);
}
}

View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
import org.lineageos.settings.R;
public class GameBarSettingsActivity extends CollapsingToolbarBaseActivity {
private static final int OVERLAY_PERMISSION_REQUEST_CODE = 1234;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_bar);
setTitle(getString(R.string.game_bar_title));
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQUEST_CODE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
Toast.makeText(this, R.string.overlay_permission_granted, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, R.string.overlay_permission_denied, Toast.LENGTH_SHORT).show();
}
}
}
}

View File

@@ -1,72 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.R;
public class GameBarTileService extends TileService {
private GameBar mGameBar;
@Override
public void onCreate() {
super.onCreate();
mGameBar = GameBar.getInstance(this);
}
@Override
public void onStartListening() {
boolean enabled = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("game_bar_enable", false);
updateTileState(enabled);
}
@Override
public void onClick() {
boolean currentlyEnabled = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("game_bar_enable", false);
boolean newState = !currentlyEnabled;
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putBoolean("game_bar_enable", newState)
.commit();
updateTileState(newState);
if (newState) {
mGameBar.applyPreferences();
mGameBar.show();
} else {
mGameBar.hide();
}
}
private void updateTileState(boolean enabled) {
Tile tile = getQsTile();
if (tile == null) return;
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setLabel(getString(R.string.game_bar_tile_label));
tile.setContentDescription(getString(R.string.game_bar_tile_description));
tile.updateTile();
}
}

View File

@@ -1,132 +0,0 @@
/*
* Copyright (C) 2025 kenway214
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.gamebar;
import android.os.Environment;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class GameDataExport {
private static GameDataExport sInstance;
public static synchronized GameDataExport getInstance() {
if (sInstance == null) {
sInstance = new GameDataExport();
}
return sInstance;
}
private boolean mCapturing = false;
private final List<String[]> mStatsRows = new ArrayList<>();
private static final String[] CSV_HEADER = {
"DateTime",
"PackageName",
"FPS",
"Battery_Temp",
"CPU_Usage",
"CPU_Temp",
"GPU_Usage",
"GPU_Clock",
"GPU_Temp"
};
private GameDataExport() {
}
public void startCapture() {
mCapturing = true;
mStatsRows.clear();
mStatsRows.add(CSV_HEADER);
}
public void stopCapture() {
mCapturing = false;
}
public boolean isCapturing() {
return mCapturing;
}
public void addOverlayData(String dateTime,
String packageName,
String fps,
String batteryTemp,
String cpuUsage,
String cpuTemp,
String gpuUsage,
String gpuClock,
String gpuTemp) {
if (!mCapturing) return;
String[] row = {
dateTime,
packageName,
fps,
batteryTemp,
cpuUsage,
cpuTemp,
gpuUsage,
gpuClock,
gpuTemp
};
mStatsRows.add(row);
}
public void exportDataToCsv() {
if (mStatsRows.size() <= 1) {
return;
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File outFile = new File(Environment.getExternalStorageDirectory(), "GameBar_log_" + timeStamp + ".csv");
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(outFile, true));
for (String[] row : mStatsRows) {
bw.write(toCsvLine(row));
bw.newLine();
}
bw.flush();
} catch (IOException ignored) {
} finally {
if (bw != null) {
try { bw.close(); } catch (IOException ignored) {}
}
}
}
private String toCsvLine(String[] columns) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
sb.append(columns[i]);
if (i < columns.length - 1) {
sb.append(",");
}
}
return sb.toString();
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.utils;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
public class ComponentUtils {
/**
* Enables or disables a specified Android component dynamically at runtime.
*
* @param context The context from which the component will be enabled or disabled.
* @param componentClass The class of the component to be enabled or disabled.
* @param enable If true, the component will be enabled; if false, it will be disabled.
*/
public static void toggleComponent(Context context, Class<?> componentClass, boolean enable) {
ComponentName componentName = new ComponentName(context, componentClass);
PackageManager packageManager = context.getPackageManager();
int currentState = packageManager.getComponentEnabledSetting(componentName);
int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
if (currentState != newState) {
packageManager.setComponentEnabledSetting(
componentName,
newState,
PackageManager.DONT_KILL_APP
);
}
}
}

View File

@@ -1,222 +0,0 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* 2025 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.utils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public final class FileUtils {
private static final String TAG = "FileUtils";
private FileUtils() {
// This class is not supposed to be instantiated
}
/**
* Reads the first line of text from the given file.
* Reference {@link BufferedReader#readLine()} for clarification on what a line is
*
* @return the read line contents, or null on failure
*/
public static String readOneLine(String fileName) {
String line = null;
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName), 512);
line = reader.readLine();
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for reading", e);
} catch (IOException e) {
Log.e(TAG, "Could not read from file " + fileName, e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return line;
}
/**
* Writes the given value into the given file
*
* @return true on success, false on failure
*/
public static boolean writeLine(String fileName, String value) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(fileName));
writer.write(value);
writer.flush();
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for writing", e);
return false;
} catch (IOException e) {
Log.e(TAG, "Could not write to file " + fileName, e);
return false;
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return true;
}
/**
* Checks whether the given file exists
*
* @return true if exists, false if not
*/
public static boolean fileExists(String fileName) {
final File file = new File(fileName);
return file.exists();
}
/**
* Checks whether the given file is readable
*
* @return true if readable, false if not
*/
public static boolean isFileReadable(String fileName) {
final File file = new File(fileName);
return file.exists() && file.canRead();
}
/**
* Checks whether the given file is writable
*
* @return true if writable, false if not
*/
public static boolean isFileWritable(String fileName) {
final File file = new File(fileName);
return file.exists() && file.canWrite();
}
/**
* Deletes an existing file
*
* @return true if the delete was successful, false if not
*/
public static boolean delete(String fileName) {
final File file = new File(fileName);
boolean ok = false;
try {
ok = file.delete();
} catch (SecurityException e) {
Log.w(TAG, "SecurityException trying to delete " + fileName, e);
}
return ok;
}
/**
* Renames an existing file
*
* @return true if the rename was successful, false if not
*/
public static boolean rename(String srcPath, String dstPath) {
final File srcFile = new File(srcPath);
final File dstFile = new File(dstPath);
boolean ok = false;
try {
ok = srcFile.renameTo(dstFile);
} catch (SecurityException e) {
Log.w(TAG, "SecurityException trying to rename " + srcPath + " to " + dstPath, e);
} catch (NullPointerException e) {
Log.e(TAG, "NullPointerException trying to rename " + srcPath + " to " + dstPath, e);
}
return ok;
}
/**
* Writes the given value into the given file.
* @return true on success, false on failure
*/
public static boolean writeValue(String fileName, String value) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(fileName));
writer.write(value);
writer.flush();
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for writing", e);
return false;
} catch (IOException e) {
Log.e(TAG, "Could not write to file " + fileName, e);
return false;
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return true;
}
/**
* Reads the value from the given file.
* @return the value read from the file, or the default value if an error occurs
*/
public static String getFileValue(String fileName, String defaultValue) {
String value = defaultValue;
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName), 512);
value = reader.readLine();
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for reading", e);
} catch (IOException e) {
Log.e(TAG, "Could not read from file " + fileName, e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return value;
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.utils;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.widget.Toast;
import org.lineageos.settings.R;
public class TileUtils {
public static void requestAddTileService(Context context, Class<?> tileServiceClass, int labelResId, int iconResId) {
ComponentName componentName = new ComponentName(context, tileServiceClass);
String label = context.getString(labelResId);
Icon icon = Icon.createWithResource(context, iconResId);
StatusBarManager sbm = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
if (sbm != null) {
sbm.requestAddTileService(
componentName,
label,
icon,
context.getMainExecutor(),
result -> handleResult(context, result)
);
}
}
private static void handleResult(Context context, Integer result) {
if (result == null)
return;
switch (result) {
case StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ADDED:
Toast.makeText(context, R.string.tile_added, Toast.LENGTH_SHORT).show();
break;
case StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED:
Toast.makeText(context, R.string.tile_not_added, Toast.LENGTH_SHORT).show();
break;
case StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED:
Toast.makeText(context, R.string.tile_already_added, Toast.LENGTH_SHORT).show();
break;
}
}
}

View File

@@ -19,6 +19,22 @@ vendor.display.disable_metadata_dynamic_fps=1
# LMKD
ro.config.low_ram=false
ro.lmk.log_stats=false
ro.lmk.kill_heaviest_task=true
ro.lmk.swap_free_low_percentage=100
# LMK tuning
ro.lmk.filecache_min_kb=153600
ro.lmk.stall_limit_critical=40
ro.lmk.use_new_strategy=true
ro.lmk.enable_watermark_check=true
ro.lmk.enable_userspace_lmk=true
ro.lmk.enhance_batch_kill=false
ro.lmk.super_critical=701
ro.lmk.kill_timeout_ms=50
ro.lmk.psi_scrit_complete_stall_ms=150
ro.lmk.direct_reclaim_pressure=45
ro.lmk.reclaim_scan_threshold=0
# Incremental FS
ro.incremental.enable=1

20
recovery/root/Android.bp Normal file
View File

@@ -0,0 +1,20 @@
//
// Copyright (C) 2026 The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
prebuilt_etc {
name: "init.recovery.qcom.rc",
src: "init.recovery.qcom.rc",
sub_dir: "recovery/root",
filename: "init.recovery.qcom.rc",
installable: true,
}
prebuilt_etc {
name: "init.recovery.usb.rc",
src: "init.recovery.usb.rc",
sub_dir: "recovery/root",
filename: "init.recovery.usb.rc",
installable: true,
}

View File

@@ -4,15 +4,15 @@
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of The Linux Foundation nor
# the names of its contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of The Linux Foundation nor
# the names of its contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -31,59 +31,148 @@
# SPDX-License-Identifier: BSD-3-Clause-Clear
#
function configure_zram_parameters() {
swapoff /dev/block/zram0 2>/dev/null || true
# Reset zram device
[ -w /sys/block/zram0/reset ] && echo 1 > /sys/block/zram0/reset
# Set compression algorithm (LZ4 optimized for ARM Cortex-A76/A55)
echo lz4 > /sys/block/zram0/comp_algorithm 2>/dev/null || return 1
# Optimize compression streams for 8-core big.LITTLE (2x A76 + 6x A55)
echo 4 > /sys/block/zram0/max_comp_streams 2>/dev/null || true
# Set 4GB zram size
echo 4294967296 > /sys/block/zram0/disksize 2>/dev/null || return 1
# Initialize and enable swap
mkswap /dev/block/zram0 2>/dev/null || return 1
swapon /dev/block/zram0 -p 32758 2>/dev/null || return 1
# VM tuning - Optimized for Realme 6 Pro mobile workloads
{
# Swappiness: Slightly higher for 4GB zram to utilize it effectively
echo 100 > /proc/sys/vm/swappiness
# Cache pressure: Aggressive reclaim for mobile RAM management
echo 100 > /proc/sys/vm/vfs_cache_pressure
# Page-cluster: Small reads optimal for mobile flash + zram combo
echo 1 > /proc/sys/vm/page-cluster
# Dirty ratios: Conservative for mobile storage longevity
echo 20 > /proc/sys/vm/dirty_ratio
echo 5 > /proc/sys/vm/dirty_background_ratio
# Extra free memory: Buffer for smooth operation
echo 1024 > /proc/sys/vm/extra_free_kbytes
# Memory overcommit: Conservative for stability
echo 1 > /proc/sys/vm/overcommit_memory
echo 50 > /proc/sys/vm/overcommit_ratio
# Additional mobile optimizations for Snapdragon 720G
echo 1 > /proc/sys/vm/compact_memory 2>/dev/null || true
echo 0 > /proc/sys/vm/oom_kill_allocating_task 2>/dev/null || true
# Optimize readahead for mobile storage patterns
echo 128 > /sys/block/*/queue/read_ahead_kb 2>/dev/null || true
} 2>/dev/null
return 0
function configure_read_ahead_kb_values() {
MemTotalStr=`cat /proc/meminfo | grep MemTotal`
MemTotal=${MemTotalStr:16:8}
dmpts=$(ls /sys/block/*/queue/read_ahead_kb | grep -e dm -e mmc)
# Set 128 for <= 3GB &
# set 512 for >= 4GB targets.
if [ $MemTotal -le 3145728 ]; then
echo 128 > /sys/block/mmcblk0/bdi/read_ahead_kb
echo 128 > /sys/block/mmcblk0rpmb/bdi/read_ahead_kb
for dm in $dmpts; do
echo 128 > $dm
done
else
echo 512 > /sys/block/mmcblk0/bdi/read_ahead_kb
echo 512 > /sys/block/mmcblk0rpmb/bdi/read_ahead_kb
for dm in $dmpts; do
echo 512 > $dm
done
fi
}
function enable_swap() {
# Enable swap if not already enabled
if [ ! -f /proc/swaps ] || [ -z "$(cat /proc/swaps | grep zram0)" ]; then
return 0
fi
}
function configure_memory_parameters() {
# Unified memory configuration for Atoll device (Realme 6 Pro: 6GB/8GB RAM)
# Combines ZRAM setup and memory management parameters
ProductName=`getprop ro.product.name`
arch_type=`uname -m`
MemTotalStr=`cat /proc/meminfo | grep MemTotal`
MemTotal=${MemTotalStr:16:8}
# Configure ZRAM parameters with LZ4 compression
echo lz4 > /sys/block/zram0/comp_algorithm
echo 100 > /proc/sys/vm/swappiness
echo 60 > /proc/sys/vm/direct_swappiness
echo 0 > /proc/sys/vm/page-cluster
if [ -f /sys/block/zram0/disksize ]; then
# Enable deduplication if available
if [ -f /sys/block/zram0/use_dedup ]; then
echo 1 > /sys/block/zram0/use_dedup
fi
# Configure ZRAM size based on total RAM
if [ $MemTotal -le 4194304 ]; then
# 4GB RAM: 2.5GB ZRAM
echo 2684354560 > /sys/block/zram0/disksize
echo 4 > /sys/module/lowmemorykiller/parameters/almk_totalram_ratio
elif [ $MemTotal -le 6291456 ]; then
# 6GB RAM: 3GB ZRAM
echo 3221225472 > /sys/block/zram0/disksize
echo 6 > /sys/module/lowmemorykiller/parameters/almk_totalram_ratio
elif [ $MemTotal -le 8388608 ]; then
# 8GB RAM: 4GB ZRAM
echo 4294967296 > /sys/block/zram0/disksize
echo 8 > /sys/module/lowmemorykiller/parameters/almk_totalram_ratio
else
# 12GB+ RAM: 5GB ZRAM
echo 5368709120 > /sys/block/zram0/disksize
echo 10 > /sys/module/lowmemorykiller/parameters/almk_totalram_ratio
fi
# Initialize and enable ZRAM swap
mkswap /dev/block/zram0
swapon /dev/block/zram0 -p 32758
fi
# Configure Low Memory Killer parameters
# Read adj series and set adj threshold for PPR and ALMK
adj_series=`cat /sys/module/lowmemorykiller/parameters/adj`
adj_1="${adj_series#*,}"
set_almk_ppr_adj="${adj_1%%,*}"
# Calculate PPR adj threshold (HOME adj and below should not be affected)
set_almk_ppr_adj=$(((set_almk_ppr_adj * 6) + 6))
echo $set_almk_ppr_adj > /sys/module/lowmemorykiller/parameters/adj_max_shift
# Calculate vmpressure_file_min for 64-bit architecture
if [ "$arch_type" == "aarch64" ]; then
minfree_series=`cat /sys/module/lowmemorykiller/parameters/minfree`
minfree_1="${minfree_series#*,}"
rem_minfree_1="${minfree_1%%,*}"
minfree_2="${minfree_1#*,}"
rem_minfree_2="${minfree_2%%,*}"
minfree_3="${minfree_2#*,}"
rem_minfree_3="${minfree_3%%,*}"
minfree_4="${minfree_3#*,}"
rem_minfree_4="${minfree_4%%,*}"
minfree_5="${minfree_4#*,}"
vmpres_file_min=$((minfree_5 + (minfree_5 - rem_minfree_4)))
echo $vmpres_file_min > /sys/module/lowmemorykiller/parameters/vmpressure_file_min
fi
# Enable Adaptive LMK
echo 1 > /sys/module/lowmemorykiller/parameters/enable_adaptive_lmk
# Enable OOM reaper
if [ -f /sys/module/lowmemorykiller/parameters/oom_reaper ]; then
echo 1 > /sys/module/lowmemorykiller/parameters/oom_reaper
fi
# Configure Process Reclaim parameters
if [ -f /sys/devices/soc0/soc_id ]; then
soc_id=`cat /sys/devices/soc0/soc_id`
else
soc_id=`cat /sys/devices/system/soc/soc0/id`
fi
# Set PPR parameters (excluding premium SoCs)
case "$soc_id" in
"321" | "341" | "292" | "319" | "246" | "291" | "305" | "312")
# Skip PPR for premium targets
;;
*)
echo $set_almk_ppr_adj > /sys/module/process_reclaim/parameters/min_score_adj
echo 1 > /sys/module/process_reclaim/parameters/enable_process_reclaim
echo 50 > /sys/module/process_reclaim/parameters/pressure_min
echo 70 > /sys/module/process_reclaim/parameters/pressure_max
echo 30 > /sys/module/process_reclaim/parameters/swap_opt_eff
echo 512 > /sys/module/process_reclaim/parameters/per_swap_size
;;
esac
# Set global VM parameters
echo 0 > /sys/module/vmpressure/parameters/allocstall_threshold
echo 1 > /proc/sys/vm/watermark_scale_factor
# Configure read-ahead values
configure_read_ahead_kb_values
# Enable swap
enable_swap
}
# Core control parameters on silver
echo 0 0 0 0 1 1 > /sys/devices/system/cpu/cpu0/core_ctl/not_preferred
@@ -103,109 +192,94 @@ echo 85 > /proc/sys/kernel/sched_group_downmigrate
echo 100 > /proc/sys/kernel/sched_group_upmigrate
echo 1 > /proc/sys/kernel/sched_walt_rotate_big_tasks
#colocation v3 settings
# Colocation v3 settings
echo 740000 > /proc/sys/kernel/sched_little_cluster_coloc_fmin_khz
# configure governor settings for little cluster
# Configure governor settings for little cluster
echo "schedutil" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 0 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/up_rate_limit_us
echo 0 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/down_rate_limit_us
echo 500 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/up_rate_limit_us
echo 20000 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/down_rate_limit_us
echo 1248000 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/hispeed_freq
echo 576000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
# configure governor settings for big cluster
# Configure governor settings for big cluster
echo "schedutil" > /sys/devices/system/cpu/cpu6/cpufreq/scaling_governor
echo 0 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/up_rate_limit_us
echo 0 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/down_rate_limit_us
echo 500 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/up_rate_limit_us
echo 20000 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/down_rate_limit_us
echo 1267200 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/hispeed_freq
echo 652800 > /sys/devices/system/cpu/cpu6/cpufreq/scaling_min_freq
# sched_load_boost as -6 is equivalent to target load as 85. It is per cpu tunable.
echo -6 > /sys/devices/system/cpu/cpu6/sched_load_boost
echo -6 > /sys/devices/system/cpu/cpu7/sched_load_boost
echo -6 > /sys/devices/system/cpu/cpu6/sched_load_boost
echo -6 > /sys/devices/system/cpu/cpu7/sched_load_boost
echo 85 > /sys/devices/system/cpu/cpu6/cpufreq/schedutil/hispeed_load
# Enable conservative pl for power save
echo 1 > /proc/sys/kernel/sched_conservative_pl
echo "0:1248000" > /sys/module/cpu_boost/parameters/input_boost_freq
echo 40 > /sys/module/cpu_boost/parameters/input_boost_ms
# Set Memory parameters
configure_memory_parameters
# Enable bus-dcvs
for device in /sys/devices/platform/soc
do
for cpubw in $device/*cpu-cpu-llcc-bw/devfreq/*cpu-cpu-llcc-bw
do
echo "bw_hwmon" > $cpubw/governor
echo "2288 4577 7110 9155 12298 14236" > $cpubw/bw_hwmon/mbps_zones
echo 4 > $cpubw/bw_hwmon/sample_ms
echo 68 > $cpubw/bw_hwmon/io_percent
echo 20 > $cpubw/bw_hwmon/hist_memory
echo 0 > $cpubw/bw_hwmon/hyst_length
echo 80 > $cpubw/bw_hwmon/down_thres
echo 0 > $cpubw/bw_hwmon/guard_band_mbps
echo 250 > $cpubw/bw_hwmon/up_scale
echo 1600 > $cpubw/bw_hwmon/idle_mbps
echo 50 > $cpubw/polling_interval
done
for cpubw in $device/*cpu-cpu-llcc-bw/devfreq/*cpu-cpu-llcc-bw
do
echo "bw_hwmon" > $cpubw/governor
echo "2288 4577 7110 9155 12298 14236" > $cpubw/bw_hwmon/mbps_zones
echo 4 > $cpubw/bw_hwmon/sample_ms
echo 68 > $cpubw/bw_hwmon/io_percent
echo 20 > $cpubw/bw_hwmon/hist_memory
echo 0 > $cpubw/bw_hwmon/hyst_length
echo 80 > $cpubw/bw_hwmon/down_thres
echo 0 > $cpubw/bw_hwmon/guard_band_mbps
echo 250 > $cpubw/bw_hwmon/up_scale
echo 1600 > $cpubw/bw_hwmon/idle_mbps
echo 50 > $cpubw/polling_interval
done
for llccbw in $device/*cpu-llcc-ddr-bw/devfreq/*cpu-llcc-ddr-bw
do
echo "bw_hwmon" > $llccbw/governor
echo "1144 1720 2086 2929 3879 5931 6881 8137" > $llccbw/bw_hwmon/mbps_zones
echo 4 > $llccbw/bw_hwmon/sample_ms
echo 68 > $llccbw/bw_hwmon/io_percent
echo 20 > $llccbw/bw_hwmon/hist_memory
echo 0 > $llccbw/bw_hwmon/hyst_length
echo 80 > $llccbw/bw_hwmon/down_thres
echo 0 > $llccbw/bw_hwmon/guard_band_mbps
echo 250 > $llccbw/bw_hwmon/up_scale
echo 1600 > $llccbw/bw_hwmon/idle_mbps
echo 40 > $llccbw/polling_interval
done
for npubw in $device/*npu*-npu-ddr-bw/devfreq/*npu*-npu-ddr-bw
do
echo 1 > /sys/devices/virtual/npu/msm_npu/pwr
echo "bw_hwmon" > $npubw/governor
echo "1144 1720 2086 2929 3879 5931 6881 8137" > $npubw/bw_hwmon/mbps_zones
echo 4 > $npubw/bw_hwmon/sample_ms
echo 80 > $npubw/bw_hwmon/io_percent
echo 20 > $npubw/bw_hwmon/hist_memory
echo 10 > $npubw/bw_hwmon/hyst_length
echo 30 > $npubw/bw_hwmon/down_thres
echo 0 > $npubw/bw_hwmon/guard_band_mbps
echo 250 > $npubw/bw_hwmon/up_scale
echo 0 > $npubw/bw_hwmon/idle_mbps
echo 40 > $npubw/polling_interval
echo 0 > /sys/devices/virtual/npu/msm_npu/pwr
done
#Enable mem_latency governor for L3, LLCC, and DDR scaling
for memlat in $device/*cpu*-lat/devfreq/*cpu*-lat
do
echo "mem_latency" > $memlat/governor
echo 10 > $memlat/polling_interval
echo 400 > $memlat/mem_latency/ratio_ceil
done
#Enable cdspl3 governor for L3 cdsp nodes
for l3cdsp in $device/*cdsp-cdsp-l3-lat/devfreq/*cdsp-cdsp-l3-lat
do
echo "cdspl3" > $l3cdsp/governor
done
#Gold L3 ratio ceil
echo 4000 > /sys/class/devfreq/soc:qcom,cpu6-cpu-l3-lat/mem_latency/ratio_ceil
#Enable compute governor for gold latfloor
for latfloor in $device/*cpu*-ddr-latfloor*/devfreq/*cpu-ddr-latfloor*
do
echo "compute" > $latfloor/governor
echo 10 > $latfloor/polling_interval
done
for llccbw in $device/*cpu-llcc-ddr-bw/devfreq/*cpu-llcc-ddr-bw
do
echo "bw_hwmon" > $llccbw/governor
echo "1144 1720 2086 2929 3879 5931 6881 8137" > $llccbw/bw_hwmon/mbps_zones
echo 4 > $llccbw/bw_hwmon/sample_ms
echo 68 > $llccbw/bw_hwmon/io_percent
echo 20 > $llccbw/bw_hwmon/hist_memory
echo 0 > $llccbw/bw_hwmon/hyst_length
echo 80 > $llccbw/bw_hwmon/down_thres
echo 0 > $llccbw/bw_hwmon/guard_band_mbps
echo 250 > $llccbw/bw_hwmon/up_scale
echo 1600 > $llccbw/bw_hwmon/idle_mbps
echo 40 > $llccbw/polling_interval
done
for npubw in $device/*npu*-npu-ddr-bw/devfreq/*npu*-npu-ddr-bw
do
echo 1 > /sys/devices/virtual/npu/msm_npu/pwr
echo "bw_hwmon" > $npubw/governor
echo "1144 1720 2086 2929 3879 5931 6881 8137" > $npubw/bw_hwmon/mbps_zones
echo 4 > $npubw/bw_hwmon/sample_ms
echo 80 > $npubw/bw_hwmon/io_percent
echo 20 > $npubw/bw_hwmon/hist_memory
echo 10 > $npubw/bw_hwmon/hyst_length
echo 30 > $npubw/bw_hwmon/down_thres
echo 0 > $npubw/bw_hwmon/guard_band_mbps
echo 250 > $npubw/bw_hwmon/up_scale
echo 0 > $npubw/bw_hwmon/idle_mbps
echo 40 > $npubw/polling_interval
echo 0 > /sys/devices/virtual/npu/msm_npu/pwr
done
done
# cpuset parameters
echo 0-5 > /dev/cpuset/background/cpus
# memlat specific settings are moved to separate file under
# device/target specific folder
setprop vendor.dcvs.prop 1
# cpuset parameters for power save
echo 0-3 > /dev/cpuset/background/cpus
echo 0-5 > /dev/cpuset/system-background/cpus
# Turn off scheduler boost at the end
@@ -214,8 +288,8 @@ echo 0 > /proc/sys/kernel/sched_boost
# Turn on sleep modes
echo 0 > /sys/module/lpm_levels/parameters/sleep_disabled
# configure zram
configure_zram_parameters
# Change IO scheduler to noop for better performance
echo noop > /sys/block/sda/queue/scheduler
# Post-setup services
setprop vendor.post_boot.parsed 1
# Create 1 kswapd thread
echo 1 > /proc/sys/vm/kswapd_threads

View File

@@ -568,11 +568,6 @@ on property:ro.crypto.state=unsupported
on property:persist.env.fastdorm.enabled=true
setprop persist.radio.data_no_toggle 1
on post-fs-data
# Charge Bypass
chown system system /sys/class/power_supply/battery
chmod 0660 /sys/class/power_supply/battery
service vendor.qrtr-ns /vendor/bin/qrtr-ns -f
class core
user vendor_qrtr

View File

@@ -29,12 +29,6 @@ on boot
chown system system /sys/class/leds/vibrator/vmax_mv
chmod 0644 /sys/class/leds/vibrator/vmax_mv
chown system graphics /sys/class/drm/sde-crtc-0/measured_fps
chmod 0660 /sys/class/drm/sde-crtc-0/measured_fps
chown system system /sys/class/thermal/thermal_zone78/temp
chmod 0660 /sys/class/thermal/thermal_zone78/temp
on property:ro.boot.product.hardware.sku=nfc
start secure_element_hal_service
start vendor.nfc_hal_service

View File

@@ -1,6 +0,0 @@
type devicesettings_app, domain;
app_domain(devicesettings_app)
# Allow charging bypass to overwrite
allow devicesettings_app sysfs_battery_writable:dir r_dir_perms;
allow devicesettings_app sysfs_battery_writable:file { open read write getattr ioctl };

View File

@@ -13,9 +13,6 @@ type proc_oppo_fp, fs_type, proc_type;
# Camera
type vendor_persist_camera_file, file_type;
# Bypass Charging
type sysfs_battery_writable, sysfs_type, fs_type;
# Devinfo
type proc_devinfo, fs_type, proc_type;

View File

@@ -19,9 +19,6 @@
# Cust
/dev/block/platform/soc/4744000.sdhci/by-name/cust u:object_r:vendor_custom_block_device:s0
# Charging Bypass
/sys/class/power_supply/battery/input_suspend u:object_r:sysfs_battery_writable:s0
# Oppo Partitions
/dev/block/platform/soc/1d84000.ufshc/by-name/oppodycnvbk u:object_r:vendor_modem_efs_partition_device:s0
/dev/block/platform/soc/1d84000.ufshc/by-name/oppostanvbk u:object_r:vendor_modem_efs_partition_device:s0

View File

@@ -1,5 +1,4 @@
allow hal_power_default proc_touchpanel:dir search;
allow hal_power_default proc_touchpanel:file rw_file_perms;
allow init sysfs_battery_supply:file rw_file_perms;
get_prop(hal_power_default, vendor_mpctl_prop);

View File

@@ -7,8 +7,5 @@ r_dir_file(system_app, proc_touchpanel);
r_dir_file(system_app, vendor_sysfs_usb_supply);
allow system_app vendor_sysfs_usb_supply:file rw_file_perms;
allow system_app vendor_sysfs_battery_supply:dir search;
allow system_app vendor_sysfs_battery_supply:file read;
allow system_app vendor_sysfs_battery_supply:file getattr;
# Allow Settings app to control input_suspend (bypass charging)
allow system_app vendor_sysfs_battery_supply:file rw_file_perms;

View File

@@ -25,9 +25,10 @@ persist.vendor.camera.oissr.debug=1
vendor.debug.camera.eisv2enable=1
vendor.debug.camera.eisv3enable=1
# Allow privileged camera apps
persist.vendor.camera.privapp.list=com.android.camera,com.google.camera,org.lineageos.aperture
persist.vendor.camera.privapp.list=org.lineageos.aperture,org.codeaurora.snapcam,com.android.camera,com.google.camera
# Allow aux cameras
vendor.camera.aux.packagelist=com.android.camera,com.google.camera,org.lineageos.aperture
vendor.camera.aux.packagelist=org.lineageos.aperture,org.codeaurora.snapcam,com.android.camera,com.google.camera
persist.vendor.camera.expose.aux=1
# CNE
persist.vendor.cne.feature=1
@@ -110,7 +111,6 @@ persist.sys.radio.force_lte_ca=true
persist.vendor.data.iwlan.enable=true
persist.vendor.data.mode=concurrent
ril.subscription.types=NV,RUIM
ro.telephony.default_network=22,22
ro.vendor.use_data_netmgrd=true
telephony.lteOnCdmaDevice=1
persist.sys.fflag.override.settings_network_and_internet_v2=true
@@ -123,11 +123,6 @@ persist.vendor.ssr.restart_level=ALL_ENABLE
persist.debug.wfd.enable=1
persist.sys.wfd.virtual=0
# ZRAM
ro.zram.mark_idle_delay_mins=60
ro.zram.first_wb_delay_mins=180
ro.zram.periodic_wb_delay_hours=24
#SkiaGL
debug.renderengine.backend=skiaglthreaded
renderthread.skia.reduceopstasksplitting=true

View File

@@ -151,19 +151,22 @@ ro.qcom.adreno.qgl.ShaderStorageImageExtendedFormats=0
# FM
vendor.hw.fm.init=0
# FRP
ro.frp.pst=/dev/block/bootdevice/by-name/frp
#Graphics
debug.hwui.use_hint_manager=true
debug.hwui.target_cpu_time_percent=30
debug.sf.disable_client_composition_cache=0
debug.sf.enable_adpf_cpu_hint=true
# Keyguard
keyguard.no_require_sim=true
debug.sf.enable_gl_backpressure=0
# Keystore
ro.hardware.keystore_desede=true
# Game FrameRate
debug.graphics.game_default_frame_rate.disabled=true
# Media
debug.media.codec2=2
debug.stagefright.c2inputsurface=-1
@@ -194,6 +197,21 @@ persist.vendor.radio.rat_on=combine
ro.telephony.default_network=22,20
ro.vendor.use_data_netmgrd=true
telephony.lteOnCdmaDevice=1
persist.vendor.radio.add_power_save=1
persist.vendor.radio.force_on_dc=1
persist.vendor.radio.lte_vrte_ltd=1
persist.vendor.radio.snrt_max_layer=3
persist.vendor.radio.data_con_rprt=1
persist.vendor.radio.ignore_dom_time=10
persist.vendor.radio.oppo.signal.adapt=1
ro.vendor.radio.oppo.signal.adapt=true
persist.vendor.radio.enable_temp_dds=true
persist.vendor.radio.custom_ecc=1
persist.vendor.radio.data_ltd_sys_ind=1
# ScrollOptimizer
persist.sys.perf.scroll_opt=true
persist.sys.perf.scroll_opt.heavy_app=1
# Sensors
persist.vendor.sensors.odl.adsp=true