201 Commits

Author SHA1 Message Date
a8e756f058 sepolicy: qti: Allow system server to detect oem charging
Some checks failed
action.yml / sepolicy: qti: Allow system server to detect oem charging (push) Failing after 0s
Signed-off-by: AnierinB <anierin@evolution-x.org>
2026-01-20 14:36:56 +01:00
DragonEmperor9480
2aa14e5ac1 sepolicy: adress fingerprint denials
*1565  1775 E [ANC_TAC][File]: AncMkDir: fail to mkdir /data/vendor/fingerprint/info, errno = 13, errnostr = Permission denied
*667   667 W qseecomd: type=1400 audit(0.0:82): avc:  denied  { write } for  name="debase_context" dev="sda2" ino=565 scontext=u:r:tee:s0 tcontext=u:object_r:vendor_persist_fingerprint_file:s0 tclass=file permissive=0
*1565  1565 W fingerprint@2.1: type=1400 audit(0.0:106): avc:  denied  { write } for  name="tee_bind_core" dev="proc" ino=4026532098 scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=0
*667   667 W qseecomd: type=1400 audit(0.0:107): avc:  denied  { write } for  name="debase_context" dev="sda2" ino=565 scontext=u:r:tee:s0 tcontext=u:object_r:vendor_persist_fingerprint_file:s0 tclass=file permissive=0
*1565  1565 W fingerprint@2.1: type=1400 audit(0.0:78): avc:  denied  { write } for  name="tee_bind_core" dev="proc" ino=4026532098 scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=0
*1565  1565 W fingerprint@2.1: type=1400 audit(0.0:79): avc:  denied  { read } for  name="u:object_r:serialno_prop:s0" dev="tmpfs" ino=3880 scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:serialno_prop:s0 tclass=file permissive=0
*1565  1565 W fingerprint@2.1: type=1400 audit(0.0:80): avc:  denied  { create } for  name="image_raw" scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:fingerprint_vendor_data_file:s0 tclass=dir permissive=0
2026-01-20 14:36:56 +01:00
a9e2434135 sepolicy: qti: Allow system_server to r/w oplus_chg nodes 2026-01-20 14:36:56 +01:00
Broly1
da7c6b9c7e keyhandler: Move Alert Slider to Sound settings and remove icon 2026-01-20 14:36:56 +01:00
Adhitya Mohan
8cb6a428b8 Add icon and summary for alert slider settings 2026-01-20 14:36:56 +01:00
Adhitya Mohan
45fd68a691 Keyhandler: Export Keyhandler setting and service 2026-01-20 14:36:56 +01:00
inferno0230
b3debd299e sensors: Bump android.hardware.sensors to V3-ndk
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:36:56 +01:00
Alcatraz323
3db4e37b15 Implement DSPVolumeSynchronizer
Some Xiaomi devices have a speaker that needs a framework to cooperate
with DSP to synchronize volume so that the DSP can limit bass when the
volume is high to prevent distortion.

Change-Id: I750803d94161e1e7482552d2a39566f42e82fc0a
2026-01-20 14:36:56 +01:00
Ghosuto
d4ba636d79 dolby: Update to use new tooltip position provider API 2026-01-20 14:36:56 +01:00
Sugakesshaa
b5f8313c8b vintf: Add oplus Dolby Atmos entries to FCM
Change-Id: Ifc4dff53e516f33b9e5581d56ce6f9c00f0da8cf
2026-01-20 14:36:56 +01:00
Sugakesshaa
4c7541801e dolby: Create a split makefile for Dolby
Change-Id: Ie191d7af0ee55c44cc939fc5dd1b6e45c965dbf4
2026-01-20 14:36:56 +01:00
Adithya R
3b46301002 sepolicy: qti: Add sepolicy for Dolby Atmos
Change-Id: I8c41ff32e579cec9c871d6a0177ca027034281c8
2026-01-20 14:36:56 +01:00
Sugakesshaa
4e0edb8439 dolby: Rebrand to oplus
Change-Id: Ic54a93647c0dcbe3b1ef8b576d80cc4c6bf74992
2026-01-20 14:36:56 +01:00
Fabian Leutenegger
8410207b70 dolby: Switch to MaterialTheme settingsBackground for EqualizerScreen background color
Change-Id: I546e3528814276eb857a650cb6c173d914550fb5
2026-01-20 14:36:56 +01:00
Bruno Martins
6935b56b10 dolby: Use all shared resources from devicesettings
Change-Id: Icd7f381c574ea36eb4d797cefd60ba9f1a0941bd
2026-01-20 14:36:56 +01:00
Pranav Vashi
2e28ec3b3b dolby: Remove deprecated PlainTooltipBox
Change-Id: I70ffff5ba30c5eeaff431e46c82eaf05d46e4cb0
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
2026-01-20 14:36:56 +01:00
basamaryan
d55ca3f36a dolby: Fix build with kotlinc 1.9.0
Reformat the code while at it

Change-Id: I4f9fdc9d25eb57240612cff1b3bef3663014f9a8
2026-01-20 14:36:56 +01:00
Michael Bestas
677728e777 dolby: Convert to SwitchPreferenceCompat
Change-Id: Ic1cbaba37d499da1855af9c3930f2df426e2d3af
2026-01-20 14:36:56 +01:00
Chaohui Wang
f35cc8024f dolby: Migrate to CompoundButton.OnCheckedChangeListener
Switch and SwitchCompat are both CompoundButton.

Using CompoundButton in Java will helps migration in the future.

Bug: 306658427 | AOSP | AOSP
Test: manual - check Settings pages
Test: m RunSettingsLibRoboTests
Change-Id: I85a70d4c504d8584030ea4a058f30d74206ab835
2026-01-20 14:36:56 +01:00
Peter Kalauskas
b438c19749 dolby: Enable use_resource_processor for all sysui deps
This will make the build faster

Test: m checkbuild
Bug: 295208392
Change-Id: I0c1bd901429bbe3bf81c1530e156735f8637a96e
2026-01-20 14:36:56 +01:00
Adithya R
36147f24ae dolby: Add intelligent equalizer setting
Move preference-related classes to a new package while we're at it,
to reduce code clutter.

Change-Id: I2430e8ab9b6758503ce1777ec985a3e400b55b8e
2026-01-20 14:36:56 +01:00
Adithya R
318cf2d6ff dolby: Introduce graphical equalizer
Squashed:

dolby: Refresh preset name on main screen

Change-Id: I96783e2a03c384f031787f4cc9140f7d64dadb2f
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>

Change-Id: I38ee6ce594e5671af42afc3d4bf0f004329482b9
2026-01-20 14:36:56 +01:00
Pranav Vashi
d46d0988b8 dolby: Add launcher icon
Change-Id: I4d36842ca96048f9b55604d66cc7741759d657f3
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
[adithya2306: Add monochrome icon as well]
Signed-off-by: Adithya R <gh0strider.2k18.reborn@gmail.com>
2026-01-20 14:36:56 +01:00
Adithya R
fef9704087 dolby: Restore current profile _after_ resetting profiles
Ensure to end the onBootCompleted routine with the correct profile set.

Change-Id: I2d5f74a7c0145af2f9d064cd98fa2dc70e5a7acd
2026-01-20 14:36:56 +01:00
Adithya R
2e27e3c870 dolby: Do not set volume leveler amount
This value is set to zero in almost every known dax-default.xml,
including ours.
DaxService also doesn't mess with this value, instead only sets
VolumeLevelerEnabled.

Change-Id: Ib944728d478cff58aebc4f47128bcd5fe32ff9f6
2026-01-20 14:36:56 +01:00
Adithya R
288abfe34e dolby: Restore all settings upon bootup
Dolby often messes up restoring profile-specific settings after a reboot.
"Fine. I'll do it myself."

Change-Id: Ic255c6922eabae0b522c05110f87e2c10a97fb6c
2026-01-20 14:36:56 +01:00
Adithya R
d54bc9bfed dolby: Rewrite in Kotlin
Some cleanup and restructuring while we're at it.

Change-Id: I2f1fc53c202d91421c7b6af68c814c25398a62e4
2026-01-20 14:36:56 +01:00
Adithya R
476c579574 dolby: Revert "Re-enable speaker virtualization after bootup"
No longer necessary

Change-Id: Iac820eafa71ea3e4ccaad2bfa0fb76c37279a22a
2026-01-20 14:36:56 +01:00
Adithya R
b11f1f6140 xiaomi: Introduce Dolby Atmos
Moved from marble/sm8450-common

History:

commit 82fe03168c0402e4cb10d25859c3b398c0ef654a
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Thu Mar 21 21:35:36 2024 +0530

    marble: parts: Restore dolby profile on audio changes

    Something keeps resetting back at random times, from what I observed,
    after resuming media or on a device change, lets workaround that.

    Change-Id: Id065f2482636194655c2399f0c35ad56b8e7a29d

commit c4400bd1326f65aeac1d0f26bb830ce7fd079773
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Fri Feb 2 09:29:08 2024 +0530

    marble: parts/keyhandler: Guard debug logging

    Change-Id: I246941f26cd1f71b696eb3c996794c9baa5dbc00

commit f11b70a98a11d0b89673d73002996aed9f11fbd7
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Sun Dec 31 20:36:52 2023 +0530

    marble: parts: Re-enable speaker virtualization after bootup

    For whatever reason, speaker virtualization isn't automatically
    restored at bootup unlike the other parameters. It was reported to be
    fixed by connecting and disconnecting headphones or disabling and
    enabling the toggle, so let's just automate that at bootup.

commit abcff4fb947c89b69c1d25bd290fd91b7873af6a
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Fri Oct 20 06:49:19 2023 +0530

    marble: parts: Implement profile-specific Dolby settings

    Some refactoring and cleanup while we're at it.

commit dc54f9ddeff212d017b0cba16e56516e99335bb3
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Mon Oct 9 21:58:58 2023 +0530

    marble: parts: Remove play/pause hack while toggling Dolby

    Not required with/fixed by:
    35217: audioflinger: Do not allow DAP effect to be suspended | https://gerrit.aospa.co/c/AOSPA/android_frameworks_av/+/35217

commit dd2acc8e0c10d05f86ff229412cc9f72ea242b44
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Wed Sep 13 21:41:20 2023 +0530

    marble: parts: Set proper summary for dolby settings

    Show the current status in Settings > Sound as well as the QS tile.

commit 92d341ba3d22f323eded525487db4289d6edc0fe
Author: Fabian Leutenegger <fabian.leutenegger@bluewin.ch>
Date:   Fri Aug 25 10:26:53 2023 +0200

    marble: parts: Always refresh playback if status changed

     * otherwise dolby would stay active even if you disable its setting

    Change-Id: If59d8081fa12da2aa67e5149db97965c0805d76e

commit b1944744649b6fddcb7bc3864b92f298b6e78821
Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Mon Aug 21 13:21:18 2023 +0530

    marble: parts: Introduce Dolby Atmos

    Based on existing dirac implementation and observing stock
    sound effects app and daxservice.

    Thanks to jhenrique09 for the hack from old dirac parts
    "Pause/play music stream to get effects applied".

    TODO: bring back misound (same as stock)

    Co-authored-by: Henrique Silva <jhenrique09.mcz@hotmail.com>

Change-Id: I79841c045fe7b92c438177916f756faab72ff0e9
2026-01-20 14:36:56 +01:00
Sugakesshaa
60e2c0d181 sepolicy: qti: Allow powerhal write to /proc
Change-Id: Id894d56fdf0df323e75004c90c0b904eb450837c
2026-01-20 14:36:56 +01:00
Sugakesshaa
f5c7563592 sepolicy: qti: Allow binder calls for sensor hal to system_server
Change-Id: Ic624ff754f0bf7f60f443a449987e30ca2691dfd
2026-01-20 14:36:56 +01:00
pjgowtham
134a96902f aidl: sensors: Add clang-format
Change-Id: Ifece344ef765d5437eefd59ecbe4cd50ce1295f5
2026-01-20 14:36:56 +01:00
pjgowtham
42d234e7b1 overlay/sensors: Configure Doze brightness sensor
Oplus doze brightness sensors either reports 0 or 1

0.0 - Dark environment
1.0 - Bright environment

aod_light_mode value of 1 enables qcom,mdss-dsi-aod-low-mode-command
and any other value would enable qcom,mdss-dsi-aod-high-mode-command

Change-Id: I98e3ea6abe0375ca75dad1b82e0bc6a1551cbb0e
2026-01-20 14:36:56 +01:00
pjgowtham
ff08d01f05 overlay: qssi: Define quick_pickup sensor string
Tests: Ensure quick pickup works when the "Lift to check phone"
is enabled under settings (with fingerprint enrolled)

Change-Id: I00626512dcca51d666e37dda4b281575bf1a2ea7
2026-01-20 14:36:56 +01:00
Sebastiano Barezzi
881b81c5c2 overlay: qssi: Enable config_dozePulsePickup
Change-Id: Ice5cd780eb77e2ae78a3a84a0140c321ad84f143
2026-01-20 14:36:56 +01:00
pjgowtham
a4c3063285 sepolicy: qti: Label sensors AIDL multihal
Change-Id: I51d1f5542f3bb6922d0f3d9b39777bc8b1ff58ff
Signed-off-by: Vaisakh Murali <mvaisakh@statixos.com>
2026-01-20 14:36:56 +01:00
pjgowtham
3909e55d4b aidl: sensors: Standardize qti.sensor.amd to glance sensor
Change-Id: I65150cffde2bd8a48c33b26a0f139a24687f8591
2026-01-20 14:36:56 +01:00
Sugakesshaa
e66bd88a16 aidl: sensors: Invert value for pickup gesture event
- oplus pickup sensor inverts the value for it to work properly;
- Hence, invert the event check for it to work accordingly.

thanks to @ cyberknight777 for the idea

Test: Build, test lift to check phone.

Change-Id: If09de1758823e2246106d6e278ecc80ca5327ee5
2026-01-20 14:36:56 +01:00
Cosmin Tanislav
ba41fe2135 aidl: sensors: Change standard tilt_detector to pickup_gesture
* ignore non-wakeup sensor variant
* ignore events that do not properly match a pickup

pjgowtham: The tilt_detector sensor already has inverted sensor events
for it to be any useful as standard sensor. Thus repurpose them as
pickup sensor.

Change-Id: Ibe2f9fee1551da613713d40c1b8d0a26d38a93ae
Signed-off-by: ralph950412 <ralph950412@gmail.com>
Signed-off-by: Sugakesshaa <sugakesshaa@pixelos.net>
2026-01-20 14:36:56 +01:00
Cosmin Tanislav
8cb1749612 aidl: sensors: Avoid target name conflicts
Change-Id: Ib6426caf68fe1a7a7f637bdc5c4f0036866f8b78
Signed-off-by: ralph950412 <ralph950412@gmail.com>
Signed-off-by: Cyber Knight <cyberknight755@gmail.com>
2026-01-20 14:36:56 +01:00
Arian
84b4fe25ff aidl: sensors: Change default applicable license to Android-Apache-2.0
hardware_interfaces_license is not available here.

Change-Id: I8c8d00cdeda2739c3e4419f979f1fbf0ef66fc0a
2026-01-20 14:36:56 +01:00
ralph950412
3661ded51c aidl: sensors: Import 2.X sensors hal proxy
* From android-14.0.0_r15

Change-Id: Id6f37920db2869574ca1b8e04c10e6ec3268ad4b
Signed-off-by: ralph950412 <ralph950412@gmail.com>
Signed-off-by: Cyber Knight <cyberknight755@gmail.com>
2026-01-20 14:36:56 +01:00
ralph950412
1d14ee1e5f aidl: sensors: Import aidl sensors MultiHal
* From android-14.0.0_r15

Change-Id: Id7d8dfae1290bdba84d5a9f4c6583d54a2769ba8
Signed-off-by: ralph950412 <ralph950412@gmail.com>
2026-01-20 14:36:56 +01:00
pjgowtham
28eb866b92 aidl: vibrator: Use THUD effect from wly for DOUBLE_CLICK
Change-Id: I4f1a718254ca1df5167956371e11b4102b10094c
2026-01-20 14:36:55 +01:00
pjgowtham
dc5ca02c7f aidl: vibrator: Minimize code for ledVibratorDevice
This fixes vibration on ziti where it works only when strace is used.

* Minimize code wherever applicable.
* Remove writes to /rtp since we are not using them.

Change-Id: I385fe64b33e541bc398e58dbbf67a728edff8b24
2026-01-20 14:35:55 +01:00
pjgowtham
5afdf4ec66 sepolicy: qti: Allow init to write to usb nodes for enabling OTG
Change-Id: I14d209d1d04ba6aae077f828a71f5683b4a6405c
2026-01-20 14:34:18 +01:00
ppanzenboeck
4dc9d516ba cleanup rebase + fix sepolicy for 16 2026-01-20 14:34:18 +01:00
ppanzenboeck
0244760a19 move oos cam oplus-fwk libs to hardware/oplus [2/2] 2026-01-20 14:34:18 +01:00
cjh1249131356
885b44b3d9 sepolicy: Add rules for NrModeSwitcher
Signed-off-by: cjh1249131356 <cjh1249131356@gmail.com>
2026-01-20 14:34:18 +01:00
cjh1249131356
f29feffced sepolicy: Add OnePlus Camera rules for sm8250
Co-authored-by: chandu078 <chandudyavanapelli03@gmail.com>
Signed-off-by: cjh1249131356 <cjh1249131356@gmail.com>
2026-01-20 14:34:18 +01:00
LineageOS Infra
047a6d40c8 Automatic translation import
Change-Id: I94362909328034c8f8b830036c1efe39bb107638
2026-01-20 14:33:23 +01:00
armdebug
4d5ed80495 KeyHandler: Use SimpleSummaryProvider for ListPreference
Setting the summary with string formatting (%s) is deprecated.

Reference: https://developer.android.com/develop/ui/views/components/settings/customize-your-settings#summaries
Change-Id: Ie541b81460627b54a794c4302bfee29c0130d842
2026-01-20 14:33:23 +01:00
armdebug
08ee047103 doze: Use SimpleSummaryProvider for ListPreference
Setting the summary with string formatting (%s) is deprecated.

Reference: https://developer.android.com/develop/ui/views/components/settings/customize-your-settings#summaries
Change-Id: I70b186738814bdab486e3f1892f34a9ab3a48e46
2026-01-20 14:33:23 +01:00
Bruno Martins
7a12b4421b fingerprint: Avoid crashing with invalid location or if parsing fails
If reading location from `persist.vendor.fingerprint.optical.sensorlocation`
ever fails or prop is malformed, then the code will crash in this line:

  ParseInt(size, &props.sensorLocations[0].sensorRadius)

Avoid that by ensuring that `props.sensorLocations` is not empty.

Change-Id: I31a43f97e526fa8b7e6ec2080932cfb5552e237f
2026-01-20 14:33:23 +01:00
Bruno Martins
544a7ca610 fingerprint: Support parsing sensor location in multi-display setups
This adds support for side-mounted fingerprint sensors in multi-display
setups, like the case of OnePlus Open. Here, the fingerprint HAL doesn't
set a property with sensor location(s), so these targets need to set it
manually in the respective device trees.

The property must be formed as follows:

  persist.vendor.fingerprint.side.sensorlocation=x::y[::displayId1][|x::y[::displayId2]]

In the example of OnePlus Open:

  [persist.vendor.fingerprint.side.sensorlocation]: [2268::790::4630946717172870531|1116::814::4630946316123810436]

Change-Id: I29ed00d402c6d04777dbc06a801b99ef1e1b2c48
2026-01-20 14:33:23 +01:00
Bruno Martins
1beec6d6f3 sepolicy: qti: Add rules for extended SE HAL
This is needed on OnePlus Open for biometrics fingerprint to come up.

Change-Id: I82430fb776d3719efa288c5aebc46d5590d39197
2026-01-20 14:33:23 +01:00
Bruno Martins
c1c47ac781 vintf: Add vendor.oplus.hardware.secure_element
Change-Id: I081993dad98cb0d4f1dc63e6894be2bbede656e6
2026-01-20 14:33:23 +01:00
Bruno Martins
64ebb13708 sepolicy: qti: Allow ICharger to connect to ISensorManager
To be able to check fold sensor status.

Change-Id: Ic066d0234e965e4cca8cef9ea36661b7fc6910b7
2026-01-20 14:33:23 +01:00
Nick Reuter
1bfa52f911 Euicc: Convert to EuiccPolicy overlay
Change-Id: I192ddbf961fc2be98dbdf804ab792bb530a0acda
2026-01-20 14:33:23 +01:00
Bruno Martins
654834e74b sepolicy: qti: Label xueying wakeup nodes
Change-Id: Iba309abdea6e645ecea5f04aacb70e691393ebe8
2026-01-20 14:33:23 +01:00
Bruno Martins
ee7cba88ee vintf: Add vendor.zeku.hardware.explorer
As seen in OnePlus Open (xueying)

Change-Id: Ib353a48c9938d49635d586451841586b7a35c881
2026-01-20 14:33:23 +01:00
Bruno Martins
621fafd73b oplus: Declare hidl_zeku_explorer_interface
Change-Id: Ibc4a2584dd8bf1df06810ffdffb2c6316b2ece36
2026-01-20 14:33:23 +01:00
Luca Stefani
9cb7b80752 KeyHandler/OplusDoze/OplusEsimSwitcher: Optimize and shrink resources
Usually a safe set of optimizations

Change-Id: I1074af3a758439ff82771b03bdb0c4484828ca25
2026-01-20 14:33:23 +01:00
LuK1337
b44d204d85 pre-commit: Enable clang-format
Change-Id: I7a22a5fe9ee7176604fed0825f96417c53adb1ff
2026-01-20 14:33:23 +01:00
LuK1337
80718930bd vibrator: richtap: Run clang-format
Change-Id: I1391e3038fc74beecd85dc1398d39574748b05d4
2026-01-20 14:33:23 +01:00
LuK1337
0260b93f2b vibrator: qti: Run clang-format
Change-Id: I5a08063bfe95c22cee0c2ea23a6c4f69c7fa4e5a
2026-01-20 14:33:23 +01:00
LuK1337
2da53565a3 sensors: Run clang-format
Change-Id: Ie5c84a5d36d0f4ef4329647160345b0ea31190ca
2026-01-20 14:33:23 +01:00
LuK1337
4e09fa357f audio_amplifier: Run clang-format
Change-Id: If07ab6cd0064d96972204aeae53e1f1bfbdf9962
2026-01-20 14:33:23 +01:00
LineageOS Infra
6018e025c7 Automatic translation import
Change-Id: Ifb359716c3df8402f424f2b56d78288a2407fb38
2026-01-20 14:33:23 +01:00
LuK1337
7a26bb680c Run pre-commit run --all
Change-Id: Iedb907afb4da921dfc9e2b706cfa63fd1467394d
2026-01-20 14:33:23 +01:00
LuK1337
af8b5b2101 Introduce pre-commit & GitHub Actions for it
Change-Id: I4604d13e5ccf74ec4c7088a40a9f7f915f9b1293
2026-01-20 14:33:23 +01:00
madmax7896
0d49bb00a4 sepolicy: qti: Label giulia wakeup nodes
giulia / # cat /sys/devices/platform/soc/9c0000.qcom,qupv3_i2c_geni_se/988000.i2c/i2c-5/5-006a/name
sc8547d
giulia / # cat /sys/devices/platform/soc/9c0000.qcom,qupv3_i2c_geni_se/990000.i2c/i2c-6/6-006a/name
sc8547d
giulia / # cat /sys/devices/platform/soc/9c0000.qcom,qupv3_i2c_geni_se/9a0000.i2c/i2c-7/7-0010/name
dhall-ak09970

Change-Id: I51a7e1854370b3a9efe16d7f59d24ad6a3bb328b
2026-01-20 14:33:23 +01:00
madmax7896
e43e0de28e Euicc: Add OnePlus 13R / Ace 5 support
Change-Id: I0c35b7fca340092c1d96f994d8c7dd8cbd3fdef1
2026-01-20 14:33:23 +01:00
chandu078
b0ef79cd22 vintf: Add display MixLut3D interface
Change-Id: Id9d6dc6714feb5b53f9261adeb9d8975e75809d5
2026-01-20 14:33:23 +01:00
Bruno Martins
596af28122 vintf: Bump vendor.oplus.hardware.cwb to V2
As seen in OOS 16.0.2.

Change-Id: Ibda54dc941a5810f9803afabb3869ff5f980e1ab
2026-01-20 14:33:23 +01:00
Bruno Martins
d83a84ebb1 sepolicy: qti: Adapt rules after NXP NFC property relabeling
Change-Id: I44513adf816d8783da44f8d4b5d47e44c44b2670
2026-01-20 14:33:23 +01:00
basamaryan
c6a79c52fd sepolicy: qti: Drop duplicated wakeup nodes
See: Id2111f398cd1c7a02fa0262676314188e08c79e7
     Id45019cdd8ff6b1e4e60ba8c742956aa5f890ff3
Change-Id: Iad73a8abbb96a72cea03952408d20dbbe61de161
2026-01-20 14:33:23 +01:00
grepfox
4cc3e7943e sepolicy: qti: Label lexus wakeup nodes
Change-Id: Ic40add2057b008ba19a567c7361778230be96964
2026-01-20 14:33:23 +01:00
LuK1337
7f38220274 fixup! sepolicy: qti: Label corvette wakeup nodes
wakeup nodes are LC_ALL=C sorted.

Change-Id: Id41b690828d8fa1aa729688f4079c576269ab90f
2026-01-20 14:33:23 +01:00
LineageOS Infra
91c90c1342 Automatic translation import
Change-Id: Id59722076a2b9d1abc2de913c996ebf08a25db63
2026-01-20 14:33:23 +01:00
chandu078
ad122eac26 uah-client: Add missing stub symbols
Change-Id: I890f2566a8ad975a5b834046b73633dea5703913
2026-01-20 14:33:23 +01:00
chandu078
40be66bfb5 sepolicy: qti: Label corvette wakeup nodes
Also sort labels for wakeup nodes.

Change-Id: Iac6ba514e7b2236e1e9c3c1063a99c372acdb360
2026-01-20 14:33:23 +01:00
LineageOS Infra
2c50925ba0 Automatic translation import
Change-Id: I1eba54c14c2dac35bc8d7ec2457e70ca499694b5
2026-01-20 14:33:23 +01:00
LuK1337
e62303931d doze: Fix ClassCastException on pickup pref change
Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/9633
Change-Id: I6662f7a11fd7aae4df86e534b1900ea1b04281f5
2026-01-20 14:33:23 +01:00
chandu078
69680e9415 oplus-fwk: Add OsenseResClient and OplusUIFirstManager stubs
Required for OOS 16.0.0 blobs.

Change-Id: Ie3921eb1f62771885f69ad76a570def89e9286ac
2026-01-20 14:33:23 +01:00
Bruno Martins
92ebe070ab doze: Use new method to listen for preference changes
Usage of addOnSwitchChangeListener(OnCheckedChangeListener) is
deprecated. The Javadoc explicitly says:

  Use setOnPreferenceChangeListener(OnPreferenceChangeListener) instead.

Change-Id: I71e0e3f86ff339a312cac1e09106f6d5d15b7e43
2026-01-20 14:33:23 +01:00
Bruno Martins
e7b724bcdd oplus-fwk: Stub NetworklessManager
Nonsense required for OOS 16.0.1 blobs.

Change-Id: Ic031af55b55b216679803116198a3d15d1fc31e4
2026-01-20 14:33:23 +01:00
Bruno Martins
3cfc3da1fb KeyHandler: Modernize ButtonSettings
Fully convert to AndroidX fragments and stop overriding
OnOptionsItemSelected(IMenuItem).

Change-Id: I56261b2bfd47bd5dd75ca52cb463e76309a14dce
2026-01-20 14:33:23 +01:00
Bruno Martins
f6b76fd2b1 KeyHandler: Switch to SwitchPreferenceCompat
Change-Id: Ib4bb4f4dab43555e24828018913ae9690c6afe88
2026-01-20 14:33:23 +01:00
Michael Bestas
d06ec4e02d doze: Convert to SwitchPreferenceCompat
Change-Id: Ic1cbaba37d499da1855af9c3930f2df426e2d3af
2026-01-20 14:33:23 +01:00
Bruno Martins
3e1566fc71 sepolicy: qti: Label /dev/sec_dev
Change-Id: I770bf6d8b69e937bbda75db3a59e39c308368c82
2026-01-20 14:33:23 +01:00
anky894
23ce8c26e0 oplus: Introduce dummy liboplus-uah-client
Change-Id: Ifc628f858a38ea9976a5796fdf8a9193e3281524
2026-01-20 14:33:23 +01:00
Bruno Martins
0dc562da5b interfaces: Update vendor.oplus.hardware.olc2 to V3
Change-Id: Ib79e5b332948d65b7581f1960f1d5e0f30bb1dcb
2026-01-20 14:33:23 +01:00
Bruno Martins
89c44a7134 interfaces: Update vendor.oplus.hardware.olc2 to V2
Change-Id: If47efd073e0a9b06a041cd71ab6b835add894176
2026-01-20 14:33:23 +01:00
Bruno Martins
67826581ba interfaces: Add vendor.oplus.hardware.olc2 V1
Change-Id: I0872fdf9ca2e5987d54ef5e851be1aea8c620f6d
2026-01-20 14:33:23 +01:00
Bruno Martins
da408f0fae sepolicy: qti: Label battery gauge daemon
It has the same label as wlchgd in OOS:

odm/etc/selinux/precompiled_file_contexts:/(vendor|odm)/bin/hw/gauged u:object_r:wlchg_exec:s0
odm/etc/selinux/precompiled_file_contexts:/(vendor|odm)/bin/hw/wlchgd u:object_r:wlchg_exec:s0

Change-Id: Ic1d5fe8bac3459cb45053cc92e4b2e7881821ca6
2026-01-20 14:33:23 +01:00
LineageOS Infra
221a68029a Automatic translation import
Change-Id: I19dd56c3567497e9aea2b5940acc10afc72e1115
2026-01-20 14:33:23 +01:00
Bruno Martins
5cb4faad74 interfaces: Update IOplusProject to V3
Change-Id: Ibfb3338f73ad24f480a4c590fc095cf640dcec85
2026-01-20 14:33:23 +01:00
Bruno Martins
b680eae9a3 interfaces: Update IOplusProject to V2
Change-Id: I628f7aa3ed07b5c02fd0a07a3e41a3cfb7291bb5
2026-01-20 14:33:23 +01:00
Bruno Martins
ecae06e225 interfaces: Introduce vendor.oplus.hardware.stability.oplus_project V1
Change-Id: Ia2337de26393070367076a04acbf0cbb87291206
2026-01-20 14:33:23 +01:00
Bruno Martins
dae91ed770 vintf: Bump ISubsys and ISubsysRadio aidl versions
As required for OOS 16:

ERROR: files are incompatible: The following instances are in the device manifest but not specified in framework compatibility matrix:
    vendor.oplus.hardware.subsys_interface.subsys.ISubsys/default (@5)
    vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot1 (@8)
    vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot2 (@8)

Change-Id: I2511ea82ccce5a4f219a38e87b892c06445c1226
2026-01-20 14:33:23 +01:00
chandu078
975e175c8c vintf: Bump vendor.oplus.hardware.charger to V9
As seen in OOS 16.

Change-Id: Ife1c267191591815c0067fe8fe401f40de6cc0bc
2026-01-20 14:33:23 +01:00
Bruno Martins
b7529516af interfaces: Add AIDL and HIDL IDisplayPanelFeature
Change-Id: I01a16fbb24ddbc02460788edfc05b83410f6a36e
2026-01-20 14:33:23 +01:00
Marc Bourgoin
f7e54b5bb7 sepolicy: Remove commonized ST NFC labels
They are moved to qcom sepolicy_vndr

Change-Id: Ifdc5a3a4a51e172de4c685a833c2da4ca114d5ce
2026-01-20 14:33:23 +01:00
inferno0230
02cdcb3595 Euicc: Add OnePlus 12R support
Change-Id: I36ce9a1cc828f4157f340e34e4ca1ff5bdaff1a1
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:33:23 +01:00
LuK1337
4787b5111f Euicc: Make JSON mappings more readable
Change-Id: I5e10327407962c8328ab73a6e5faee1da639c00d
2026-01-20 14:33:23 +01:00
LuK1337
c2ac80b26e Euicc: Make JSON mappings untranslatable
Change-Id: I438b90a69e55f62bd02c875a9a0ee40aa08d011b
2026-01-20 14:33:23 +01:00
DroidFreak32
d42835de19 eSimSwitcher: Restrict activity to primary profile only
This avoids the "Choose Profile" popup every time the activity
is started when Android for Work is set up on the device or when using
apps like Shelter.

Change-Id: I716176445e6a9d9f8877c651a8f5524bfcef48b3
2026-01-20 14:33:23 +01:00
Bruno Martins
0ec5c7ee17 eSimSwitcher: Support targets using SE
Co-authored-by: LuK1337 <priv.luk@gmail.com>
Change-Id: I8be990cd691b4ca84701f68c84ea0e807f22c647
2026-01-20 14:33:23 +01:00
Bruno Martins
8cbc195c1c Introduce eSIM switcher app
Icon taken from google/material-design-icons.

Co-authored-by: LuK1337 <priv.luk@gmail.com>
Change-Id: I28216910c39f4ee690d2e69d39158413422bfe8d
2026-01-20 14:33:23 +01:00
inferno0230
34bdc76ed5 livedisplay: Use PWM pulse for IAntiFlicker if available
Change-Id: I03331c4dc123a95b0882318af48aa4f22e0d13b7
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:33:23 +01:00
inferno0230
dc68150e61 kernel-headers: Add PANEL_IOCTL_{GET,SET}_PWM_PULSE
Change-Id: Ia81c01fd2eb707e06d1cf40f90585f2da01fe934
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:33:23 +01:00
LuK1337
11a489b80b Euicc: Migrate to privapp_allowlist
Change-Id: I52aa7e1d8a158be2a252d2949f5207551a1a4070
2026-01-20 14:33:23 +01:00
LineageOS Infra
ea27d5578c Automatic translation import
Change-Id: I1cc36db194d97b53ce1582b92ae864b7e6da4c5d
2026-01-20 14:33:23 +01:00
LuK1337
2c2c666e79 Pen: Support Goodix BT MAC prefix
add device 2: /dev/input/event9
  bus:      0005
  vendor    22d9
  product   386a
  version   0101
  name:     "OnePlus Pencil Pro Mouse"
  location: "XX:XX:XX:XX:XX:XX"
  id:       "f8:6f:de:XX:XX:XX"
  version:  1.0.1
  events:
    KEY (0001): BTN_MOUSE             BTN_RIGHT             BTN_MIDDLE
    REL (0002): REL_X                 REL_Y                 REL_WHEEL             REL_WHEEL_HI_RES
    MSC (0004): MSC_SCAN
  input props:
    <none>

Change-Id: Iebff07ee1a7fc34fc3cd806d9dc00a88f26688a7
2026-01-20 14:33:23 +01:00
LuK1337
0841cef5b7 Pen: Support Maxeye vendor ID
add device 4: /dev/input/event12
  bus:      0005
  vendor    330a
  product   0001
  version   0101
  name:     "OPPO Pencil 2"
  location: "XX:XX:XX:XX:XX:XX"
  id:       "c0:87:06:XX:XX:XX"
  version:  1.0.1
  events:
    KEY (0001): KEY_F21
    MSC (0004): MSC_SCAN
  input props:
    <none>

Change-Id: I89fff6e3cc24d159bd72175fb078286194016786
2026-01-20 14:33:23 +01:00
LuK1337
70c27d3906 Pen: Simplify stylus identification
Change-Id: Ica177eab3a1b1e9fe4f63a3f2eda7afd5e44cd7e
2026-01-20 14:33:23 +01:00
inferno0230
dda94bb591 sepolicy: qti: Label oplus,ufcs_protocol wakeup node
As seen on OnePlus Ace 2 Pro (xigua)

Change-Id: Icc04b17df095d8c8f5360551573129237cc3f724
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:33:23 +01:00
LuK1337
cf4c32a0d2 sensors: Skip first fp state event
We don't want to report initial state as otherwise that might result in
unwanted AOD UDFPS icon illumination after locking the device.

Change-Id: I4b595fcd0013b62c7d22a97e0243b39b5f1dcb16
2026-01-20 14:33:23 +01:00
LuK1337
7e77774f6d Pen: Get rid of location permission
https://developer.android.com/develop/connectivity/bluetooth/bt-permissions#assert-never-for-location

Change-Id: Ied5bd77a692a459cd25def85860ae6b940238879
2026-01-20 14:33:23 +01:00
LuK1337
85030c32bc Pen: Wait up to 5s for BLE scanner to be available
I'm too lazy to do this properly, this much easier and not like we have
UI to worry about.

Change-Id: If678fa861c9c25b159dbea4a8429777a4665ab51
2026-01-20 14:33:23 +01:00
LuK1337
efcb0981b3 folio-daemon: Remove unwanted event count check
No idea what was the point of it, but it prevents us from listening to
sensor events when device is asleep.

Change-Id: Id7ce79e8cce051256ee15d8b8f342726af085976
2026-01-20 14:33:23 +01:00
LuK1337
d219e9dab7 folio-daemon: Fix ALooper_pollOnce() return value check
Fixes: e9f090f ("folio-daemon: PollOnce instead of PollAll")
Change-Id: I651a1614c85d0729f960a7dc524b45118d6de932
2026-01-20 14:33:23 +01:00
Christian Hoffmann
d72f26d697 folio-daemon: Do not use batching for hall sensor
* hallMinDelay is 0, so just drop fetching it
* Using batching wakes up the system so frequently and
* unnecessarily that it never allowed deep sleep
* Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/8261

Change-Id: I597676b2dc93ab5581442f8c74734e18ff7217e3
2026-01-20 14:33:23 +01:00
LuK1337
30af5429c8 sepolicy: qti: Allow folio_daemon to find virtual_device_native_service
10-03 16:43:17.001   611   611 E SELinux : avc:  denied  { find } for pid=6977 uid=1000 name=virtualdevice_native scontext=u:r:folio_daemon:s0 tcontext=u:object_r:virtual_device_native_service:s0 tclass=service_manager permissive=0

Change-Id: I4900e1649d6e93d7eefa2c1027f362d1109fdf60
2026-01-20 14:33:23 +01:00
LuK1337
00bdb4360e Pen: Support overriding peak refresh rate when pen is connected
Change-Id: Ic65abaeb124613f9251905404eb77b67a63e28f1
2026-01-20 14:33:23 +01:00
LuK1337
b7f4ffe60f sepolicy: qti: Add sepolicy for folio-daemon
Change-Id: I72294055d6dfa548c50ba9be5a842aba8e86e709
2026-01-20 14:33:23 +01:00
LuK1337
bf6353c94d folio-daemon: Migrate to SPDX license header
Change-Id: If31c35027d24cba99833f48e05bf32e9e5ef32a0
2026-01-20 14:33:23 +01:00
LuK1337
9e1ddd8dff folio-daemon: Run clang-format
Change-Id: Ie874df9fa83b923e113fb47c56e257655c398c2b
2026-01-20 14:33:23 +01:00
LuK1337
3ab7d3e54c folio-daemon: Add init rc
Change-Id: Ic8e4b1956b3d5f47bd05a04db0edb69d54380137
2026-01-20 14:33:23 +01:00
LuK1337
1a5f653c9a folio-daemon: Move to /system_ext
Change-Id: Ib2d5dba4197fb8499cb778e41ef0fe30cb8db012
2026-01-20 14:33:23 +01:00
Christian Hoffmann
3205e0b0f3 folio-daemon: Explicity request wakeup version of hall sensor
Change-Id: Iafd2c2cc5afc1ae6b1354ad6bbeb3b3f95bfa3ee
2026-01-20 14:33:23 +01:00
LuK1337
7192398f65 folio-daemon: Flip sensor event data check
Change-Id: I5fe3969500f2f72308741c299b0a09ac8152f973
2026-01-20 14:33:23 +01:00
LuK1337
0b4cc238ab folio-daemon: Update sensor type
0x010003fe) bu52053nvx Oplus Hall Effect Sensor Wakeup | ROHM            | ver: 393228 | type: qti.sensor.hall_effect(33171002) | perm: n/a | flags: 0x00000003

Change-Id: Id6887fe8651758530e6ca2225f26743396e61195
2026-01-20 14:33:23 +01:00
Michael Bestas
128d956db2 folio-daemon: Convert Android.mk to bp
Change-Id: I52813cd047f685db97f9994d81cd28225a2c1b10
2026-01-20 14:33:23 +01:00
Christian Hoffmann
394aa2e793 folio-daemon: PollOnce instead of PollAll
* Fixes build error.

Change-Id: I62019c3116a3ee697923595904f1d66d6842957b
2026-01-20 14:33:23 +01:00
Andrew Lehmer
14f7c432cb folio-daemon: Avoid UAF with stale sensor handle
It is possible for sensor handles retrieved using
ASensorManager_getDefaultSensor() to become stale if the underlying
binder connection to the sensor service gets reset. This can be
triggered by ASensorManager_createEventQueue(), so any sensor handle
retrieved prior to this call may become stale, resulting in a use-after-
free when the handle is eventually registered with the queue. To avoid
this, the event queue is created before retrieving or registering the
sensor.

Bug: 150225255
Test: No longer crashes with proof-of-concept on Pixel 2 XL.
Change-Id: I243f6c68c734af3eb5488855d965a894b5fb99e5
2026-01-20 14:33:23 +01:00
Jiyong Park
af5a26eb25 folio-daemon: Disable modules that can't be built in PDK
Modules that can't be built in PDK are disabled when TARGET_BUILD_PDK is
true

Bug: 71361051
Test: lunch aosp_walleye-userdebug
PDK_FUSION_PLATFORM_ZIP=vendor/pdk/walleye/walleye-userdebug/platform/platform.zip m -j

Change-Id: I2cc7ab6d667daab7d3566baf8a9b473cafc4e452
2026-01-20 14:33:23 +01:00
Lennart Wieboldt
3f4a69a1dd folio-daemon: Remove LOCAL_CLANG := true
Clang is the default compiler since nougat.

Change-Id: I565e25f9f688a979eac41de0eee4a88b24099098
Signed-off-by: Lennart Wieboldt <lennart.1997@gmx.de>
2026-01-20 14:33:23 +01:00
Chih-Hung Hsieh
f8ec485a1c folio-daemon: Use -Werror
* Remove unused local variable.

Bug: 66996870
Test: build with WITH_TIDY=1
Change-Id: I96228277b9c81b71e73e4e376d86cdea6cbcb647
2026-01-20 14:33:23 +01:00
Dan Albert
8a602bf650 folio-daemon: Add missing includes.
Change-Id: I74ce25b3b5c918e371140b91f82ec00ff571f9fe
Exempt-From-Owner-Approval: trivial cleanup
Test: mma
Bug: None
2026-01-20 14:33:23 +01:00
Jeff Vander Stoep
f90a565d15 folio-daemon: Move to system
Remove Treble violations.

Bug: 36867326
Bug: 62387246
Test: loaded on taimen, checked dmesg, and tested daemon with magnet
Change-Id: I4662b41206b94cae6ac9843b5dc7e1452003c63c
2026-01-20 14:33:23 +01:00
Andrew Lehmer
1b685157fa folio-daemon: Retry slowly on failure
Bug: 38001818
Test: loaded on taimen
Change-Id: I3f5a8cbf0faca3b5d027dcd74f1b16de80fdbee2
2026-01-20 14:33:23 +01:00
Andrew Lehmer
77bf539b3b folio-daemon: Exit when poll returns zero events
Bug: 37402669
Test: loaded on walleye, issued `adb shell stop`, checked `top`
Change-Id: I7d43cab39809b6b156eb26195df2c913991e5c96
2026-01-20 14:33:23 +01:00
Andrew Lehmer
98429e3f13 folio-daemon: Improve logging for debugging
Bug: 37402669
Test: loaded on walleye
Change-Id: I9cfd071158386d3eb15a5b81656b09452c7fed15
2026-01-20 14:33:23 +01:00
Andrew Lehmer
f0a0026ed3 oplus: Add support for folio cases
Bug: 35243564
Test: Used magnet to wake and lock device. Also tested during suspend.
Change-Id: I4b819e12cc23a3d7a8ce048e208c15eac4f8d6c5
2026-01-20 14:33:23 +01:00
LineageOS Infra
55e999831a Automatic translation import
Change-Id: I9d71722a8e84ba8d1503995031ba92beaba044ef
2026-01-20 14:33:23 +01:00
dianlujitao
ff1be84372 sepolicy: qti: Allow rules for subsystem_daemon
Change-Id: I22040ac0d0ab70f32de07a5ac451d41f045433a9
2026-01-20 14:33:23 +01:00
dianlujitao
c5ae56b117 sepolicy: qti: Fix wrong macro usages
Change-Id: I6e6a52ecf8fb223fc87c51bb8fa191bd1115a3e2
2026-01-20 14:33:23 +01:00
dianlujitao
753f235c4a sepolicy: qti: Support both context prefixes in oplusreserve partition
Also apply some minor clean-ups while at it.

Change-Id: I7676bf126099222ef56b2f639aba1ab62f662361
2026-01-20 14:33:23 +01:00
Bruno Martins
3bac36d457 sepolicy: qti: Let qcril look into /mnt/vendor/oplusreserve
Change-Id: Iaa6425e662c83b660af9a3bf1371faa0faf494b3
2026-01-20 14:33:23 +01:00
dianlujitao
a049bb7efd sepolicy: qti: Allow init to label vendor_reserve_partition
[    0.983556] init: Running restorecon...
[    0.989819] selinux: SELinux: Could not set context for /dev/block/platform/soc/1d84000.ufshc/by-name/oplusreserve2:  Permission denied
[    0.989819] audit: type=1400 audit(10810748.011:9): avc:  denied  { relabelto } for  pid=1 comm="init" name="oplusreserve2" dev="tmpfs" ino=35 scontext=u:r:init:s0 tcontext=u:object_r:vendor_reserve_partition:s0 tclass=lnk_file permissive=0

Change-Id: I5b356016e6f5e2b2564179eb2b87bf99c4ee78e2
2026-01-20 14:33:23 +01:00
dianlujitao
d4f9134f96 sepolicy: qti: Label wireless charging device and daemon
Change-Id: I3d56dd86eecdfb18aba55e64e4b7d362441b1935
2026-01-20 14:33:23 +01:00
Bruno Martins
1ff60bfff0 sepolicy: qti: Allow touchDeamon to stop itself
As seen on devices without OplusTouch support:

[   14.155867] init: Unable to set property 'ctl.stop' from uid:0 gid:0 pid:1991: Invalid permissions to perform 'stop' on 'touchDaemon'
[   14.155902] type=1107 audit(1758323930.135:13): uid=0 auid=4294967295 ses=4294967295 subj=u:r:init:s0 msg='avc:  denied  { set } for property=ctl.stop$touchDaemon pid=1991 uid=0 gid=0 scontext=u:r:oplus_touchdaemon:s0 tcontext=u:object_r:ctl_stop_prop:s0 tclass=property_service permissive=0'

Change-Id: Iacc073b0b74713c268966c69480cf02d543d395a
2026-01-20 14:33:23 +01:00
LuK1337
859abb5626 sepolicy: qti: Allow camera HAL to find osense_service
09-19 22:25:35.045   925   925 E SELinux : avc:  denied  { find } for pid=1634 uid=1047 name=osensemanager scontext=u:r:hal_camera_default:s0 tcontext=u:object_r:osense_service:s0 tclass=service_manager permissive=0

Change-Id: I45f432e8378c726ef0026e5a1c9456b36b6929e1
2026-01-20 14:33:23 +01:00
dianlujitao
05e3cba485 sepolicy: qti: Allow eSIM HAL to access /mnt/vendor/oplusreserve
Change-Id: I07b964681f472d4d5c38be3d5aa1afd8604a1642
2026-01-20 14:32:54 +01:00
dianlujitao
dba2aef92a sepolicy: qti: Allow vendor.lineage.touch to access binder
[    4.389706] type=1400 audit(1758283865.674:53): avc:  denied  { call } for  comm="servicemanager" scontext=u:r:servicemanager:s0 tcontext=u:r:hal_lineage_touch_default:s0 tclass=binder permissive=0

Change-Id: I338d3fd5cb80035905c6c509eb53da61a2aa0338
2026-01-20 14:32:54 +01:00
LuK1337
15e343047f sepolicy: qti: Let vendor_init set vendor_camera_prop
Required for erhai's vendor.qti.camera.provider-service_64.rc:

on property:sys.boot_completed=1
    setprop vendor.oplus.camera.cam0.count 0
    setprop vendor.oplus.camera.cam3.count 0
    setprop vendor.oplus.camera.error.camlist 0

Change-Id: I7b9c50f5532a8c809b2061f8c6eedc08d7a18802
2026-01-20 14:32:54 +01:00
dianlujitao
9f813549e9 sepolicy: qti: Label thermal engine prop
Change-Id: I14766b69fd83031083730a445c958a5e1027bd34
2026-01-20 14:32:54 +01:00
inferno0230
d7b9c4c999 sepolicy: qti: Label more SM8650 wakeup nodes
Needed by OnePlus Pad 2 (caihong)

Change-Id: Ia134dfadb0d05ebe2728c1899534ccd85930f3d2
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:32:54 +01:00
LineageOS Infra
31a56b12f8 Automatic translation import
Change-Id: I471279ee8af9e2d3c7c95f572bbd809d680a0535
2026-01-20 14:32:54 +01:00
LuK1337
efa692f969 readme: Remove USE_BSG_FRAMEWORK variable
See: 18ef7dd547
Change-Id: I874e5cf669a5f068cc8b8cf058e6e26c8401d883
2026-01-20 14:32:54 +01:00
LuK1337
bb9a27add9 interfaces: Add vendor.oplus.hardware.urcc V1
Change-Id: I1b483913586c45717d86f3faa036d5afe3077858
2026-01-20 14:32:54 +01:00
kok-o3
e4aec89ee9 sepolicy: qti: Label SM7675 wakeup nodes
Change-Id: I0f7f1dec0f8f9da88afd17233898ceb5c4a23ec5
2026-01-20 14:32:54 +01:00
inferno0230
526648fcf6 sepolicy: qti: Label SM7550 charging sysfs path
Change-Id: Ia79079f3df34714e5a8f9294d3db6048552609e6
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:32:54 +01:00
LuK1337
f1003ce752 sepolicy: qti: Allow vendor_init to set vendor_fingerprint_prop
Change-Id: Icc898bba9d8a06b79e1cfcf34412871471a9bdf7
Signed-off-by: inferno0230 <mail@inferno0230.in>
2026-01-20 14:32:54 +01:00
dianlujitao
3dedf9c959 sepolicy: qti: Move proc_horae to vendor
This fixes booting AOSP GSIs.

Fixes: 8acb73ff6a ("sepolicy: qti: Add support for horae service")
Change-Id: Ica812bb31d6c60b4ec5f6837de7712bd0c275543
2026-01-20 14:32:54 +01:00
dianlujitao
9d4c72dc99 Euicc: Add China version support
Despite lack of native eSIM hardware, this enables managing removable
eUICCs through EuiccGoogle

Change-Id: I9d5a360dde85ede18761ff795641e199507ff688
2026-01-20 14:32:54 +01:00
LuK1337
234c545bec livedisplay: Use PWM turbo for IAntiFlicker if available
Change-Id: I4162f79c5309038dfff1bd00f2ca8a726c7eb206
2026-01-20 14:32:54 +01:00
LuK1337
e2162b65ed kernel-headers: Add PANEL_IOCTL_{GET,SET}_PWM_TURBO
Change-Id: I0c63693be15a09baa582d14113b642e086e94d6e
2026-01-20 14:32:54 +01:00
grep
cbe70f6a98 vintf: Bump vendor.oplus.hardware.charger to V8
lexus shipped with V8.

Change-Id: I0b4733fcb7f5e3ac0834b8526e1ec5a99fd0e8c3
2026-01-20 14:32:54 +01:00
Bruno Martins
d72e165e4f interfaces: Mark all aidl interfaces as system_ext_specific
Change-Id: I62d8099cae1d3c2cbe98d5bc514a0713eb84cbe9
2026-01-20 14:32:54 +01:00
Bruno Martins
8d5d48166e interfaces: Update ICharger all the way to V8
V7 adds GET_RX_DISABLE_STATUS and SET_RX_DISABLE enum entries on top of
V6 and V8 finally adds only GET_BATTERY_SEC_IC_TEST_STATUS.

Change-Id: I134bac4ffc536280dbb778a4a349943b67c175dc
2026-01-20 14:32:54 +01:00
Bruno Martins
ff7dfce91f interfaces: Bump ICharger directly to V5
Looks like V4 never existed.

Change-Id: I1999da190461411913e98d98c258a2825fb039d5
2026-01-20 14:32:54 +01:00
Bruno Martins
01ac349af0 interfaces: Update ICharger to V3
Change-Id: Ife15bb3b9f51dbc83bb975a7603f47985e1178bd
2026-01-20 14:32:54 +01:00
Bruno Martins
1a4ac49ba1 interfaces: Update ICharger to V2
Change-Id: I2ffe384dad647c3e115d6bb1d2e7d85e94d720e5
2026-01-20 14:32:54 +01:00
Bruno Martins
05339ef6d9 interfaces: Add vendor.oplus.hardware.charger V1
Change-Id: Ia3916a80e106c3b92428b1239c0fae90b8a5eaf3
2026-01-20 14:32:54 +01:00
Bruno Martins
823b03ee9c sepolicy: qti: Add inital eSIM support
Change-Id: Iae2d3c17a6eb5a9b1c71198c8ac861ad4e5f85d5
2026-01-20 14:32:54 +01:00
Bruno Martins
b22e76db0f sepolicy: qti: Update compatibility mapping files
Change-Id: I6d10fa03042e4f360a494a7eb2c9ffd0502c86a4
2026-01-20 14:32:54 +01:00
chandu078
0782313698 sepolicy: qti: Add support for horae service
Service required for thermal management, as it reports and updates shell
temperature to /proc/shell-temp.

Change-Id: I02e2ddeda461cbb2ead1348edc6ebf57b8f7fdde
2026-01-20 14:32:54 +01:00
LuK1337
a1e3f9b235 oplus: Get rid of in_ prefix
Change-Id: Ibdafd315098ccc54ec19f298bdb28cb894017489
2026-01-20 14:32:54 +01:00
pjgowtham
41973058e6 Introduce vendor.oplus.hardware.performance-service
Dummy service named differently from the stock one to avoid conflicts.

This can be used on devices that do not include CPU ricing, but still
require the service to register for camera and prebuilt audio stack to
actually work.

Change-Id: I41087aefe9af57e7a1161a3a71ab3b9e849925f2
2026-01-20 14:32:54 +01:00
pjgowtham
325c2ff0ef interfaces: Add vendor.oplus.hardware.performance V1
Change-Id: I5a56cdc826495e1770905e3286bcbc2bef0cf2a3
2026-01-20 14:32:54 +01:00
LineageOS Infra
24045995ae Automatic translation import
Change-Id: I433a0975161c90f6e9cec98e824f56c3c80e39a1
2026-01-20 14:32:54 +01:00
Bruno Martins
62a590a3e0 usb_compositions: Restore QCOM VID/PID combos for diag
This re-allows installing Qualcomm drivers for accessing diag,
serial_cdev, rmnet (and others) devices. Needed for QPST Flash Tool.

Change-Id: Iafe2236bb63adb005bfecae46887c58c69db8ca2
2026-01-20 14:32:54 +01:00
dianlujitao
0ce9e4d22e KeyHandler: Populate tri-state-key state on boot
Change-Id: I11e785b5824d581f748e038f292c8846b2a13a0f
2026-01-20 14:32:54 +01:00
LuK1337
2321cf482d sepolicy: qti: Add system_oplus_radio_prop to *.ignore.cil
Change-Id: If943028a54f7a7f32f289bf080f6565052bdaf40
2026-01-20 14:32:54 +01:00
pjgowtham
f565d7e6c2 sepolicy: qti: Let qti secure_element rw /dev/nq-nci
vendor.qti.secu: type=1400 audit(0.0:2346): avc:  denied  { getattr }
for  path=/dev/nq-nci dev=tmpfs ino=1371
scontext=u:r:hal_secure_element_default:s0
tcontext=u:object_r:nfc_device:s0 tclass=chr_file permissive=1

Spotted on ferrari.

Change-Id: I8869fffae3cc6028b6b8ff009bd84108e2a53ada
2026-01-20 14:32:54 +01:00
pjgowtham
14f773f0bc fingerprint: Shim property_get() as well
On OnePlus Nord CE3 (ziti), shimming `__system_property_get()` is not
enough. Without this change, `vendor.fingerprint.cali` is set to 0 when
`ro.boot.vbmeta.device_state` is unset.

Test: Ensure adb logcat | grep "lcd LockState" does not show up as NULL
      Ensure adb shell getprop vendor.fingerprint.cali is 1
Change-Id: I913f00db1542a28aaaa11dba93fcce67b39717bf
2026-01-20 14:32:54 +01:00
pjgowtham
1998146e2f sepolicy: qti: Label awinic vibrator sysfs for ziti
Change-Id: I6543983b6de8f7852015ea6a304be9aa809dc65f
2026-01-20 14:32:54 +01:00
LuK1337
3dff3e1051 sepolicy: qti: oplusSensor -> oplus_sensor
Matches new AIDL naming style.

Change-Id: I93a22091f54df5c48d105bc82d51b90bcf1e59e3
2026-01-20 14:32:32 +01:00
pjgowtham
df2b12b0e2 sepolicy: qti: Label and add rules for oplusSensor AIDL
Change-Id: I451d7bf6bb110ed900ff5258cdcf6566945ab490
2026-01-20 14:32:32 +01:00
pjgowtham
a91b970b30 sepolicy: qti: Let vendor_hal_oplusSensor_default search /dev/block
Change-Id: I248bd96c9753a4c9f51643368a0a5f67d52729df
2026-01-20 14:32:32 +01:00
pjgowtham
11a12b9fdd sepolicy: qti: Let hal_oplus_charger_aidl rw /dev/oplus_chg
Change-Id: I222aed7542f5750a3fe2f062998237bc00d22a3a
2026-01-20 14:32:32 +01:00
pjgowtham
86ea694955 sepolicy: qti: Let hal_oplus_charger_aidl rw vendor_sysfs_battery_supply
Change-Id: I058aad89acba10eaae84734341d30d1efa8e4a2f
2026-01-20 14:32:32 +01:00
pjgowtham
176876bce6 sepolicy: qti: Update qseecom rules for fingerprint
Change-Id: I34cbd4642f1c03446d1e57da079e5e495c2326cc
2026-01-20 14:32:32 +01:00
pjgowtham
8552508a5f sepolicy: qti: Label goodix fingerprint property
W /system/bin/init: type=1107 audit(0.0:13): uid=0 auid=4294967295
ses=4294967295 subj=u:r:init:s0 msg='avc:  denied  { set } for
property=gf.debug.dump_data pid=1873 uid=1000 gid=1000
scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:default_prop:s0
tclass=property_service permissive=0'

Change-Id: I07acc42f6a5cba7e7b94f8473feb0540eee9096c
2026-01-20 14:32:32 +01:00
pjgowtham
9695a5684a sepolicy: qti: Let camera hal rw /proc/qcom_flash
On Ziti (OnePlus Nord CE 3), this seems necessary for the torchlight
function to work.

Change-Id: I37ac5d7a1578d939d61728e8292c47b2fa9d870d
2026-01-20 14:32:32 +01:00
pjgowtham
c976840bcd sepolicy: qti: Label wly wakeup nodes
wly / # cat /sys/devices/platform/soc/984000.i2c/i2c-5/5-003b/name
p9415-rx
wly / # cat /sys/devices/platform/soc/990000.i2c/i2c-6/6-004b/name
synaptics-s3908
wly / # cat /sys/devices/platform/soc/a84000.i2c/i2c-8/8-0028/name
sn-nci

Change-Id: I8aef0c21df2af86b06515ef609729c352770a260
2026-01-20 14:32:32 +01:00
pjgowtham
5768223b50 sepolicy: qti: Label ferrari wakeup nodes
ferrari / # cat /sys/devices/platform/soc/990000.i2c/i2c-5/5-004b/name
synaptics-s3908
ferrari / # cat /sys/devices/platform/soc/a84000.i2c/i2c-7/7-0028/name
sn-nci

Change-Id: Ia2af6499a912697694ee24f209726a974887545f
2026-01-20 14:32:32 +01:00
pjgowtham
b28da47d8b sepolicy: qti: Label lunaa/ziti wakeup nodes
lunaa / # cat /sys/devices/platform/soc/a84000.i2c/i2c-1/1-0008/name
st21nfc
lunaa / # cat /sys/devices/platform/soc/a94000.i2c/i2c-2/2-0038/name
fts
ziti / # ls /sys/devices/platform/soc/a94000.spi/spi_master/spi1/spi1.0/
driver           fts_rw_reg  supplier:18200000.rsc:rpmh-regulator-ldoc12
driver_override  input       supplier:18200000.rsc:rpmh-regulator-ldoc3
fts_dump_reg     modalias    supplier:f000000.pinctrl
fts_esd_check    of_node     supplier:regulator.36
fts_fw_version   power       supplier:regulator.47
fts_hw_reset     statistics  uevent
fts_irq          subsystem   wakeup

Change-Id: I2933a1fb695f72cd859d6654947ac37bd7f3f77f
2026-01-20 14:32:32 +01:00
421 changed files with 14624 additions and 1161 deletions

View File

@@ -1 +0,0 @@
../../build/soong/scripts/system-clang-format

13
.clang-format Normal file
View File

@@ -0,0 +1,13 @@
BasedOnStyle: Google
Standard: Cpp11
AccessModifierOffset: -2
AllowShortFunctionsOnASingleLine: Inline
ColumnLimit: 100
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
IncludeBlocks: Preserve
IndentWidth: 4
ContinuationIndentWidth: 8
PointerAlignment: Left
TabWidth: 4
UseTab: Never

13
.github/workflows/build/action.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: build
runs:
using: composite
steps:
- name: Install dependencies
shell: bash
run: pip install pre-commit
- name: Lint
shell: bash
run: pre-commit run --all

38
.github/workflows/gerrit.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: gerrit checks
on:
workflow_dispatch:
inputs:
ref:
type: string
gerrit-ref:
type: string
change:
type: string
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: lineageos-infra/fetch-gerrit-change@main
with:
gerrit-ref: ${{ inputs.gerrit-ref }}
ref: ${{ inputs.ref }}
- name: Check if build/action.yml exists
id: check
run: |
if [ -f ./.github/workflows/build/action.yml ]; then
echo "run=1" >> "$GITHUB_OUTPUT"
fi
- name: Build
if: ${{ steps.check.outputs.run }}
uses: ./.github/workflows/build
- uses: lineageos-infra/gerrit-vote@main
if: ${{ steps.check.outputs.run && always() }}
with:
auth: ${{ secrets.GERRIT_VOTE_CREDS }}
change: ${{ inputs.change }}
ref: ${{ inputs.ref }}

20
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,20 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v21.1.8
hooks:
- id: clang-format
types_or: [c, c++]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.15.0
hooks:
- id: pretty-format-kotlin
args: [--autofix, --ktfmt, --ktfmt-style=kotlinlang]

View File

@@ -1,5 +1,5 @@
//
// SPDX-FileCopyrightText: 2022-2025 The LineageOS Project
// SPDX-FileCopyrightText: 2022-2026 The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
@@ -23,3 +23,10 @@ prebuilt_hidl_interfaces {
"vendor.pixelworks.hardware.feature@1.0::IIrisFeature",
],
}
prebuilt_hidl_interfaces {
name: "hidl_zeku_explorer_interface",
interfaces: [
"vendor.zeku.hardware.explorer@1.0::IMmsProvider",
],
}

View File

@@ -0,0 +1,39 @@
//
// Copyright (C) 2024-2025 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
android_app {
name: "DSPVolumeSynchronizer",
certificate: "platform",
srcs: ["src/**/*.java"],
platform_apis: true,
privileged: true,
system_ext_specific: true,
static_libs: [
"androidx.core_core",
"SettingsLib",
],
required: [
"privapp-permissions-dspvolume",
"config-dspvolume",
],
}
prebuilt_etc {
name: "privapp-permissions-dspvolume",
relative_install_path: "permissions",
src: "privapp-permissions-dspvolume.xml",
system_ext_specific: true,
filename_from_src: true,
}
prebuilt_etc {
name: "config-dspvolume",
relative_install_path: "sysconfig",
src: "config-dspvolume.xml",
system_ext_specific: true,
filename_from_src: true,
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.dspvolume.xiaomi"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:label="@string/app_name"
android:persistent="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
<receiver
android:name=".BootReceiver"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter android:priority="999">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name=".VolumeListenerService" />
</application>
</manifest>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<config>
<allow-in-power-save package="org.lineageos.dspvolume.xiaomi" />
<hidden-api-whitelisted-app package="org.lineageos.dspvolume.xiaomi" />
</config>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<privapp-permissions package="org.lineageos.dspvolume.xiaomi">
<permission name="android.permission.INTERACT_ACROSS_USERS" />
<permission name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<permission name="android.permission.MODIFY_AUDIO_SETTINGS" />
<permission name="android.permission.RECEIVE_BOOT_COMPLETED" />
</privapp-permissions>
</permissions>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App Name -->
<string name="app_name">DSP Volume Synchronizer</string>
</resources>

View File

@@ -0,0 +1,16 @@
package org.lineageos.dspvolume.xiaomi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
if (context == null) {
return;
}
context.startService(new Intent(context, VolumeListenerService.class));
}
}

View File

@@ -0,0 +1,28 @@
package org.lineageos.dspvolume.xiaomi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.Log;
import android.os.Bundle;
public class VolumeListenerReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (context == null) {
return;
}
if(intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_TYPE", 0) == AudioManager.STREAM_MUSIC) {
AudioManager audioManager = context.getSystemService(AudioManager.class);
int current = intent.getIntExtra(
"android.media.EXTRA_VOLUME_STREAM_VALUE",
0
);
audioManager.setParameters("volume_change=" + current + ";flags=8");
}
}
}

View File

@@ -0,0 +1,30 @@
package org.lineageos.dspvolume.xiaomi;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.IBinder;
import androidx.annotation.Nullable;
public class VolumeListenerService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.media.VOLUME_CHANGED_ACTION");
registerReceiver(new VolumeListenerReceiver(), intentFilter);
AudioManager audioManager = getSystemService(AudioManager.class);
int current = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
audioManager.setParameters("volume_change=" + current + ";flags=8");
return super.onStartCommand(intent, flags, startId);
}
}

View File

@@ -1,40 +1,17 @@
//
// Copyright (C) 2023 The LineageOS Project
//
// SPDX-FileCopyrightText: 2023-2025 The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
android_app {
phony {
name: "OplusEuicc",
srcs: ["src/**/*.kt"],
sdk_version: "current",
product_specific: true,
certificate: "platform",
privileged: true,
optimize: {
proguard_flags_files: ["proguard.flags"],
},
required: [
"org.lineageos.euicc.xml",
"hidden-api-whitelist-org.lineageos.euicc.xml",
"EuiccPolicy",
"EuiccPolicyOplus",
],
}
prebuilt_etc {
name: "org.lineageos.euicc.xml",
relative_install_path: "permissions",
filename: "org.lineageos.euicc.xml",
src: "org.lineageos.euicc.xml",
product_specific: true,
}
prebuilt_etc {
name: "hidden-api-whitelist-org.lineageos.euicc.xml",
relative_install_path: "sysconfig",
filename: "hidden-api-whitelist-org.lineageos.euicc.xml",
src: "hidden-api-whitelist-org.lineageos.euicc.xml",
runtime_resource_overlay {
name: "EuiccPolicyOplus",
product_specific: true,
}

View File

@@ -1,42 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023-2024 The LineageOS Project
SPDX-FileCopyrightText: 2023-2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.euicc">
<queries>
<package android:name="com.google.android.gms" />
<package android:name="com.google.android.gsf" />
<package android:name="com.google.android.euicc" />
<package android:name="com.google.android.ims" />
</queries>
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
<application
android:persistent="true"
android:usesNonSdkApi="true">
<receiver
android:exported="true"
android:name=".BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver
android:directBootAware="true"
android:exported="true"
android:name=".EuiccReceiver"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS">
<intent-filter>
<action android:name="com.google.android.euicc.action.PARTNER_CUSTOMIZATION"/>
</intent-filter>
</receiver>
</application>
package="org.lineageos.euicc.overlay.oplus">
<overlay android:targetPackage="org.lineageos.euicc"
android:isStatic="true" />
</manifest>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<hidden-api-whitelisted-app package="org.lineageos.euicc" />
</config>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<privapp-permissions package="org.lineageos.euicc">
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
</privapp-permissions>
</permissions>

View File

@@ -1,3 +0,0 @@
-keep class org.lineageos.euicc.* {
*;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 The LineageOS Project
SPDX-FileCopyrightText: 2023-2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="sim_illustration_lottie_mappings_json">{\"sim_illustration_lottie_mappings\":[{\"devices\":[\"OP594DL1\",\"OP595DL1\",\"OP5D55L1\"],\"illustration_lottie\":\"sim_illustration_lottie_bottom\"}]}</string>
<string name="sim_slot_mappings_json">{\"sim-slot-mappings\":[{\"devices\":[\"OP594DL1\",\"OP595DL1\",\"OP5D55L1\"],\"esim-slot-ids\":[1],\"psim-slot-ids\":[0]}]}</string>
<string name="sim_illustration_lottie_mappings_json" translatable="false">
{
\"sim_illustration_lottie_mappings\": [
{
\"devices\": [
\"OP591BL1\",
\"OP5929L1\",
\"OP594DL1\",
\"OP595DL1\",
\"OP5CF9L1\",
\"OP5D0DL1\",
\"OP5D2BL1\",
\"OP5D35L1\",
\"OP5D3BL1\",
\"OP5D55L1\"
],
\"illustration_lottie\": \"sim_illustration_lottie_bottom\"
}
]
}
</string>
<string name="sim_slot_mappings_json" translatable="false">
{
\"sim-slot-mappings\": [
{
\"devices\": [
\"OP594DL1\",
\"OP595DL1\",
\"OP5D35L1\",
\"OP5D3BL1\",
\"OP5D55L1\"
],
\"esim-slot-ids\": [
1
],
\"psim-slot-ids\": [
0
]
},
{
\"devices\": [
\"OP591BL1\",
\"OP5929L1\",
\"OP5CF9L1\",
\"OP5D0DL1\",
\"OP5D2BL1\"
],
\"esim-slot-ids\": [],
\"psim-slot-ids\": [
0,
1
]
}
]
}
</string>
</resources>

View File

@@ -1,22 +0,0 @@
/*
* Copyright (C) 2021 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.euicc
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
class BootCompletedReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "Received boot completed intent")
EuiccDisabler.enableOrDisableEuicc(context)
}
companion object {
private const val TAG = "OplusEuiccBootReceiver"
}
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright (C) 2021-2024 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.euicc
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.ApplicationInfoFlags
import android.util.Log
object EuiccDisabler {
private const val TAG = "OplusEuiccDisabler"
private val EUICC_DEPENDENCIES = listOf(
"com.google.android.gms",
"com.google.android.gsf",
)
private val EUICC_PACKAGES = listOf(
"com.google.android.euicc",
"com.google.android.ims",
)
private fun isInstalled(pm: PackageManager, pkgName: String) = runCatching {
val info = pm.getApplicationInfo(pkgName, ApplicationInfoFlags.of(0))
info.flags and ApplicationInfo.FLAG_INSTALLED != 0
}.getOrDefault(false)
private fun isInstalledAndEnabled(pm: PackageManager, pkgName: String) = runCatching {
val info = pm.getApplicationInfo(pkgName, ApplicationInfoFlags.of(0))
Log.d(TAG, "package $pkgName installed, enabled = ${info.enabled}")
info.enabled
}.getOrDefault(false)
fun enableOrDisableEuicc(context: Context) {
val pm = context.packageManager
val disable = EUICC_DEPENDENCIES.any { !isInstalledAndEnabled(pm, it) }
val flag = if (disable) {
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
} else {
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
}
for (pkg in EUICC_PACKAGES) {
if (isInstalled(pm, pkg)) {
pm.setApplicationEnabledSetting(pkg, flag, 0)
}
}
}
}

View File

@@ -1,21 +0,0 @@
/*
* Copyright (C) 2023 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.euicc
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
class EuiccReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "Received PARTNER_CUSTOMIZATION intent")
}
companion object {
private const val TAG = "OplusEuiccReceiver"
}
}

View File

@@ -22,113 +22,131 @@ import vendor.oplus.hardware.biometrics.fingerprintpay.IFingerprintPay
class IfaaService : Service() {
private var _fpPayService: IFingerprintPay? = null
private val fpPayServiceDeathRecipient = IBinder.DeathRecipient {
Log.i(LOG_TAG, "aidl FingerprintPay hal died, reset hal proxy!")
_fpPayService = null
}
private val fpPayServiceDeathRecipient =
IBinder.DeathRecipient {
Log.i(LOG_TAG, "aidl FingerprintPay hal died, reset hal proxy!")
_fpPayService = null
}
private val fingerprintManager by lazy { getSystemService(FingerprintManager::class.java)!! }
private val keyguardManager by lazy { getSystemService(KeyguardManager::class.java)!! }
private val windowManager by lazy { getSystemService(WindowManager::class.java)!! }
override fun onBind(intent: Intent) = object : IfaaManagerService.Stub() {
private val _supportBIOTypes by lazy {
when (SystemProperties.get(FP_TYPE_PROP, "")) {
"back", "side", "front" -> AUTH_TYPE_FINGERPRINT
"ultrasonic", "optical" -> AUTH_TYPE_OPTICAL_FINGERPRINT
else -> AUTH_TYPE_NOT_SUPPORT
}
}
override fun getSupportBIOTypes() = _supportBIOTypes
override fun startBIOManager(authType: Int) = when (authType) {
AUTH_TYPE_FINGERPRINT -> {
applicationContext.startActivity(
Intent(Settings.ACTION_SECURITY_SETTINGS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
)
COMMAND_OK
override fun onBind(intent: Intent) =
object : IfaaManagerService.Stub() {
private val _supportBIOTypes by lazy {
when (SystemProperties.get(FP_TYPE_PROP, "")) {
"back",
"side",
"front" -> AUTH_TYPE_FINGERPRINT
"ultrasonic",
"optical" -> AUTH_TYPE_OPTICAL_FINGERPRINT
else -> AUTH_TYPE_NOT_SUPPORT
}
}
else -> COMMAND_FAIL
}
override fun getSupportBIOTypes() = _supportBIOTypes
private val _deviceModel by lazy { SystemProperties.get(IFAA_MODEL_PROP, "OPLUS-Default") }
override fun getDeviceModel() = _deviceModel
override fun startBIOManager(authType: Int) =
when (authType) {
AUTH_TYPE_FINGERPRINT -> {
applicationContext.startActivity(
Intent(Settings.ACTION_SECURITY_SETTINGS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
)
override fun processCmd(param: ByteArray) = try {
getFpPayService()?.ifaa_invoke_command(param)
} catch (e: Exception) {
Log.e(LOG_TAG, "processCmdImpl: ifaa_invoke_command aidl failed", e)
null
}
override fun getVersion() = 4
override fun getExtInfo(authType: Int, keyExtInfo: String) = when (keyExtInfo) {
KEY_GET_SENSOR_LOCATION -> initExtString()
else -> ""
}
override fun setExtInfo(authType: Int, keyExtInfo: String, valExtInfo: String) {
// Do nothing
}
override fun getEnabled(bioType: Int): Int {
if (!keyguardManager.isKeyguardSecure) {
Log.e(LOG_TAG, "No secure keyguard set.")
return BIOMETRIC_NOUSE_NOSET_KEYGUARD
}
return when (bioType) {
AUTH_TYPE_FINGERPRINT -> when {
!fingerprintManager.isHardwareDetected -> {
Log.e(LOG_TAG, "Fingerprint hardware not available!")
BIOMETRIC_NOUSE_SYSTEMLOCKED
COMMAND_OK
}
fingerprintManager.enrolledFingerprints.isNullOrEmpty() -> {
Log.e(LOG_TAG, "Fingerprint not enrolled!")
BIOMETRIC_NOUSE_NOT_ENROLLED
}
else -> BIOMETRIC_USE_READY
else -> COMMAND_FAIL
}
else -> 0
}
}
override fun getIDList(bioType: Int): IntArray? = when (bioType) {
AUTH_TYPE_FINGERPRINT -> {
val enrolledFingerprintIds = fingerprintManager.enrolledFingerprints?.map {
it.biometricId
}?.toIntArray()
Log.w(LOG_TAG, "getIDList: ${enrolledFingerprintIds}!")
enrolledFingerprintIds
private val _deviceModel by lazy {
SystemProperties.get(IFAA_MODEL_PROP, "OPLUS-Default")
}
else -> null
}
}
override fun getDeviceModel() = _deviceModel
private fun getFpPayService() = _fpPayService ?: run {
val binder = ServiceManager.getService("${IFingerprintPay.DESCRIPTOR}/default")
IFingerprintPay.Stub.asInterface(binder)?.also {
binder.linkToDeath(fpPayServiceDeathRecipient, 0)
_fpPayService = it
override fun processCmd(param: ByteArray) =
try {
getFpPayService()?.ifaa_invoke_command(param)
} catch (e: Exception) {
Log.e(LOG_TAG, "processCmdImpl: ifaa_invoke_command aidl failed", e)
null
}
override fun getVersion() = 4
override fun getExtInfo(authType: Int, keyExtInfo: String) =
when (keyExtInfo) {
KEY_GET_SENSOR_LOCATION -> initExtString()
else -> ""
}
override fun setExtInfo(authType: Int, keyExtInfo: String, valExtInfo: String) {
// Do nothing
}
override fun getEnabled(bioType: Int): Int {
if (!keyguardManager.isKeyguardSecure) {
Log.e(LOG_TAG, "No secure keyguard set.")
return BIOMETRIC_NOUSE_NOSET_KEYGUARD
}
return when (bioType) {
AUTH_TYPE_FINGERPRINT ->
when {
!fingerprintManager.isHardwareDetected -> {
Log.e(LOG_TAG, "Fingerprint hardware not available!")
BIOMETRIC_NOUSE_SYSTEMLOCKED
}
fingerprintManager.enrolledFingerprints.isNullOrEmpty() -> {
Log.e(LOG_TAG, "Fingerprint not enrolled!")
BIOMETRIC_NOUSE_NOT_ENROLLED
}
else -> BIOMETRIC_USE_READY
}
else -> 0
}
}
override fun getIDList(bioType: Int): IntArray? =
when (bioType) {
AUTH_TYPE_FINGERPRINT -> {
val enrolledFingerprintIds =
fingerprintManager.enrolledFingerprints
?.map { it.biometricId }
?.toIntArray()
Log.w(LOG_TAG, "getIDList: ${enrolledFingerprintIds}!")
enrolledFingerprintIds
}
else -> null
}
}
}
private fun getFpPayService() =
_fpPayService
?: run {
val binder = ServiceManager.getService("${IFingerprintPay.DESCRIPTOR}/default")
IFingerprintPay.Stub.asInterface(binder)?.also {
binder.linkToDeath(fpPayServiceDeathRecipient, 0)
_fpPayService = it
}
}
private val defaultDisplayDimension by lazy {
val dim1 = displayNoVerify?.supportedModes?.maxByOrNull { it.physicalHeight }
?.run { Point(physicalWidth, physicalHeight) }
val dim2 = windowManager.maximumWindowMetrics.bounds
.run { Point(width(), height()) }
val dim1 =
displayNoVerify
?.supportedModes
?.maxByOrNull { it.physicalHeight }
?.run { Point(physicalWidth, physicalHeight) }
val dim2 = windowManager.maximumWindowMetrics.bounds.run { Point(width(), height()) }
dim1?.let { Point(maxOf(dim1.x, dim2.x), maxOf(dim1.y, dim2.y)) } ?: dim2
}
@@ -140,33 +158,37 @@ class IfaaService : Service() {
val iconLocationBottom = SystemProperties.getInt(FP_ICON_LOCATION_PROP, 278)
Point(
(defaultDisplayDimension.x - iconDiameter) / 2,
defaultDisplayDimension.y - iconLocationBottom - iconDiameter / 2
defaultDisplayDimension.y - iconLocationBottom - iconDiameter / 2,
)
}
private fun initExtString() = run {
val displayDimension = windowManager.maximumWindowMetrics.bounds.run {
Point(width(), height())
}
val displayDimension =
windowManager.maximumWindowMetrics.bounds.run { Point(width(), height()) }
val scale = { pos: Point ->
Point(
pos.x * displayDimension.x / defaultDisplayDimension.x,
pos.y * displayDimension.y / defaultDisplayDimension.y
pos.y * displayDimension.y / defaultDisplayDimension.y,
)
}
val scaledLocation = scale(iconLocation)
val scaledDiameter = scale(Point(iconDiameter, iconDiameter))
JSONObject().apply {
put("type", 0)
put("fullView", JSONObject().apply {
put("startX", scaledLocation.x)
put("startY", scaledLocation.y)
put("width", scaledDiameter.x)
put("height", scaledDiameter.y)
put("navConflict", true)
})
}.toString()
JSONObject()
.apply {
put("type", 0)
put(
"fullView",
JSONObject().apply {
put("startX", scaledLocation.x)
put("startY", scaledLocation.y)
put("width", scaledDiameter.x)
put("height", scaledDiameter.y)
put("navConflict", true)
},
)
}
.toString()
}
companion object {

View File

@@ -12,7 +12,9 @@ android_app {
],
optimize: {
optimize: true,
proguard_flags_files: ["proguard.flags"],
shrink_resources: true,
},
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018, 2021-2022 The LineageOS Project
Copyright (C) 2018, 2021-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.
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.system"
package="org.lineageos.settings.device">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
@@ -41,17 +42,19 @@
<!-- Additional button settings (Button settings) -->
<activity
android:name=".ButtonSettingsActivity"
android:label="@string/button_panel_title"
android:exported="false">
android:label="@string/alert_slider_category_title"
android:exported="true">
<intent-filter>
<action android:name="org.lineageos.settings.device.ADDITIONAL_BUTTONS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<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.sound" />
</activity>
<service
android:name=".KeyHandler"
android:permission="KeyHandlerService"
android:exported="false" />
android:exported="true" />
</application>
</manifest>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="alert_slider_category_title">מתג התראות</string>
<string name="alert_slider_selection_dialog_title">פעולה</string>
<string name="alert_slider_top_position">ממוקם למעלה</string>
<string name="alert_slider_middle_position">ממוקם באמצע</string>
<string name="alert_slider_bottom_position">ממוקם למטה</string>
<string name="alert_slider_mode_none">ללא</string>
<string name="alert_slider_mode_silent">שקט</string>
<string name="alert_slider_mode_normal">רגיל</string>
<string name="alert_slider_mode_vibration">רטט</string>
<string name="alert_slider_mode_dnd_priority_only">עדיפות בלבד</string>
<string name="alert_slider_mode_dnd_total_silence">מושתק לחלוטין</string>
<string name="alert_slider_mode_dnd_alarms_only">שעון מעורר בלבד</string>
<string name="alert_slider_mute_media_title">השתקת מדיה</string>
<string name="alert_slider_mute_media_summary">השתקת מדיה במעבר להשתקה</string>
</resources>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="alert_slider_selection_dialog_title">Atzione</string>
<string name="alert_slider_top_position">Positzione superiore</string>
<string name="alert_slider_middle_position">Positzione tzentrale</string>
<string name="alert_slider_bottom_position">Positzione inferiore</string>
<string name="alert_slider_mode_silent">A sa muda</string>
<string name="alert_slider_mode_normal">Normale</string>
<string name="alert_slider_mode_vibration">Vibratzione</string>
<string name="alert_slider_mode_dnd_priority_only">Prioridade isceti</string>
<string name="alert_slider_mode_dnd_total_silence">Silèntziu totale</string>
<string name="alert_slider_mode_dnd_alarms_only">Isvèllias isceti</string>
<string name="alert_slider_mute_media_title">Pone is cuntenutos multimediales a sa muda</string>
<string name="alert_slider_mute_media_summary">Pone is cuntenutos multimediales a sa muda cando passas a silèntziu</string>
</resources>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="alert_slider_top_position">முதற் நிலை</string>
<string name="alert_slider_middle_position">நடு நிலை</string>
<string name="alert_slider_bottom_position">கீழ் நிலை</string>
<string name="alert_slider_mode_none">இல்லை</string>
<string name="alert_slider_mode_silent">ஒலியின்மை</string>
</resources>

View File

@@ -5,7 +5,7 @@
-->
<resources>
<!-- Alert slider -->
<string name="alert_slider_category_title">Alert slider</string>
<string name="alert_slider_category_title">Alert slider settings</string>
<string name="alert_slider_selection_dialog_title">Action</string>
<string name="alert_slider_top_position">Top position</string>
<string name="alert_slider_middle_position">Middle position</string>

View File

@@ -1,13 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 The LineageOS Project
SPDX-FileCopyrightText: 2021-2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:title="@string/alert_slider_category_title">
<SwitchPreference
<SwitchPreferenceCompat
android:key="config_mute_media"
android:title="@string/alert_slider_mute_media_title"
android:summary="@string/alert_slider_mute_media_summary"
@@ -16,29 +19,29 @@
<ListPreference
android:key="config_top_position"
android:dialogTitle="@string/alert_slider_selection_dialog_title"
android:title="@string/alert_slider_top_position"
android:summary="%s"
android:entries="@array/alert_slider_action_entries"
android:entryValues="@array/alert_slider_action_entry_values"
android:defaultValue="0" />
android:defaultValue="0"
android:title="@string/alert_slider_top_position"
app:useSimpleSummaryProvider="true" />
<ListPreference
android:key="config_middle_position"
android:dialogTitle="@string/alert_slider_selection_dialog_title"
android:title="@string/alert_slider_middle_position"
android:summary="%s"
android:entries="@array/alert_slider_action_entries"
android:entryValues="@array/alert_slider_action_entry_values"
android:defaultValue="1" />
android:defaultValue="1"
android:title="@string/alert_slider_middle_position"
app:useSimpleSummaryProvider="true" />
<ListPreference
android:key="config_bottom_position"
android:dialogTitle="@string/alert_slider_selection_dialog_title"
android:title="@string/alert_slider_bottom_position"
android:summary="%s"
android:entries="@array/alert_slider_action_entries"
android:entryValues="@array/alert_slider_action_entry_values"
android:defaultValue="2" />
android:defaultValue="2"
android:title="@string/alert_slider_bottom_position"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -1,20 +1,27 @@
/*
* Copyright (C) 2021-2024 The LineageOS Project
* SPDX-FileCopyrightText: 2021-2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.settings.device
import android.os.Bundle
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity
class ButtonSettingsActivity : CollapsingToolbarBaseActivity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
fragmentManager.beginTransaction().replace(
com.android.settingslib.collapsingtoolbar.R.id.content_frame,
ButtonSettingsFragment()
).commit()
supportFragmentManager
.beginTransaction()
.replace(
com.android.settingslib.collapsingtoolbar.R.id.content_frame,
ButtonSettingsFragment(),
TAG,
)
.commit()
}
companion object {
private const val TAG = "ButtonSettingsActivity"
}
}

View File

@@ -1,31 +1,15 @@
/*
* Copyright (C) 2021 The LineageOS Project
* SPDX-FileCopyrightText: 2021-2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.settings.device
import android.os.Bundle
import android.view.MenuItem
import androidx.preference.PreferenceFragment
import androidx.preference.PreferenceFragmentCompat
class ButtonSettingsFragment : PreferenceFragment() {
class ButtonSettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.button_panel)
activity.actionBar!!.setDisplayHomeAsUpEnabled(true)
}
override fun addPreferencesFromResource(preferencesResId: Int) {
super.addPreferencesFromResource(preferencesResId)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.home -> {
activity.finish()
return true
}
}
return super.onOptionsItemSelected(item)
setPreferencesFromResource(R.xml.button_panel, rootKey)
}
}

View File

@@ -8,7 +8,6 @@ package org.lineageos.settings.device
import android.database.Cursor
import android.database.MatrixCursor
import android.provider.SearchIndexableResource
import android.provider.SearchIndexablesProvider
import android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME
import android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID
import android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION
@@ -19,15 +18,14 @@ import android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID
import android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS
import android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS
import android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS
import android.provider.SearchIndexablesProvider
class ConfigPanelSearchIndexablesProvider : SearchIndexablesProvider() {
override fun onCreate(): Boolean = true
override fun queryXmlResources(projection: Array<String?>?): Cursor {
val cursor = MatrixCursor(INDEXABLES_XML_RES_COLUMNS)
INDEXABLE_RES.forEach {
cursor.addRow(generateResourceRef(it))
}
INDEXABLE_RES.forEach { cursor.addRow(generateResourceRef(it)) }
return cursor
}
@@ -54,10 +52,14 @@ class ConfigPanelSearchIndexablesProvider : SearchIndexablesProvider() {
companion object {
private const val TAG = "ConfigPanelSearchIndexablesProvider"
private val INDEXABLE_RES = arrayOf<SearchIndexableResource>(
SearchIndexableResource(
1, R.xml.button_panel, ButtonSettingsActivity::class.java.name, 0
private val INDEXABLE_RES =
arrayOf<SearchIndexableResource>(
SearchIndexableResource(
1,
R.xml.button_panel,
ButtonSettingsActivity::class.java.name,
0,
)
)
)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2023 The LineageOS Project
* Copyright (C) 2021-2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,7 +18,6 @@ import android.os.Vibrator
import android.provider.Settings
import android.view.KeyEvent
import com.android.internal.os.DeviceKeyHandler
import java.io.File
import java.util.concurrent.Executors
@@ -27,32 +26,43 @@ class KeyHandler(context: Context) : DeviceKeyHandler {
private val notificationManager = context.getSystemService(NotificationManager::class.java)!!
private val vibrator = context.getSystemService(Vibrator::class.java)!!
private val packageContext = context.createPackageContext(
KeyHandler::class.java.getPackage()!!.name, 0
)
private val packageContext =
context.createPackageContext(KeyHandler::class.java.getPackage()!!.name, 0)
private val sharedPreferences
get() = packageContext.getSharedPreferences(
packageContext.packageName + "_preferences",
Context.MODE_PRIVATE or Context.MODE_MULTI_PROCESS
)
get() =
packageContext.getSharedPreferences(
packageContext.packageName + "_preferences",
Context.MODE_PRIVATE or Context.MODE_MULTI_PROCESS,
)
private val executorService = Executors.newSingleThreadExecutor()
private var wasMuted = false
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1)
val state = intent.getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false)
if (stream == AudioSystem.STREAM_MUSIC && !state) {
wasMuted = false
private val broadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
AudioManager.STREAM_MUTE_CHANGED_ACTION -> {
val stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1)
val state =
intent.getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false)
if (stream == AudioSystem.STREAM_MUSIC && !state) {
wasMuted = false
}
}
Intent.ACTION_BOOT_COMPLETED -> populateKeyState(false)
}
}
}
}
init {
context.registerReceiver(
broadcastReceiver,
IntentFilter(AudioManager.STREAM_MUTE_CHANGED_ACTION)
IntentFilter().apply {
addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION)
addAction(Intent.ACTION_BOOT_COMPLETED)
},
)
}
@@ -67,37 +77,40 @@ class KeyHandler(context: Context) : DeviceKeyHandler {
return event
}
when (File("/proc/tristatekey/tri_state").readText().trim()) {
"1" -> handleMode(POSITION_TOP)
"2" -> handleMode(POSITION_MIDDLE)
"3" -> handleMode(POSITION_BOTTOM)
}
populateKeyState(true)
return null
}
private fun vibrateIfNeeded(mode: Int) {
when (mode) {
AudioManager.RINGER_MODE_VIBRATE -> vibrator.vibrate(
MODE_VIBRATION_EFFECT,
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES
)
AudioManager.RINGER_MODE_NORMAL -> vibrator.vibrate(
MODE_NORMAL_EFFECT,
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES
)
private fun populateKeyState(vibrate: Boolean) {
when (File("/proc/tristatekey/tri_state").readText().trim()) {
"1" -> handleMode(POSITION_TOP, vibrate)
"2" -> handleMode(POSITION_MIDDLE, vibrate)
"3" -> handleMode(POSITION_BOTTOM, vibrate)
}
}
private fun handleMode(position: Int) {
private fun vibrateIfNeeded(mode: Int) {
when (mode) {
AudioManager.RINGER_MODE_VIBRATE ->
vibrator.vibrate(MODE_VIBRATION_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES)
AudioManager.RINGER_MODE_NORMAL ->
vibrator.vibrate(MODE_NORMAL_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES)
}
}
private fun handleMode(position: Int, vibrate: Boolean) {
val muteMedia = sharedPreferences.getBoolean(MUTE_MEDIA_WITH_SILENT, false)
val mode = when (position) {
POSITION_TOP -> sharedPreferences.getString(ALERT_SLIDER_TOP_KEY, "0")!!.toInt()
POSITION_MIDDLE -> sharedPreferences.getString(ALERT_SLIDER_MIDDLE_KEY, "1")!!.toInt()
POSITION_BOTTOM -> sharedPreferences.getString(ALERT_SLIDER_BOTTOM_KEY, "2")!!.toInt()
else -> return
}
val mode =
when (position) {
POSITION_TOP -> sharedPreferences.getString(ALERT_SLIDER_TOP_KEY, "0")!!.toInt()
POSITION_MIDDLE ->
sharedPreferences.getString(ALERT_SLIDER_MIDDLE_KEY, "1")!!.toInt()
POSITION_BOTTOM ->
sharedPreferences.getString(ALERT_SLIDER_BOTTOM_KEY, "2")!!.toInt()
else -> return
}
executorService.submit {
when (mode) {
@@ -109,14 +122,17 @@ class KeyHandler(context: Context) : DeviceKeyHandler {
wasMuted = true
}
}
AudioManager.RINGER_MODE_VIBRATE, AudioManager.RINGER_MODE_NORMAL -> {
AudioManager.RINGER_MODE_VIBRATE,
AudioManager.RINGER_MODE_NORMAL -> {
setZenMode(Settings.Global.ZEN_MODE_OFF)
audioManager.ringerModeInternal = mode
if (muteMedia && wasMuted) {
audioManager.adjustVolume(AudioManager.ADJUST_UNMUTE, 0)
}
}
ZEN_PRIORITY_ONLY, ZEN_TOTAL_SILENCE, ZEN_ALARMS_ONLY -> {
ZEN_PRIORITY_ONLY,
ZEN_TOTAL_SILENCE,
ZEN_ALARMS_ONLY -> {
audioManager.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL
setZenMode(mode - ZEN_OFFSET)
if (muteMedia && wasMuted) {
@@ -124,7 +140,10 @@ class KeyHandler(context: Context) : DeviceKeyHandler {
}
}
}
vibrateIfNeeded(mode)
if (vibrate) {
vibrateIfNeeded(mode)
}
}
}

View File

@@ -10,6 +10,7 @@ android_app {
certificate: "platform",
platform_apis: true,
privileged: true,
system_ext_specific: true,
optimize: {

View File

@@ -6,11 +6,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.pen">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:label="@string/app_name"

View File

@@ -5,7 +5,6 @@
-->
<exceptions>
<exception package="org.lineageos.pen">
<permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false" />
<permission name="android.permission.BLUETOOTH_CONNECT" fixed="false" />
<permission name="android.permission.BLUETOOTH_SCAN" fixed="false" />
<permission name="android.permission.POST_NOTIFICATIONS" fixed="false" />

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Qələm taxılıb</string>
<string name="tap_to_connect">Bağlanmaq üçün toxunun</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Дигитална писалка е сдвоена</string>
<string name="tap_to_connect">Натисни за сдвояване</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Bolígraf adjunt</string>
<string name="tap_to_connect">Toqueu per connectar</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pero připojeno</string>
<string name="tap_to_connect">Klepnutím připojit</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Η γραφίδα προσαρτήθηκε</string>
<string name="tap_to_connect">Πατήστε για σύνδεση</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pen attached</string>
<string name="tap_to_connect">Tap to connect</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pen attached</string>
<string name="tap_to_connect">Tap to connect</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pen attached</string>
<string name="tap_to_connect">Tap to connect</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pen attached</string>
<string name="tap_to_connect">Tap to connect</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Bolígrafo adjunto</string>
<string name="tap_to_connect">Toca para conectar</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">قلم متصل شد</string>
<string name="tap_to_connect">برای اتصال ضربه بزنید</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Stylo attaché</string>
<string name="tap_to_connect">Appuyer pour connecter</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Peann ceangailte</string>
<string name="tap_to_connect">Tapáil chun ceangal</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Toll mellékelve</string>
<string name="tap_to_connect">A csatlakoztatáshoz érintse meg</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Penna attaccata</string>
<string name="tap_to_connect">Tocca per connettere</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">עט מצורף</string>
<string name="tap_to_connect">נגיעה להתחברות</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">ペンを装着しました</string>
<string name="tap_to_connect">タップして接続</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">კალამი მიუერთდა</string>
<string name="tap_to_connect">შეეხეთ მიერთებისთვის</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Dołączone pióro</string>
<string name="tap_to_connect">Dotknij, aby połączyć</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Caneta anexada</string>
<string name="tap_to_connect">Toque para conectar</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Caneta anexada</string>
<string name="tap_to_connect">Toque para conectar</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Stilou atașat</string>
<string name="tap_to_connect">Atingeți pentru a conecta</string>
</resources>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="tap_to_connect">Нажмите, чтобы подключить</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pinna alligongiada</string>
<string name="tap_to_connect">Toca pro connètere</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Pisalo priključeno</string>
<string name="tap_to_connect">Tapnite za povezavo</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">எழுத்தாணி இணைக்கப்பட்டது</string>
<string name="tap_to_connect">இணைக்கத் தட்டுக</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">قەلەم ئۇلاندى</string>
<string name="tap_to_connect">چېكىلسە باغلىنىدۇ</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">Đã gắn bút</string>
<string name="tap_to_connect">Chạm để kết nối</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<string name="pen_attached">笔已连接</string>
<string name="tap_to_connect">轻触以连接</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2025 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- Max supported refresh rate when using pen. -->
<string name="config_penSupportedRefreshRate" translatable="false"></string>
</resources>

View File

@@ -15,38 +15,73 @@ import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.content.Intent
import android.database.ContentObserver
import android.hardware.input.InputManager
import android.os.Handler
import android.os.IBinder
import android.os.UEventObserver
import android.provider.Settings
import android.provider.Settings.System.PEAK_REFRESH_RATE
import android.util.Log
class PenService : Service() {
private val bluetoothManager by lazy { getSystemService(BluetoothManager::class.java) }
private val inputManager by lazy { getSystemService(InputManager::class.java) }
private val notificationManager by lazy { getSystemService(NotificationManager::class.java) }
private val observer = object : UEventObserver() {
private val lock = Any()
private val penSupportedRefreshRate by lazy {
getString(R.string.config_penSupportedRefreshRate)
}
override fun onUEvent(event: UEvent) {
synchronized(lock) {
val pencilStatus = event.get("pencil_status") ?: return
val pencilAddr = event.get("pencil_addr")?.chunked(2)?.joinToString(":") {
it.uppercase()
} ?: return
private val handler by lazy { Handler(mainLooper) }
when (pencilStatus) {
"0" -> notificationManager.cancel(NOTIFICATION_ID)
"1" -> postNotification(pencilAddr)
private val observer =
object : UEventObserver() {
private val lock = Any()
override fun onUEvent(event: UEvent) {
synchronized(lock) {
val pencilStatus = event.get("pencil_status") ?: return
val pencilAddr =
event.get("pencil_addr")?.chunked(2)?.joinToString(":") { it.uppercase() }
?: return
when (pencilStatus) {
"0" -> notificationManager.cancel(NOTIFICATION_ID)
"1" -> postNotification(pencilAddr)
}
}
}
}
private val inputObserver =
object : InputManager.InputDeviceListener {
override fun onInputDeviceAdded(deviceId: Int) {
overridePeakRefreshRateIfNeeded()
}
override fun onInputDeviceRemoved(deviceId: Int) {
overridePeakRefreshRateIfNeeded()
}
override fun onInputDeviceChanged(deviceId: Int) {
// Do nothing
}
}
private val peakRefreshRateSettingsObserver by lazy {
object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
overridePeakRefreshRateIfNeeded()
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
intent?.getStringExtra(EXTRA_PENCIL_ADDR)?.let {
bondBtDevice(it)
}
intent?.getStringExtra(EXTRA_PENCIL_ADDR)?.let { bondBtDevice(it) }
return START_STICKY
}
@@ -56,12 +91,28 @@ class PenService : Service() {
override fun onCreate() {
super.onCreate()
if (!penSupportedRefreshRate.isEmpty()) {
contentResolver.registerContentObserver(
Settings.System.getUriFor(PEAK_REFRESH_RATE),
false,
peakRefreshRateSettingsObserver,
)
peakRefreshRateSettingsObserver.onChange(true)
inputManager.registerInputDeviceListener(inputObserver, handler)
}
observer.startObserving("DEVPATH=/devices/virtual/oplus_wireless/pencil")
}
override fun onDestroy() {
super.onDestroy()
if (!penSupportedRefreshRate.isEmpty()) {
contentResolver.unregisterContentObserver(peakRefreshRateSettingsObserver)
inputManager.unregisterInputDeviceListener(inputObserver)
}
observer.stopObserving()
}
@@ -69,8 +120,16 @@ class PenService : Service() {
val adapter = bluetoothManager.adapter
@Suppress("DEPRECATION") adapter.enable()
val scanner = adapter.bluetoothLeScanner
scanner.startScan(
val scanner = run {
repeat(50) {
adapter.bluetoothLeScanner?.let {
return@run it
}
Thread.sleep(100)
}
return@run null
}
scanner?.startScan(
listOf(ScanFilter.Builder().setDeviceAddress(pencilAddr).build()),
ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
@@ -93,10 +152,36 @@ class PenService : Service() {
super.onScanFailed(errorCode)
scanner.stopScan(this)
}
}
},
)
}
private fun overridePeakRefreshRateIfNeeded() {
val isPenConnected =
inputManager.inputDeviceIds.firstOrNull {
val device = inputManager.getInputDevice(it) ?: return@firstOrNull false
if (device.vendorId != 0x22D9 && device.vendorId != 0x330A) {
// Not an OPPO/Maxeye vendor ID
return@firstOrNull false
}
if (
device.bluetoothAddress?.startsWith("C0:87:06") == false &&
device.bluetoothAddress?.startsWith("F8:6F:DE") == false
) {
// Not a Maxeye/Goodix MAC prefix
return@firstOrNull false
}
return@firstOrNull true
} != null
val peakRefreshRate = Settings.System.getString(contentResolver, PEAK_REFRESH_RATE)
if (isPenConnected && peakRefreshRate == "Infinity") {
Settings.System.putString(contentResolver, PEAK_REFRESH_RATE, penSupportedRefreshRate)
} else if (!isPenConnected && peakRefreshRate == penSupportedRefreshRate) {
Settings.System.putString(contentResolver, PEAK_REFRESH_RATE, "Infinity")
}
}
private fun postNotification(pencilAddr: String) {
val adapter = bluetoothManager.adapter
@@ -110,27 +195,29 @@ class PenService : Service() {
NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH
NotificationManager.IMPORTANCE_HIGH,
)
)
}
val contentIntent = PendingIntent.getService(
this,
0,
Intent(this, PenService::class.java).apply {
putExtra(EXTRA_PENCIL_ADDR, pencilAddr)
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val contentIntent =
PendingIntent.getService(
this,
0,
Intent(this, PenService::class.java).apply {
putExtra(EXTRA_PENCIL_ADDR, pencilAddr)
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
)
val notification = Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stylus)
.setContentTitle(getString(R.string.pen_attached))
.setContentText(getString(R.string.tap_to_connect))
.setContentIntent(contentIntent)
.setAutoCancel(true)
.build()
val notification =
Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stylus)
.setContentTitle(getString(R.string.pen_attached))
.setContentText(getString(R.string.tap_to_connect))
.setContentIntent(contentIntent)
.setAutoCancel(true)
.build()
notificationManager.notify(NOTIFICATION_ID, notification)
}

View File

@@ -16,4 +16,3 @@
| OPLUS_LINEAGE_TOUCH_HAL | USE_OPLUSTOUCH | Use and interface with stock OplusTouch | false |
| OPLUS_LINEAGE_VIBRATOR_HAL | INCLUDE_DIR | Device specific include dir path | |
| OPLUS_LINEAGE_VIBRATOR_HAL | USE_EFFECT_STREAM | Enable effect stream feature | false |
| QTI_GPT_UTILS | USE_BSG_FRAMEWORK | Enable BSG framework feature | true |

View File

@@ -26,15 +26,15 @@ ConsumerIr::ConsumerIr() : supportedFreqs({{MIN_FREQ, MAX_FREQ}}) {}
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus ConsumerIr::transmit(int32_t in_carrierFreqHz,
const std::vector<int32_t>& in_pattern) {
if (in_carrierFreqHz < MIN_FREQ || in_carrierFreqHz > MAX_FREQ) {
LOG(ERROR) << "Invalid carrier frequency: " << in_carrierFreqHz;
::ndk::ScopedAStatus ConsumerIr::transmit(int32_t carrierFreqHz,
const std::vector<int32_t>& pattern) {
if (carrierFreqHz < MIN_FREQ || carrierFreqHz > MAX_FREQ) {
LOG(ERROR) << "Invalid carrier frequency: " << carrierFreqHz;
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
int32_t totalTime = 0;
for (int32_t value : in_pattern) {
for (int32_t value : pattern) {
if (value < 0) {
LOG(ERROR) << "Invalid pattern value: " << value;
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -53,7 +53,7 @@ ConsumerIr::ConsumerIr() : supportedFreqs({{MIN_FREQ, MAX_FREQ}}) {}
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
size_t paramsSize = sizeof(struct pattern_params) + in_pattern.size() * sizeof(int32_t);
size_t paramsSize = sizeof(struct pattern_params) + pattern.size() * sizeof(int32_t);
auto params = std::unique_ptr<struct pattern_params, decltype(&free)>(
static_cast<pattern_params*>(malloc(paramsSize)), free);
if (!params) {
@@ -61,9 +61,9 @@ ConsumerIr::ConsumerIr() : supportedFreqs({{MIN_FREQ, MAX_FREQ}}) {}
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
params->carrier_freq = in_carrierFreqHz;
params->size = in_pattern.size();
memcpy(params->pattern, in_pattern.data(), in_pattern.size() * sizeof(int32_t));
params->carrier_freq = carrierFreqHz;
params->size = pattern.size();
memcpy(params->pattern, pattern.data(), pattern.size() * sizeof(int32_t));
int result = ioctl(fd, IR_SEND_PATTERN, params.get());

View File

@@ -18,8 +18,8 @@ class ConsumerIr : public BnConsumerIr {
private:
::ndk::ScopedAStatus getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) override;
::ndk::ScopedAStatus transmit(int32_t in_carrierFreqHz,
const std::vector<int32_t>& in_pattern) override;
::ndk::ScopedAStatus transmit(int32_t carrierFreqHz,
const std::vector<int32_t>& pattern) override;
std::vector<ConsumerIrFreqRange> supportedFreqs;
};

View File

@@ -19,7 +19,9 @@ AntiFlicker::AntiFlicker() : mOplusDisplayFd(open("/dev/oplus_display", O_RDWR))
ndk::ScopedAStatus AntiFlicker::getEnabled(bool* _aidl_return) {
unsigned int value;
if (ioctl(mOplusDisplayFd, PANEL_IOCTL_GET_DIMLAYER_BL_EN, &value) != 0) {
if (ioctl(mOplusDisplayFd, PANEL_IOCTL_GET_PWM_PULSE, &value) != 0 &&
ioctl(mOplusDisplayFd, PANEL_IOCTL_GET_PWM_TURBO, &value) != 0 &&
ioctl(mOplusDisplayFd, PANEL_IOCTL_GET_DIMLAYER_BL_EN, &value) != 0) {
LOG(ERROR) << "Failed to read current AntiFlicker state";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
@@ -33,7 +35,8 @@ ndk::ScopedAStatus AntiFlicker::setEnabled(bool enabled) {
return status;
}
unsigned int value = enabled;
if (isEnabled != enabled &&
if (isEnabled != enabled && ioctl(mOplusDisplayFd, PANEL_IOCTL_SET_PWM_PULSE, &value) != 0 &&
ioctl(mOplusDisplayFd, PANEL_IOCTL_SET_PWM_TURBO, &value) != 0 &&
ioctl(mOplusDisplayFd, PANEL_IOCTL_SET_DIMLAYER_BL_EN, &value) != 0) {
LOG(ERROR) << "Failed to set AntiFlicker state";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);

View File

@@ -0,0 +1,21 @@
//
// SPDX-FileCopyrightText: 2025 The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
cc_binary {
name: "vendor.oplus.hardware.performance-service",
vendor: true,
relative_install_path: "hw",
init_rc: ["vendor.oplus.hardware.performance-service.rc"],
vintf_fragments: ["vendor.oplus.hardware.performance-service.xml"],
srcs: [
"Performance.cpp",
"service.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
"vendor.oplus.hardware.performance-V1-ndk",
],
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
/*
* SPDX-FileCopyrightText: 2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <aidl/vendor/oplus/hardware/performance/BnPerformance.h>
namespace aidl {
namespace vendor {
namespace oplus {
namespace hardware {
namespace performance {
class Performance : public BnPerformance {
ndk::ScopedAStatus addAcmDirName(const std::string& dirname, int64_t flag,
int32_t* _aidl_return) override;
ndk::ScopedAStatus addAcmNomediaDirName(const std::string& dirname,
int32_t* _aidl_return) override;
ndk::ScopedAStatus addAcmPkgName(const std::string& pkgname, int64_t flag,
int32_t* _aidl_return) override;
ndk::ScopedAStatus addTaskTrackPid(int32_t group, int32_t pid, bool clear,
int32_t* _aidl_return) override;
ndk::ScopedAStatus clearTaskTrackGroup(int32_t group) override;
ndk::ScopedAStatus delAcmDirName(const std::string& dirname, int32_t* _aidl_return) override;
ndk::ScopedAStatus delAcmNomediaDirName(const std::string& dirname,
int32_t* _aidl_return) override;
ndk::ScopedAStatus delAcmPkgName(const std::string& pkgname, int32_t* _aidl_return) override;
ndk::ScopedAStatus disableDamonReclaim(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableKmallocDebug(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableMultiThreadOptimize(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableProcessReclaim(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableTaskCpustats(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableTaskPlacementDecision(int32_t* _aidl_return) override;
ndk::ScopedAStatus disableVmallocDebug(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableAudioPerf(const std::string& value, int32_t* _aidl_return) override;
ndk::ScopedAStatus enableDamonReclaim(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableKmallocDebug(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableMultiThreadOptimize(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableProcessReclaim(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableTaskCpustats(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableTaskPlacementDecision(int32_t* _aidl_return) override;
ndk::ScopedAStatus enableVmallocDebug(int32_t* _aidl_return) override;
ndk::ScopedAStatus existMemMonitor(int32_t* _aidl_return) override;
ndk::ScopedAStatus getAcmDirFlag(const std::string& dirname, int64_t* _aidl_return) override;
ndk::ScopedAStatus getAcmOpstat(int32_t* _aidl_return) override;
ndk::ScopedAStatus getAcmPkgFlag(const std::string& pkgname, int64_t* _aidl_return) override;
ndk::ScopedAStatus getClmMuxSwitch(std::string* _aidl_return) override;
ndk::ScopedAStatus getClmThreshold(int32_t threshold_id, std::string* _aidl_return) override;
ndk::ScopedAStatus getDdrResidency(std::string* _aidl_return) override;
ndk::ScopedAStatus getDevinfoDDRInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus getDevinfoUfsInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus getDevinfoUfsVersionInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus getExt4FragScore(const std::string& devpath,
std::string* _aidl_return) override;
ndk::ScopedAStatus getExt4FreefragInfo(const std::string& devpath,
std::string* _aidl_return) override;
ndk::ScopedAStatus getF2fsMovedBlks(std::string* _aidl_return) override;
ndk::ScopedAStatus getHIAllocWait(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHICpuInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus getHICpuLoading(std::string* _aidl_return) override;
ndk::ScopedAStatus getHIDState(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIEmcdrvIowait(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIFsyncWait(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIIonWait(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIIowait(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIIowaitHung(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIKswapdLoading(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHISchedLatency(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIScmCall(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getHIUfsFeature(ProcReqHal* _aidl_return) override;
ndk::ScopedAStatus getKernelVersion(int32_t* _aidl_return) override;
ndk::ScopedAStatus getKmallocDebug(std::string* _aidl_return) override;
ndk::ScopedAStatus getKmallocOrigin(std::string* _aidl_return) override;
ndk::ScopedAStatus getKmallocUsed(std::string* _aidl_return) override;
ndk::ScopedAStatus getMemMonitor(std::string* _aidl_return) override;
ndk::ScopedAStatus getOswapVersion(int32_t* _aidl_return) override;
ndk::ScopedAStatus getUfsSignalRecordUpload(std::string* _aidl_return) override;
ndk::ScopedAStatus getUfsplusHpbStatus(int32_t* _aidl_return) override;
ndk::ScopedAStatus getUfsplusTwStatus(int32_t* _aidl_return) override;
ndk::ScopedAStatus getVmallocDebug(std::string* _aidl_return) override;
ndk::ScopedAStatus getVmallocHashCal(std::string* _aidl_return) override;
ndk::ScopedAStatus getVmallocUsed(std::string* _aidl_return) override;
ndk::ScopedAStatus getWakeThreadsAffinityOrdered(const std::string& handle, int32_t size,
TaskWakeInfo* _aidl_return) override;
ndk::ScopedAStatus getallocwait(std::string* _aidl_return) override;
ndk::ScopedAStatus getdstate(std::string* _aidl_return) override;
ndk::ScopedAStatus getfsyncwait(std::string* _aidl_return) override;
ndk::ScopedAStatus getionwait(std::string* _aidl_return) override;
ndk::ScopedAStatus getiowait(std::string* _aidl_return) override;
ndk::ScopedAStatus getschedlatency(std::string* _aidl_return) override;
ndk::ScopedAStatus hybridswap_memcg_para_read(int32_t action, const std::string& cgroup,
std::string* _aidl_return) override;
ndk::ScopedAStatus hybridswap_memcg_para_write(int32_t action, const std::string& cgroup,
const std::string& str,
int32_t* _aidl_return) override;
ndk::ScopedAStatus hybridswap_zram_para_read(int32_t action,
std::string* _aidl_return) override;
ndk::ScopedAStatus hybridswap_zram_para_write(int32_t action, const std::string& str,
int32_t* _aidl_return) override;
ndk::ScopedAStatus isJankTaskTrackEnable(bool* _aidl_return) override;
ndk::ScopedAStatus perProcessMemReadahead(int32_t uid, int32_t pid, int32_t type,
int32_t* _aidl_return) override;
ndk::ScopedAStatus perProcessMemReclaim(int32_t uid, int32_t pid, int32_t type,
int32_t* _aidl_return) override;
ndk::ScopedAStatus readCallStack(std::string* _aidl_return) override;
ndk::ScopedAStatus readClmEnable(std::string* _aidl_return) override;
ndk::ScopedAStatus readClmHighLoadAll(std::string* _aidl_return) override;
ndk::ScopedAStatus readClmHighLoadGrp(std::string* _aidl_return) override;
ndk::ScopedAStatus readClmLowLoadGrp(std::string* _aidl_return) override;
ndk::ScopedAStatus readCpuTaskstats(std::string* _aidl_return) override;
ndk::ScopedAStatus readDBacktrace(std::string* _aidl_return) override;
ndk::ScopedAStatus readDConvert(std::string* _aidl_return) override;
ndk::ScopedAStatus readFgFreqsThreshold(std::string* _aidl_return) override;
ndk::ScopedAStatus readIOBacktrace(std::string* _aidl_return) override;
ndk::ScopedAStatus readIomonitorInfo(const std::string& procname,
std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuIndicator(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuInfoSig(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuLoad(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuLoad32(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankCpuLoad32Scale(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankTaskTrack(std::string* _aidl_return) override;
ndk::ScopedAStatus readJankTaskTrackByPid(int32_t pid, std::string* _aidl_return) override;
ndk::ScopedAStatus readJankVersion(std::string* _aidl_return) override;
ndk::ScopedAStatus readKmallocDebugCreate(std::string* _aidl_return) override;
ndk::ScopedAStatus readLimitTable(std::string* _aidl_return) override;
ndk::ScopedAStatus readMemleakDetectThread(std::string* _aidl_return) override;
ndk::ScopedAStatus readMemoryByPids(const std::vector<int32_t>& pids, int32_t flags,
ProcMemStatRet* _aidl_return) override;
ndk::ScopedAStatus readMemoryByUids(const std::vector<int32_t>& uids, int32_t flags,
ProcMemStatRet* _aidl_return) override;
ndk::ScopedAStatus readNandswapProc(const std::string& inProc,
std::string* _aidl_return) override;
ndk::ScopedAStatus readNormalizeRealTime(std::string* _aidl_return) override;
ndk::ScopedAStatus readNormalizeRunningTime(std::string* _aidl_return) override;
ndk::ScopedAStatus readOplusReserve3(int32_t offset, int32_t len,
std::string* _aidl_return) override;
ndk::ScopedAStatus readOsvelteVersion(OsvelteVersionRet* _aidl_return) override;
ndk::ScopedAStatus readPidsSet(std::string* _aidl_return) override;
ndk::ScopedAStatus readRealTime(std::string* _aidl_return) override;
ndk::ScopedAStatus readRunningTime(std::string* _aidl_return) override;
ndk::ScopedAStatus readSchedInfoThreshold(std::string* _aidl_return) override;
ndk::ScopedAStatus readSgeFreqInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus readSgeInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus readStorageFeature(const std::string& name, const std::string& addr,
const std::string& isMulti,
std::string* _aidl_return) override;
ndk::ScopedAStatus readTargetProcess(const std::string& buffer,
std::string* _aidl_return) override;
ndk::ScopedAStatus readTaskCpustatsEnable(std::string* _aidl_return) override;
ndk::ScopedAStatus readTaskSchedInfo(std::string* _aidl_return) override;
ndk::ScopedAStatus readTidsSet(std::string* _aidl_return) override;
ndk::ScopedAStatus readTmemoryDirtypages(std::string* _aidl_return) override;
ndk::ScopedAStatus readTmemoryErrorStat(std::string* _aidl_return) override;
ndk::ScopedAStatus readTmemoryIoLatency(std::string* _aidl_return) override;
ndk::ScopedAStatus readTmemorySysdirtypages(std::string* _aidl_return) override;
ndk::ScopedAStatus readUxTaskTrack(int32_t uPid, int32_t rPid,
std::string* _aidl_return) override;
ndk::ScopedAStatus readVaFeature(std::string* _aidl_return) override;
ndk::ScopedAStatus readVersion(std::string* _aidl_return) override;
ndk::ScopedAStatus removeTaskTrackPid(int32_t group, int32_t pid) override;
ndk::ScopedAStatus searchAcmNomediaDirName(const std::string& dirname,
int32_t* _aidl_return) override;
ndk::ScopedAStatus setAcmOpstat(int32_t flag, int32_t* _aidl_return) override;
ndk::ScopedAStatus setClmMuxSwitch(const std::string& buffer) override;
ndk::ScopedAStatus setClmThreshold(const std::string& buffer, int32_t threshold_id) override;
ndk::ScopedAStatus setDamonReclaimColdTime(int32_t cold_time, int32_t* _aidl_return) override;
ndk::ScopedAStatus setDamonReclaimMonitoring(int32_t sample, int32_t aggr,
int32_t* _aidl_return) override;
ndk::ScopedAStatus setDamonReclaimQuota(int32_t quota_ms, int32_t quota_sz,
int32_t reset_interval, int32_t* _aidl_return) override;
ndk::ScopedAStatus setDamonReclaimWmarks(int32_t metric, int32_t high, int32_t mid, int32_t low,
int32_t* _aidl_return) override;
ndk::ScopedAStatus setExtSchedProp(const std::string& pid, const std::string& prop) override;
ndk::ScopedAStatus setFgUids(const std::string& fg_uid) override;
ndk::ScopedAStatus setFrameRate(const std::string& frame_rate) override;
ndk::ScopedAStatus setFreqGoverner(const std::string& gov_name,
const std::vector<int32_t>& clusters,
int32_t* _aidl_return) override;
ndk::ScopedAStatus setImFlag(const std::string& pid, const std::string& im_flag) override;
ndk::ScopedAStatus setProcessReclaim(const std::string& info, int32_t* _aidl_return) override;
ndk::ScopedAStatus setSchedAssistImptTask(const std::string& impt_info) override;
ndk::ScopedAStatus setSchedAssistScene(const std::string& scene_id) override;
ndk::ScopedAStatus setSlideboost(const std::string& boost) override;
ndk::ScopedAStatus setTpdID(const std::string& param, int32_t* _aidl_return) override;
ndk::ScopedAStatus setTpdSerialParams(const std::string& params,
int32_t* _aidl_return) override;
ndk::ScopedAStatus setWakeSeedThread(const std::string& tid, bool identify_type, bool inUid,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writeClmEnable(const std::string& buffer) override;
ndk::ScopedAStatus writeClmHighLoadAll(const std::string& buffer) override;
ndk::ScopedAStatus writeClmHighLoadGrp(const std::string& buffer) override;
ndk::ScopedAStatus writeClmLowLoadGrp(const std::string& buffer) override;
ndk::ScopedAStatus writeDBacktrace(const std::string& buffer) override;
ndk::ScopedAStatus writeFgFreqsThreshold(const std::string& buffer) override;
ndk::ScopedAStatus writeIOBacktrace(const std::string& buffer) override;
ndk::ScopedAStatus writeJankTaskTrackEnable(bool enable) override;
ndk::ScopedAStatus writeKmallocDebugCreate(int32_t kcreate, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeKmallocDebugCreateWithType(const std::string& type,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writeMemMonitor(const std::string& buffer, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeMemleakDetectThread(int32_t memdect, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeMonitorStatus(const std::string& buffer,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writeNandswapProc(const std::string& inProc, const std::string& cmd,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writeOplusReserve3(int32_t offset, int32_t len, const std::string& info,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writePidsSet(const std::string& buffer) override;
ndk::ScopedAStatus writeSchedInfoThreshold(const std::string& buffer) override;
ndk::ScopedAStatus writeStorageFeature(const std::string& name, const std::string& addr,
const std::string& isMulti, const std::string& cmd,
int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTaskSchedInfo(const std::string& buffer) override;
ndk::ScopedAStatus writeTidsSet(const std::string& buffer) override;
ndk::ScopedAStatus writeTmemoryCapacity(int32_t param, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTmemoryFlushBusy(int32_t param, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTmemoryFlushIdle(int32_t param, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTmemoryHighWaterRatio(int32_t param, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTmemoryMemory(const std::string& str, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeTmemorySwitch(int32_t param, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeUxState(const std::string& ux_state, const std::string& pid,
const std::string& tid, int32_t* _aidl_return) override;
ndk::ScopedAStatus writeVaFeature(int32_t vafeature, int32_t* _aidl_return) override;
};
} // namespace performance
} // namespace hardware
} // namespace oplus
} // namespace vendor
} // namespace aidl

View File

@@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
#include "Performance.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
using ::aidl::vendor::oplus::hardware::performance::Performance;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<Performance> performance = ndk::SharedRefBase::make<Performance>();
const std::string instance = std::string() + Performance::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(performance->asBinder().get(), instance.c_str());
CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}

View File

@@ -0,0 +1,4 @@
service oplus.performance.hal.service /vendor/bin/hw/vendor.oplus.hardware.performance-service
class hal
user system
group system

View File

@@ -0,0 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>vendor.oplus.hardware.performance</name>
<version>1</version>
<fqname>IPerformance/default</fqname>
</hal>
</manifest>

1
aidl/sensors/.clang-format Symbolic link
View File

@@ -0,0 +1 @@
../../../../build/soong/scripts/system-clang-format

57
aidl/sensors/Android.bp Normal file
View File

@@ -0,0 +1,57 @@
//
// Copyright (C) 2021 The Android Open Source 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 {
// See: http://go/android-license-faq
default_applicable_licenses: ["Android-Apache-2.0"],
}
cc_binary {
name: "android.hardware.sensors-service.oplus-multihal",
vendor: true,
relative_install_path: "hw",
srcs: [
"service.cpp",
"HalProxy.cpp",
"HalProxyCallback.cpp",
],
header_libs: [
"android.hardware.sensors@2.X-multihal.header",
"android.hardware.sensors@2.X-shared-utils",
],
init_rc: ["android.hardware.sensors-service.oplus-multihal.rc"],
vintf_fragments: ["android.hardware.sensors.oplus-multihal.xml"],
shared_libs: [
"android.hardware.sensors@2.0-ScopedWakelock",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"android.hardware.sensors-V3-ndk",
"libbase",
"libcutils",
"libfmq",
"liblog",
"libpower",
"libutils",
"libbinder_ndk",
"libhidlbase",
],
static_libs: [
"libaidlcommonsupport",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.X-multihal",
"android.hardware.sensors@aidl-multihal",
],
}

810
aidl/sensors/HalProxy.cpp Normal file
View File

@@ -0,0 +1,810 @@
/*
* Copyright (C) 2019 The Android Open Source 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.
*/
#include "HalProxy.h"
#include <android/hardware/sensors/2.0/types.h>
#include <android-base/file.h>
#include "hardware_legacy/power.h"
#include <dlfcn.h>
#include <cinttypes>
#include <cmath>
#include <fstream>
#include <functional>
#include <thread>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using ::android::hardware::sensors::V2_0::implementation::getTimeNow;
using ::android::hardware::sensors::V2_0::implementation::kWakelockTimeoutNs;
typedef V2_0::implementation::ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
typedef V2_1::implementation::ISensorsSubHal*(SensorsHalGetSubHalV2_1Func)(uint32_t*);
static constexpr int32_t kBitsAfterSubHalIndex = 24;
/**
* Set the subhal index as first byte of sensor handle and return this modified version.
*
* @param sensorHandle The sensor handle to modify.
* @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to.
*
* @return The modified sensor handle.
*/
int32_t setSubHalIndex(int32_t sensorHandle, size_t subHalIndex) {
return sensorHandle | (static_cast<int32_t>(subHalIndex) << kBitsAfterSubHalIndex);
}
/**
* Extract the subHalIndex from sensorHandle.
*
* @param sensorHandle The sensorHandle to extract from.
*
* @return The subhal index.
*/
size_t extractSubHalIndex(int32_t sensorHandle) {
return static_cast<size_t>(sensorHandle >> kBitsAfterSubHalIndex);
}
/**
* Convert nanoseconds to milliseconds.
*
* @param nanos The nanoseconds input.
*
* @return The milliseconds count.
*/
int64_t msFromNs(int64_t nanos) {
constexpr int64_t nanosecondsInAMillsecond = 1000000;
return nanos / nanosecondsInAMillsecond;
}
bool patchOplusGlanceSensor(V2_1::SensorInfo& sensor) {
if (sensor.typeAsString != "qti.sensor.amd") {
return true;
}
/*
* Implement only the wake-up version of this sensor.
*/
if (!(sensor.flags & V1_0::SensorFlagBits::WAKE_UP)) {
return false;
}
sensor.type = V2_1::SensorType::GLANCE_GESTURE;
sensor.typeAsString = SENSOR_STRING_TYPE_GLANCE_GESTURE;
sensor.maxRange = 2;
return true;
}
bool patchOplusPickupSensor(V2_1::SensorInfo& sensor) {
if (sensor.typeAsString != "android.sensor.tilt_detector") {
return true;
}
/*
* Implement only the wake-up version of this sensor.
*/
if (!(sensor.flags & V1_0::SensorFlagBits::WAKE_UP)) {
return false;
}
sensor.type = V2_1::SensorType::PICK_UP_GESTURE;
sensor.typeAsString = SENSOR_STRING_TYPE_PICK_UP_GESTURE;
sensor.maxRange = 1;
return true;
}
HalProxy::HalProxy() {
static const std::string kMultiHalConfigFiles[] = {"/vendor/etc/sensors/hals.conf",
"/odm/etc/sensors/hals.conf"};
for (const std::string& configFile : kMultiHalConfigFiles) {
initializeSubHalListFromConfigFile(configFile.c_str());
}
init();
}
HalProxy::HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList) {
for (ISensorsSubHalV2_0* subHal : subHalList) {
mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
}
init();
}
HalProxy::HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList,
std::vector<ISensorsSubHalV2_1*>& subHalListV2_1) {
for (ISensorsSubHalV2_0* subHal : subHalList) {
mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
}
for (ISensorsSubHalV2_1* subHal : subHalListV2_1) {
mSubHalList.push_back(std::make_unique<SubHalWrapperV2_1>(subHal));
}
init();
}
HalProxy::~HalProxy() {
stopThreads();
}
Return<void> HalProxy::getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb) {
std::vector<V2_1::SensorInfo> sensors;
for (const auto& iter : mSensors) {
sensors.push_back(iter.second);
}
_hidl_cb(sensors);
return Void();
}
Return<void> HalProxy::getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) {
std::vector<V1_0::SensorInfo> sensors;
for (const auto& iter : mSensors) {
if (iter.second.type != SensorType::HINGE_ANGLE) {
sensors.push_back(convertToOldSensorInfo(iter.second));
}
}
_hidl_cb(sensors);
return Void();
}
Return<Result> HalProxy::setOperationMode(OperationMode mode) {
Result result = Result::OK;
size_t subHalIndex;
for (subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
result = mSubHalList[subHalIndex]->setOperationMode(mode);
if (result != Result::OK) {
ALOGE("setOperationMode failed for SubHal: %s",
mSubHalList[subHalIndex]->getName().c_str());
break;
}
}
if (result != Result::OK) {
// Reset the subhal operation modes that have been flipped
for (size_t i = 0; i < subHalIndex; i++) {
mSubHalList[i]->setOperationMode(mCurrentOperationMode);
}
} else {
mCurrentOperationMode = mode;
}
return result;
}
Return<Result> HalProxy::activate(int32_t sensorHandle, bool enabled) {
if (!isSubHalIndexValid(sensorHandle)) {
return Result::BAD_VALUE;
}
return getSubHalForSensorHandle(sensorHandle)
->activate(clearSubHalIndex(sensorHandle), enabled);
}
Return<Result> HalProxy::initialize_2_1(
const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) {
sp<ISensorsCallbackWrapperBase> dynamicCallback =
new ISensorsCallbackWrapperV2_1(sensorsCallback);
// Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
auto eventQueue =
std::make_unique<EventMessageQueueV2_1>(eventQueueDescriptor, true /* resetPointers */);
std::unique_ptr<EventMessageQueueWrapperBase> queue =
std::make_unique<EventMessageQueueWrapperV2_1>(eventQueue);
// Create the Wake Lock FMQ from the wakeLockDescriptor. Reset the read/write positions.
auto hidlWakeLockQueue =
std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
std::unique_ptr<WakeLockMessageQueueWrapperBase> wakeLockQueue =
std::make_unique<WakeLockMessageQueueWrapperHidl>(hidlWakeLockQueue);
return initializeCommon(queue, wakeLockQueue, dynamicCallback);
}
Return<Result> HalProxy::initialize(
const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_0::ISensorsCallback>& sensorsCallback) {
sp<ISensorsCallbackWrapperBase> dynamicCallback =
new ISensorsCallbackWrapperV2_0(sensorsCallback);
// Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
auto eventQueue =
std::make_unique<EventMessageQueueV2_0>(eventQueueDescriptor, true /* resetPointers */);
std::unique_ptr<EventMessageQueueWrapperBase> queue =
std::make_unique<EventMessageQueueWrapperV1_0>(eventQueue);
// Create the Wake Lock FMQ from the wakeLockDescriptor. Reset the read/write positions.
auto hidlWakeLockQueue =
std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
std::unique_ptr<WakeLockMessageQueueWrapperBase> wakeLockQueue =
std::make_unique<WakeLockMessageQueueWrapperHidl>(hidlWakeLockQueue);
return initializeCommon(queue, wakeLockQueue, dynamicCallback);
}
Return<Result> HalProxy::initializeCommon(
std::unique_ptr<EventMessageQueueWrapperBase>& eventQueue,
std::unique_ptr<WakeLockMessageQueueWrapperBase>& wakeLockQueue,
const sp<ISensorsCallbackWrapperBase>& sensorsCallback) {
Result result = Result::OK;
stopThreads();
resetSharedWakelock();
// So that the pending write events queue can be cleared safely and when we start threads
// again we do not get new events until after initialize resets the subhals.
disableAllSensors();
// Clears the queue if any events were pending write before.
mPendingWriteEventsQueue = std::queue<std::pair<std::vector<V2_1::Event>, size_t>>();
mSizePendingWriteEventsQueue = 0;
// Clears previously connected dynamic sensors
mDynamicSensors.clear();
mDynamicSensorsCallback = sensorsCallback;
// Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
mEventQueue = std::move(eventQueue);
// Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
// events have been successfully read and handled by the framework.
mWakeLockQueue = std::move(wakeLockQueue);
if (mEventQueueFlag != nullptr) {
EventFlag::deleteEventFlag(&mEventQueueFlag);
}
if (mWakelockQueueFlag != nullptr) {
EventFlag::deleteEventFlag(&mWakelockQueueFlag);
}
if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
result = Result::BAD_VALUE;
}
if (EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakelockQueueFlag) != OK) {
result = Result::BAD_VALUE;
}
if (!mDynamicSensorsCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
result = Result::BAD_VALUE;
}
mThreadsRun.store(true);
mPendingWritesThread = std::thread(startPendingWritesThread, this);
mWakelockThread = std::thread(startWakelockThread, this);
for (size_t i = 0; i < mSubHalList.size(); i++) {
Result currRes = mSubHalList[i]->initialize(this, this, i);
if (currRes != Result::OK) {
result = currRes;
ALOGE("Subhal '%s' failed to initialize with reason %" PRId32 ".",
mSubHalList[i]->getName().c_str(), static_cast<int32_t>(currRes));
}
}
mCurrentOperationMode = OperationMode::NORMAL;
return result;
}
Return<Result> HalProxy::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t maxReportLatencyNs) {
if (!isSubHalIndexValid(sensorHandle)) {
return Result::BAD_VALUE;
}
return getSubHalForSensorHandle(sensorHandle)
->batch(clearSubHalIndex(sensorHandle), samplingPeriodNs, maxReportLatencyNs);
}
Return<Result> HalProxy::flush(int32_t sensorHandle) {
if (!isSubHalIndexValid(sensorHandle)) {
return Result::BAD_VALUE;
}
return getSubHalForSensorHandle(sensorHandle)->flush(clearSubHalIndex(sensorHandle));
}
Return<Result> HalProxy::injectSensorData_2_1(const V2_1::Event& event) {
return injectSensorData(convertToOldEvent(event));
}
Return<Result> HalProxy::injectSensorData(const V1_0::Event& event) {
Result result = Result::OK;
if (mCurrentOperationMode == OperationMode::NORMAL &&
event.sensorType != V1_0::SensorType::ADDITIONAL_INFO) {
ALOGE("An event with type != ADDITIONAL_INFO passed to injectSensorData while operation"
" mode was NORMAL.");
result = Result::BAD_VALUE;
}
if (result == Result::OK) {
V1_0::Event subHalEvent = event;
if (!isSubHalIndexValid(event.sensorHandle)) {
return Result::BAD_VALUE;
}
subHalEvent.sensorHandle = clearSubHalIndex(event.sensorHandle);
result = getSubHalForSensorHandle(event.sensorHandle)
->injectSensorData(convertToNewEvent(subHalEvent));
}
return result;
}
Return<void> HalProxy::registerDirectChannel(const SharedMemInfo& mem,
ISensorsV2_0::registerDirectChannel_cb _hidl_cb) {
if (mDirectChannelSubHal == nullptr) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
} else {
mDirectChannelSubHal->registerDirectChannel(mem, _hidl_cb);
}
return Return<void>();
}
Return<Result> HalProxy::unregisterDirectChannel(int32_t channelHandle) {
Result result;
if (mDirectChannelSubHal == nullptr) {
result = Result::INVALID_OPERATION;
} else {
result = mDirectChannelSubHal->unregisterDirectChannel(channelHandle);
}
return result;
}
Return<void> HalProxy::configDirectReport(int32_t sensorHandle, int32_t channelHandle,
RateLevel rate,
ISensorsV2_0::configDirectReport_cb _hidl_cb) {
if (mDirectChannelSubHal == nullptr) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* reportToken */);
} else if (sensorHandle == -1 && rate != RateLevel::STOP) {
_hidl_cb(Result::BAD_VALUE, -1 /* reportToken */);
} else {
// -1 denotes all sensors should be disabled
if (sensorHandle != -1) {
sensorHandle = clearSubHalIndex(sensorHandle);
}
mDirectChannelSubHal->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
}
return Return<void>();
}
Return<void> HalProxy::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
ALOGE("%s: missing fd for writing", __FUNCTION__);
return Void();
}
int writeFd = fd->data[0];
std::ostringstream stream;
stream << "===HalProxy===" << std::endl;
stream << "Internal values:" << std::endl;
stream << " Threads are running: " << (mThreadsRun.load() ? "true" : "false") << std::endl;
int64_t now = getTimeNow();
stream << " Wakelock timeout start time: " << msFromNs(now - mWakelockTimeoutStartTime)
<< " ms ago" << std::endl;
stream << " Wakelock timeout reset time: " << msFromNs(now - mWakelockTimeoutResetTime)
<< " ms ago" << std::endl;
// TODO(b/142969448): Add logging for history of wakelock acquisition per subhal.
stream << " Wakelock ref count: " << mWakelockRefCount << std::endl;
stream << " # of events on pending write writes queue: " << mSizePendingWriteEventsQueue
<< std::endl;
stream << " Most events seen on pending write events queue: "
<< mMostEventsObservedPendingWriteEventsQueue << std::endl;
if (!mPendingWriteEventsQueue.empty()) {
stream << " Size of events list on front of pending writes queue: "
<< mPendingWriteEventsQueue.front().first.size() << std::endl;
}
stream << " # of non-dynamic sensors across all subhals: " << mSensors.size() << std::endl;
stream << " # of dynamic sensors across all subhals: " << mDynamicSensors.size() << std::endl;
stream << "SubHals (" << mSubHalList.size() << "):" << std::endl;
for (auto& subHal : mSubHalList) {
stream << " Name: " << subHal->getName() << std::endl;
stream << " Debug dump: " << std::endl;
android::base::WriteStringToFd(stream.str(), writeFd);
subHal->debug(fd, args);
stream.str("");
stream << std::endl;
}
android::base::WriteStringToFd(stream.str(), writeFd);
return Return<void>();
}
Return<void> HalProxy::onDynamicSensorsConnected(const hidl_vec<SensorInfo>& dynamicSensorsAdded,
int32_t subHalIndex) {
std::vector<SensorInfo> sensors;
{
std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
for (SensorInfo sensor : dynamicSensorsAdded) {
if (!subHalIndexIsClear(sensor.sensorHandle)) {
ALOGE("Dynamic sensor added %s had sensorHandle with first byte not 0.",
sensor.name.c_str());
} else {
sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex);
mDynamicSensors[sensor.sensorHandle] = sensor;
sensors.push_back(sensor);
}
}
}
mDynamicSensorsCallback->onDynamicSensorsConnected(sensors);
return Return<void>();
}
Return<void> HalProxy::onDynamicSensorsDisconnected(
const hidl_vec<int32_t>& dynamicSensorHandlesRemoved, int32_t subHalIndex) {
// TODO(b/143302327): Block this call until all pending events are flushed from queue
std::vector<int32_t> sensorHandles;
{
std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
for (int32_t sensorHandle : dynamicSensorHandlesRemoved) {
if (!subHalIndexIsClear(sensorHandle)) {
ALOGE("Dynamic sensorHandle removed had first byte not 0.");
} else {
sensorHandle = setSubHalIndex(sensorHandle, subHalIndex);
if (mDynamicSensors.find(sensorHandle) != mDynamicSensors.end()) {
mDynamicSensors.erase(sensorHandle);
sensorHandles.push_back(sensorHandle);
}
}
}
}
mDynamicSensorsCallback->onDynamicSensorsDisconnected(sensorHandles);
return Return<void>();
}
void HalProxy::initializeSubHalListFromConfigFile(const char* configFileName) {
std::ifstream subHalConfigStream(configFileName);
if (!subHalConfigStream) {
ALOGE("Failed to load subHal config file: %s", configFileName);
} else {
std::string subHalLibraryFile;
while (subHalConfigStream >> subHalLibraryFile) {
void* handle = getHandleForSubHalSharedObject(subHalLibraryFile);
if (handle == nullptr) {
ALOGE("dlopen failed for library: %s", subHalLibraryFile.c_str());
} else {
SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
(SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
if (sensorsHalGetSubHalPtr != nullptr) {
std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
*sensorsHalGetSubHalPtr;
uint32_t version;
ISensorsSubHalV2_0* subHal = sensorsHalGetSubHal(&version);
if (version != SUB_HAL_2_0_VERSION) {
ALOGE("SubHal version was not 2.0 for library: %s",
subHalLibraryFile.c_str());
} else {
ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
}
} else {
SensorsHalGetSubHalV2_1Func* getSubHalV2_1Ptr =
(SensorsHalGetSubHalV2_1Func*)dlsym(handle, "sensorsHalGetSubHal_2_1");
if (getSubHalV2_1Ptr == nullptr) {
ALOGE("Failed to locate sensorsHalGetSubHal function for library: %s",
subHalLibraryFile.c_str());
} else {
std::function<SensorsHalGetSubHalV2_1Func> sensorsHalGetSubHal_2_1 =
*getSubHalV2_1Ptr;
uint32_t version;
ISensorsSubHalV2_1* subHal = sensorsHalGetSubHal_2_1(&version);
if (version != SUB_HAL_2_1_VERSION) {
ALOGE("SubHal version was not 2.1 for library: %s",
subHalLibraryFile.c_str());
} else {
ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
mSubHalList.push_back(std::make_unique<SubHalWrapperV2_1>(subHal));
}
}
}
}
}
}
}
void HalProxy::initializeSensorList() {
for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
auto result = mSubHalList[subHalIndex]->getSensorsList([&](const auto& list) {
for (SensorInfo sensor : list) {
if (!subHalIndexIsClear(sensor.sensorHandle)) {
ALOGE("SubHal sensorHandle's first byte was not 0");
} else {
ALOGV("Loaded sensor: %s", sensor.name.c_str());
sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex);
setDirectChannelFlags(&sensor, mSubHalList[subHalIndex]);
bool keep = patchOplusPickupSensor(sensor) && patchOplusGlanceSensor(sensor);
if (!keep) {
continue;
}
mSensors[sensor.sensorHandle] = sensor;
}
}
});
if (!result.isOk()) {
ALOGE("getSensorsList call failed for SubHal: %s",
mSubHalList[subHalIndex]->getName().c_str());
}
}
}
void* HalProxy::getHandleForSubHalSharedObject(const std::string& filename) {
static const std::string kSubHalShareObjectLocations[] = {
"", // Default locations will be searched
#ifdef __LP64__
"/vendor/lib64/hw/", "/odm/lib64/hw/"
#else
"/vendor/lib/hw/", "/odm/lib/hw/"
#endif
};
for (const std::string& dir : kSubHalShareObjectLocations) {
void* handle = dlopen((dir + filename).c_str(), RTLD_NOW);
if (handle != nullptr) {
return handle;
}
}
return nullptr;
}
void HalProxy::init() {
initializeSensorList();
}
void HalProxy::stopThreads() {
mThreadsRun.store(false);
if (mEventQueueFlag != nullptr && mEventQueue != nullptr) {
size_t numToRead = mEventQueue->availableToRead();
std::vector<Event> events(numToRead);
mEventQueue->read(events.data(), numToRead);
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ));
}
if (mWakelockQueueFlag != nullptr && mWakeLockQueue != nullptr) {
uint32_t kZero = 0;
mWakeLockQueue->write(&kZero);
mWakelockQueueFlag->wake(static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN));
}
mWakelockCV.notify_one();
mEventQueueWriteCV.notify_one();
if (mPendingWritesThread.joinable()) {
mPendingWritesThread.join();
}
if (mWakelockThread.joinable()) {
mWakelockThread.join();
}
}
void HalProxy::disableAllSensors() {
for (const auto& sensorEntry : mSensors) {
int32_t sensorHandle = sensorEntry.first;
activate(sensorHandle, false /* enabled */);
}
std::lock_guard<std::mutex> dynamicSensorsLock(mDynamicSensorsMutex);
for (const auto& sensorEntry : mDynamicSensors) {
int32_t sensorHandle = sensorEntry.first;
activate(sensorHandle, false /* enabled */);
}
}
void HalProxy::startPendingWritesThread(HalProxy* halProxy) {
halProxy->handlePendingWrites();
}
void HalProxy::handlePendingWrites() {
// TODO(b/143302327): Find a way to optimize locking strategy maybe using two mutexes instead of
// one.
std::unique_lock<std::mutex> lock(mEventQueueWriteMutex);
while (mThreadsRun.load()) {
mEventQueueWriteCV.wait(
lock, [&] { return !mPendingWriteEventsQueue.empty() || !mThreadsRun.load(); });
if (mThreadsRun.load()) {
std::vector<Event>& pendingWriteEvents = mPendingWriteEventsQueue.front().first;
size_t numWakeupEvents = mPendingWriteEventsQueue.front().second;
size_t eventQueueSize = mEventQueue->getQuantumCount();
size_t numToWrite = std::min(pendingWriteEvents.size(), eventQueueSize);
lock.unlock();
if (!mEventQueue->writeBlocking(
pendingWriteEvents.data(), numToWrite,
static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ),
static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS),
kPendingWriteTimeoutNs, mEventQueueFlag)) {
ALOGE("Dropping %zu events after blockingWrite failed.", numToWrite);
if (numWakeupEvents > 0) {
if (pendingWriteEvents.size() > eventQueueSize) {
decrementRefCountAndMaybeReleaseWakelock(
countNumWakeupEvents(pendingWriteEvents, eventQueueSize));
} else {
decrementRefCountAndMaybeReleaseWakelock(numWakeupEvents);
}
}
}
lock.lock();
mSizePendingWriteEventsQueue -= numToWrite;
if (pendingWriteEvents.size() > eventQueueSize) {
// TODO(b/143302327): Check if this erase operation is too inefficient. It will copy
// all the events ahead of it down to fill gap off array at front after the erase.
pendingWriteEvents.erase(pendingWriteEvents.begin(),
pendingWriteEvents.begin() + eventQueueSize);
} else {
mPendingWriteEventsQueue.pop();
}
}
}
}
void HalProxy::startWakelockThread(HalProxy* halProxy) {
halProxy->handleWakelocks();
}
void HalProxy::handleWakelocks() {
std::unique_lock<std::recursive_mutex> lock(mWakelockMutex);
while (mThreadsRun.load()) {
mWakelockCV.wait(lock, [&] { return mWakelockRefCount > 0 || !mThreadsRun.load(); });
if (mThreadsRun.load()) {
int64_t timeLeft;
if (sharedWakelockDidTimeout(&timeLeft)) {
resetSharedWakelock();
} else {
uint32_t numWakeLocksProcessed;
lock.unlock();
bool success = mWakeLockQueue->readBlocking(
&numWakeLocksProcessed, 1, 0,
static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN), timeLeft);
lock.lock();
if (success) {
decrementRefCountAndMaybeReleaseWakelock(
static_cast<size_t>(numWakeLocksProcessed));
}
}
}
}
resetSharedWakelock();
}
bool HalProxy::sharedWakelockDidTimeout(int64_t* timeLeft) {
bool didTimeout;
int64_t duration = getTimeNow() - mWakelockTimeoutStartTime;
if (duration > kWakelockTimeoutNs) {
didTimeout = true;
} else {
didTimeout = false;
*timeLeft = kWakelockTimeoutNs - duration;
}
return didTimeout;
}
void HalProxy::resetSharedWakelock() {
std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex);
decrementRefCountAndMaybeReleaseWakelock(mWakelockRefCount);
mWakelockTimeoutResetTime = getTimeNow();
}
void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents,
V2_0::implementation::ScopedWakelock wakelock) {
size_t numToWrite = 0;
std::lock_guard<std::mutex> lock(mEventQueueWriteMutex);
if (wakelock.isLocked()) {
incrementRefCountAndMaybeAcquireWakelock(numWakeupEvents);
}
if (mPendingWriteEventsQueue.empty()) {
numToWrite = std::min(events.size(), mEventQueue->availableToWrite());
if (numToWrite > 0) {
if (mEventQueue->write(events.data(), numToWrite)) {
// TODO(b/143302327): While loop if mEventQueue->avaiableToWrite > 0 to possibly fit
// in more writes immediately
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
} else {
numToWrite = 0;
}
}
}
size_t numLeft = events.size() - numToWrite;
if (numToWrite < events.size() &&
mSizePendingWriteEventsQueue + numLeft <= kMaxSizePendingWriteEventsQueue) {
std::vector<Event> eventsLeft(events.begin() + numToWrite, events.end());
mPendingWriteEventsQueue.push({eventsLeft, numWakeupEvents});
mSizePendingWriteEventsQueue += numLeft;
mMostEventsObservedPendingWriteEventsQueue =
std::max(mMostEventsObservedPendingWriteEventsQueue, mSizePendingWriteEventsQueue);
mEventQueueWriteCV.notify_one();
}
}
bool HalProxy::incrementRefCountAndMaybeAcquireWakelock(size_t delta,
int64_t* timeoutStart /* = nullptr */) {
if (!mThreadsRun.load()) return false;
std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex);
if (mWakelockRefCount == 0) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakelockName);
mWakelockCV.notify_one();
}
mWakelockTimeoutStartTime = getTimeNow();
mWakelockRefCount += delta;
if (timeoutStart != nullptr) {
*timeoutStart = mWakelockTimeoutStartTime;
}
return true;
}
void HalProxy::decrementRefCountAndMaybeReleaseWakelock(size_t delta,
int64_t timeoutStart /* = -1 */) {
if (!mThreadsRun.load()) return;
std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex);
if (delta > mWakelockRefCount) {
ALOGE("Decrementing wakelock ref count by %zu when count is %zu",
delta, mWakelockRefCount);
}
if (timeoutStart == -1) timeoutStart = mWakelockTimeoutResetTime;
if (mWakelockRefCount == 0 || timeoutStart < mWakelockTimeoutResetTime) return;
mWakelockRefCount -= std::min(mWakelockRefCount, delta);
if (mWakelockRefCount == 0) {
release_wake_lock(kWakelockName);
}
}
void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo,
std::shared_ptr<ISubHalWrapperBase> subHal) {
bool sensorSupportsDirectChannel =
(sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL)) != 0;
if (mDirectChannelSubHal == nullptr && sensorSupportsDirectChannel) {
mDirectChannelSubHal = subHal;
} else if (mDirectChannelSubHal != nullptr && subHal != mDirectChannelSubHal) {
// disable direct channel capability for sensors in subHals that are not
// the only one we will enable
sensorInfo->flags &= ~(V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL);
}
}
std::shared_ptr<ISubHalWrapperBase> HalProxy::getSubHalForSensorHandle(int32_t sensorHandle) {
return mSubHalList[extractSubHalIndex(sensorHandle)];
}
bool HalProxy::isSubHalIndexValid(int32_t sensorHandle) {
return extractSubHalIndex(sensorHandle) < mSubHalList.size();
}
size_t HalProxy::countNumWakeupEvents(const std::vector<Event>& events, size_t n) {
size_t numWakeupEvents = 0;
for (size_t i = 0; i < n; i++) {
int32_t sensorHandle = events[i].sensorHandle;
if (mSensors[sensorHandle].flags & static_cast<uint32_t>(V1_0::SensorFlagBits::WAKE_UP)) {
numWakeupEvents++;
}
}
return numWakeupEvents;
}
int32_t HalProxy::clearSubHalIndex(int32_t sensorHandle) {
return sensorHandle & (~kSensorHandleSubHalIndexMask);
}
bool HalProxy::subHalIndexIsClear(int32_t sensorHandle) {
return (sensorHandle & kSensorHandleSubHalIndexMask) == 0;
}
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2019 The Android Open Source 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.
*/
#include "HalProxyCallback.h"
#include <cinttypes>
#include <fstream>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {
static constexpr int32_t kBitsAfterSubHalIndex = 24;
/**
* Set the subhal index as first byte of sensor handle and return this modified version.
*
* @param sensorHandle The sensor handle to modify.
* @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to.
*
* @return The modified sensor handle.
*/
int32_t setSubHalIndex(int32_t sensorHandle, size_t subHalIndex) {
return sensorHandle | (static_cast<int32_t>(subHalIndex) << kBitsAfterSubHalIndex);
}
void HalProxyCallbackBase::postEvents(const std::vector<V2_1::Event>& events,
ScopedWakelock wakelock) {
if (events.empty() || !mCallback->areThreadsRunning()) return;
size_t numWakeupEvents;
std::vector<V2_1::Event> processedEvents = processEvents(events, &numWakeupEvents);
if (numWakeupEvents > 0) {
ALOG_ASSERT(wakelock.isLocked(),
"Wakeup events posted while wakelock unlocked for subhal"
" w/ index %" PRId32 ".",
mSubHalIndex);
} else {
ALOG_ASSERT(!wakelock.isLocked(),
"No Wakeup events posted but wakelock locked for subhal"
" w/ index %" PRId32 ".",
mSubHalIndex);
}
mCallback->postEventsToMessageQueue(processedEvents, numWakeupEvents, std::move(wakelock));
}
ScopedWakelock HalProxyCallbackBase::createScopedWakelock(bool lock) {
ScopedWakelock wakelock(mRefCounter, lock);
return wakelock;
}
std::vector<V2_1::Event> HalProxyCallbackBase::processEvents(const std::vector<V2_1::Event>& events,
size_t* numWakeupEvents) const {
*numWakeupEvents = 0;
std::vector<V2_1::Event> eventsOut;
const char* aodLightModeNode = "/sys/kernel/oplus_display/aod_light_mode_set";
for (V2_1::Event event : events) {
event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex);
if (event.sensorType == V2_1::SensorType::DYNAMIC_SENSOR_META) {
event.u.dynamic.sensorHandle =
setSubHalIndex(event.u.dynamic.sensorHandle, mSubHalIndex);
}
const V2_1::SensorInfo& sensor = mCallback->getSensorInfo(event.sensorHandle);
if (sensor.type == V2_1::SensorType::GLANCE_GESTURE
&& event.u.scalar != 2) {
continue;
}
if (sensor.type == V2_1::SensorType::PICK_UP_GESTURE
&& event.u.scalar != 0) {
continue;
}
if (sensor.typeAsString == "qti.sensor.lux_aod") {
std::ofstream nodeFile(aodLightModeNode);
if (nodeFile.is_open()) {
nodeFile << !event.u.scalar;
nodeFile.close();
}
}
if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) {
(*numWakeupEvents)++;
}
eventsOut.push_back(event);
}
return eventsOut;
}
} // namespace implementation
} // namespace V2_0
} // namespace sensors
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,10 @@
on boot
chmod 666 /sys/kernel/oplus_display/aod_light_mode_set
service vendor.sensors-hal-multihal /vendor/bin/hw/android.hardware.sensors-service.oplus-multihal
class hal
user system
group system wakelock context_hub input uhid
task_profiles ServiceCapacityLow
capabilities BLOCK_SUSPEND
rlimit rtprio 10 10

View File

@@ -0,0 +1,23 @@
<!--
~ Copyright (C) 2021 The Android Open Source 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 version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.sensors</name>
<version>2</version>
<fqname>ISensors/default</fqname>
</hal>
</manifest>

36
aidl/sensors/service.cpp Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include "HalProxyAidl.h"
using ::aidl::android::hardware::sensors::implementation::HalProxyAidl;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
// Make a default multihal sensors service
auto halProxy = ndk::SharedRefBase::make<HalProxyAidl>();
const std::string halProxyName = std::string() + HalProxyAidl::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(halProxy->asBinder().get(), halProxyName.c_str());
CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}

View File

@@ -49,39 +49,38 @@ namespace android {
namespace hardware {
namespace vibrator {
#define STRONG_MAGNITUDE 0x7fff
#define MEDIUM_MAGNITUDE 0x5fff
#define LIGHT_MAGNITUDE 0x3fff
#define INVALID_VALUE -1
#define CUSTOM_DATA_LEN 3
#define NAME_BUF_SIZE 32
#define STRONG_MAGNITUDE 0x7fff
#define MEDIUM_MAGNITUDE 0x5fff
#define LIGHT_MAGNITUDE 0x3fff
#define INVALID_VALUE -1
#define CUSTOM_DATA_LEN 3
#define NAME_BUF_SIZE 32
#define MSM_CPU_LAHAINA 415
#define APQ_CPU_LAHAINA 439
#define MSM_CPU_SHIMA 450
#define MSM_CPU_SM8325 501
#define APQ_CPU_SM8325P 502
#define MSM_CPU_TARO 457
#define MSM_CPU_TARO_LTE 552
#define MSM_CPU_YUPIK 475
#define MSM_CPU_CAPE 530
#define APQ_CPU_CAPE 531
#define MSM_CPU_KALAMA 519
#define MSM_CPU_PINEAPPLE 557
#define MSM_CPU_SUN 618
#define MSM_CPU_LAHAINA 415
#define APQ_CPU_LAHAINA 439
#define MSM_CPU_SHIMA 450
#define MSM_CPU_SM8325 501
#define APQ_CPU_SM8325P 502
#define MSM_CPU_TARO 457
#define MSM_CPU_TARO_LTE 552
#define MSM_CPU_YUPIK 475
#define MSM_CPU_CAPE 530
#define APQ_CPU_CAPE 531
#define MSM_CPU_KALAMA 519
#define MSM_CPU_PINEAPPLE 557
#define MSM_CPU_SUN 618
#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8)))
#define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8)))
#define LED_DEVICE "/sys/class/leds/vibrator"
InputFFDevice::InputFFDevice()
{
DIR *dp;
FILE *fp = NULL;
struct dirent *dir;
InputFFDevice::InputFFDevice() {
DIR* dp;
FILE* fp = NULL;
struct dirent* dir;
uint8_t ffBitmask[FF_CNT / 8];
char devicename[PATH_MAX];
const char *INPUT_DIR = "/dev/input/";
const char* INPUT_DIR = "/dev/input/";
char name[NAME_BUF_SIZE];
int fd, ret;
int soc = property_get_int32("ro.vendor.qti.soc_id", -1);
@@ -101,10 +100,9 @@ InputFFDevice::InputFFDevice()
}
memset(ffBitmask, 0, sizeof(ffBitmask));
while ((dir = readdir(dp)) != NULL){
while ((dir = readdir(dp)) != NULL) {
if (dir->d_name[0] == '.' &&
(dir->d_name[1] == '\0' ||
(dir->d_name[1] == '.' && dir->d_name[2] == '\0')))
(dir->d_name[1] == '\0' || (dir->d_name[1] == '.' && dir->d_name[2] == '\0')))
continue;
snprintf(devicename, PATH_MAX, "%s%s", INPUT_DIR, dir->d_name);
@@ -135,34 +133,31 @@ InputFFDevice::InputFFDevice()
continue;
}
if (test_bit(FF_CONSTANT, ffBitmask) ||
test_bit(FF_PERIODIC, ffBitmask)) {
if (test_bit(FF_CONSTANT, ffBitmask) || test_bit(FF_PERIODIC, ffBitmask)) {
mVibraFd = fd;
if (test_bit(FF_CUSTOM, ffBitmask))
mSupportEffects = true;
if (test_bit(FF_GAIN, ffBitmask))
mSupportGain = true;
if (test_bit(FF_CUSTOM, ffBitmask)) mSupportEffects = true;
if (test_bit(FF_GAIN, ffBitmask)) mSupportGain = true;
if (soc <= 0 && (fp = fopen("/sys/devices/soc0/soc_id", "r")) != NULL) {
fscanf(fp, "%u", &soc);
fclose(fp);
}
switch (soc) {
case MSM_CPU_LAHAINA:
case APQ_CPU_LAHAINA:
case MSM_CPU_SHIMA:
case MSM_CPU_SM8325:
case APQ_CPU_SM8325P:
case MSM_CPU_TARO:
case MSM_CPU_YUPIK:
case MSM_CPU_KALAMA:
case MSM_CPU_PINEAPPLE:
case MSM_CPU_SUN:
mSupportExternalControl = true;
break;
default:
mSupportExternalControl = false;
break;
case MSM_CPU_LAHAINA:
case APQ_CPU_LAHAINA:
case MSM_CPU_SHIMA:
case MSM_CPU_SM8325:
case APQ_CPU_SM8325P:
case MSM_CPU_TARO:
case MSM_CPU_YUPIK:
case MSM_CPU_KALAMA:
case MSM_CPU_PINEAPPLE:
case MSM_CPU_SUN:
mSupportExternalControl = true;
break;
default:
mSupportExternalControl = false;
break;
}
break;
}
@@ -191,20 +186,19 @@ InputFFDevice::InputFFDevice()
* kernel driver, and the rest two parameters are used for returning
* back the real playing length from kernel driver.
*/
int InputFFDevice::play(int effectId, uint32_t timeoutMs, long *playLengthMs) {
int InputFFDevice::play(int effectId, uint32_t timeoutMs, long* playLengthMs) {
struct ff_effect effect;
struct input_event play;
int16_t data[CUSTOM_DATA_LEN] = {0, 0, 0};
int ret;
#ifdef USE_EFFECT_STREAM
const struct effect_stream *stream;
const struct effect_stream* stream;
#endif
/* For QMAA compliance, return OK even if vibrator device doesn't exist */
if (mVibraFd == INVALID_VALUE) {
if (playLengthMs != NULL)
*playLengthMs = 0;
return 0;
if (playLengthMs != NULL) *playLengthMs = 0;
return 0;
}
if (timeoutMs != 0) {
@@ -228,7 +222,7 @@ int InputFFDevice::play(int effectId, uint32_t timeoutMs, long *playLengthMs) {
#ifdef USE_EFFECT_STREAM
stream = get_effect_stream(effectId);
if (stream != NULL) {
effect.u.periodic.custom_data = (int16_t *)stream;
effect.u.periodic.custom_data = (int16_t*)stream;
effect.u.periodic.custom_len = sizeof(*stream);
}
#endif
@@ -265,8 +259,7 @@ int InputFFDevice::play(int effectId, uint32_t timeoutMs, long *playLengthMs) {
if (ret == -1) {
ALOGE("write failed, errno = %d\n", -errno);
ret = TEMP_FAILURE_RETRY(ioctl(mVibraFd, EVIOCRMFF, mCurrAppId));
if (ret == -1)
ALOGE("ioctl EVIOCRMFF failed, errno = %d", -errno);
if (ret == -1) ALOGE("ioctl EVIOCRMFF failed, errno = %d", -errno);
goto errout;
}
} else if (mCurrAppId != INVALID_VALUE) {
@@ -297,8 +290,7 @@ int InputFFDevice::setAmplitude(uint8_t amplitude) {
struct input_event ie;
/* For QMAA compliance, return OK even if vibrator device doesn't exist */
if (mVibraFd == INVALID_VALUE)
return 0;
if (mVibraFd == INVALID_VALUE) return 0;
tmp = amplitude * (STRONG_MAGNITUDE - LIGHT_MAGNITUDE) / 255;
tmp += LIGHT_MAGNITUDE;
@@ -316,19 +308,19 @@ int InputFFDevice::setAmplitude(uint8_t amplitude) {
return 0;
}
int InputFFDevice::playEffect(int effectId, EffectStrength es, long *playLengthMs) {
int InputFFDevice::playEffect(int effectId, EffectStrength es, long* playLengthMs) {
switch (es) {
case EffectStrength::LIGHT:
mCurrMagnitude = LIGHT_MAGNITUDE;
break;
case EffectStrength::MEDIUM:
mCurrMagnitude = MEDIUM_MAGNITUDE;
break;
case EffectStrength::STRONG:
mCurrMagnitude = STRONG_MAGNITUDE;
break;
default:
return -1;
case EffectStrength::LIGHT:
mCurrMagnitude = LIGHT_MAGNITUDE;
break;
case EffectStrength::MEDIUM:
mCurrMagnitude = MEDIUM_MAGNITUDE;
break;
case EffectStrength::STRONG:
mCurrMagnitude = STRONG_MAGNITUDE;
break;
default:
return -1;
}
return play(effectId, INVALID_VALUE, playLengthMs);
@@ -350,7 +342,7 @@ LedVibratorDevice::LedVibratorDevice() {
mDetected = true;
}
int LedVibratorDevice::write_value(const char *file, const char *value) {
int LedVibratorDevice::write_value(const char* file, const char* value) {
int fd;
int ret;
@@ -379,7 +371,7 @@ int LedVibratorDevice::write_value(const char *file, const char *value) {
return ret;
}
int LedVibratorDevice::write_value(const char *file, int value) {
int LedVibratorDevice::write_value(const char* file, int value) {
return write_value(file, std::to_string(value).c_str());
}
@@ -396,6 +388,7 @@ int LedVibratorDevice::on(int32_t timeoutMs) {
ret |= write_value(LED_DEVICE "/duration", timeoutMs);
ret |= write_value(LED_DEVICE "/state", "1");
ret |= write_value(LED_DEVICE "/activate", "1");
usleep(100 * 1000);
ret |= write_value(LED_DEVICE "/activate", "0");
return ret;
@@ -403,16 +396,13 @@ int LedVibratorDevice::on(int32_t timeoutMs) {
int LedVibratorDevice::onWaveform(int waveformIndex) {
int ret = 0;
ret |= write_value(LED_DEVICE "/rtp", "0");
ret |= write_value(LED_DEVICE "/vmax", "1600");
ret |= write_value(LED_DEVICE "/waveform_index", waveformIndex);
ret |= write_value(LED_DEVICE "/brightness", "1");
ret |= write_value(LED_DEVICE "/rtp", "0");
return ret;
}
int LedVibratorDevice::off()
{
int LedVibratorDevice::off() {
char file[PATH_MAX];
int ret;
@@ -430,12 +420,9 @@ ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
return ndk::ScopedAStatus::ok();
}
if (ff.mSupportGain)
*_aidl_return |= IVibrator::CAP_AMPLITUDE_CONTROL;
if (ff.mSupportEffects)
*_aidl_return |= IVibrator::CAP_PERFORM_CALLBACK;
if (ff.mSupportExternalControl)
*_aidl_return |= IVibrator::CAP_EXTERNAL_CONTROL;
if (ff.mSupportGain) *_aidl_return |= IVibrator::CAP_AMPLITUDE_CONTROL;
if (ff.mSupportEffects) *_aidl_return |= IVibrator::CAP_PERFORM_CALLBACK;
if (ff.mSupportExternalControl) *_aidl_return |= IVibrator::CAP_EXTERNAL_CONTROL;
ALOGD("QTI Vibrator reporting capabilities: %d", *_aidl_return);
return ndk::ScopedAStatus::ok();
@@ -449,8 +436,7 @@ ndk::ScopedAStatus Vibrator::off() {
ret = ledVib.off();
else
ret = ff.off();
if (ret != 0)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
if (ret != 0) return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
return ndk::ScopedAStatus::ok();
}
@@ -465,8 +451,7 @@ ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
else
ret = ff.on(timeoutMs);
if (ret != 0)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
if (ret != 0) return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
if (callback != nullptr) {
std::thread([=] {
@@ -482,7 +467,9 @@ ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es, const std::shared_ptr<IVibratorCallback>& callback, int32_t* _aidl_return) {
ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es,
const std::shared_ptr<IVibratorCallback>& callback,
int32_t* _aidl_return) {
long playLengthMs;
int ret;
@@ -490,64 +477,50 @@ ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es, const std
if (ledVib.mDetected) {
switch (effect) {
case Effect::CLICK:
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
case Effect::CLICK:
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
break;
case Effect::DOUBLE_CLICK:
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
break;
case Effect::TICK:
ledVib.write_value(LED_DEVICE "/vmax", "1400");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
break;
case Effect::HEAVY_CLICK:
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "4");
break;
case Effect::TEXTURE_TICK:
ledVib.write_value(LED_DEVICE "/vmax", "60");
ledVib.write_value(LED_DEVICE "/waveform_index", "2");
break;
default:
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
if (effect == Effect::DOUBLE_CLICK) {
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
break;
case Effect::DOUBLE_CLICK:
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
usleep(100 * 1000);
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
break;
case Effect::TICK:
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "1400");
ledVib.write_value(LED_DEVICE "/waveform_index", "1");
} else {
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
break;
case Effect::HEAVY_CLICK:
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "2500");
ledVib.write_value(LED_DEVICE "/waveform_index", "4");
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
break;
case Effect::TEXTURE_TICK:
ledVib.write_value(LED_DEVICE "/rtp", "0");
ledVib.write_value(LED_DEVICE "/vmax", "60");
ledVib.write_value(LED_DEVICE "/waveform_index", "2");
ledVib.write_value(LED_DEVICE "/brightness", "1");
ledVib.write_value(LED_DEVICE "/rtp", "0");
break;
default:
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
// Return magic value for play length so that we won't end up calling on() / off()
playLengthMs = 150;
} else {
if (effect < Effect::CLICK || effect > Effect::HEAVY_CLICK)
if (effect < Effect::CLICK || effect > Effect::HEAVY_CLICK)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
if (es != EffectStrength::LIGHT && es != EffectStrength::MEDIUM &&
es != EffectStrength::STRONG)
es != EffectStrength::STRONG)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
ret = ff.playEffect((static_cast<int>(effect)), es, &playLengthMs);
if (ret != 0)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
if (ret != 0) return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
}
if (callback != nullptr) {
@@ -568,8 +541,8 @@ ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_retu
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::HEAVY_CLICK,
Effect::TEXTURE_TICK};
} else {
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD,
Effect::POP, Effect::HEAVY_CLICK};
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK,
Effect::THUD, Effect::POP, Effect::HEAVY_CLICK};
}
return ndk::ScopedAStatus::ok();
}
@@ -591,8 +564,7 @@ ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
tmp = (uint8_t)(amplitude * 0xff);
ret = ff.setAmplitude(tmp);
if (ret != 0)
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
if (ret != 0) return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
return ndk::ScopedAStatus::ok();
}
@@ -609,7 +581,7 @@ ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs __unused) {
ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs __unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
@@ -617,7 +589,8 @@ ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize __unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>* supported __unused) {
ndk::ScopedAStatus Vibrator::getSupportedPrimitives(
std::vector<CompositePrimitive>* supported __unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
@@ -631,7 +604,8 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composi
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return __unused) {
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(
std::vector<Effect>* _aidl_return __unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
@@ -648,4 +622,3 @@ ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id __unused) {
} // namespace hardware
} // namespace android
} // namespace aidl

View File

@@ -27,227 +27,276 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Wly THUD as DOUBLE_CLICK */
static const int8_t effect_1[] = {
1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4,
4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20,
22, 26, 29, 33, 38, 43, 49, 56, 64, 71, 76, 81,
85, 88, 90, 92, 93, 93, 93, 92, 91, 90, 88, 86,
84, 81, 78, 75, 72, 68, 65, 61, 57, 53, 49, 44,
40, 36, 31, 27, 22, 17, 12, 7, 2, -3, -9, -15,
-21, -28, -35, -43, -51, -60, -71, -82, -94, -103, -112, -118,
-123, -126, -127, -127, -127, -127, -124, -121, -117, -112, -107, -101,
-94, -87, -80, -72, -64, -55, -47, -38, -30, -21, -12, -4,
5, 13, 21, 29, 37, 44, 51, 57, 63, 68, 73, 77,
81, 84, 86, 88, 89, 89, 88, 86, 84, 81, 78, 75,
72, 68, 64, 59, 54, 49, 44, 38, 32, 25, 19, 12,
5, -2, -9, -17, -24, -32, -40, -47, -55, -62, -69, -76,
-83, -89, -95, -101, -106, -111, -115, -119, -122, -124, -125, -125,
-125, -123, -120, -116, -111, -104, -95, -85, -74, -65, -56, -49,
-42, -35, -30, -24, -19, -15, -10, -6, -3, 1, 5, 8,
11, 15, 18, 21, 24, 26, 29, 32, 34, 37, 39, 41,
43, 45, 47, 49, 50, 51, 52, 53, 54, 54, 54, 54,
53, 52, 50, 48, 45, 42, 38, 33, 29, 25, 22, 19,
17, 14, 12, 11, 9, 8, 7, 6, 5, 4, 4, 3,
3, 2, 2, 2, 1, 1, 1, 1, 1, 0
0, 5, 10, 15, 20, 25, 29, 34, 38, 43, 47, 51, 55, 58, 62,
65, 68, 70, 73, 75, 77, 78, 79, 80, 81, 81, 81, 81, 80, 79,
78, 77, 75, 73, 70, 68, 65, 62, 59, 55, 51, 47, 43, 39, 34,
30, 25, 20, 15, 10, 5, 0, -5, -10, -15, -19, -24, -29, -34, -38,
-42, -47, -51, -54, -58, -61, -65, -68, -70, -73, -75, -77, -78, -79, -80,
-81, -81, -81, -81, -80, -79, -78, -77, -75, -73, -71, -68, -65, -62, -59,
-55, -51, -47, -43, -39, -35, -30, -25, -20, -16, -11, -6, -1, 4, 9,
14, 19, 24, 29, 33, 38, 42, 46, 50, 54, 58, 61, 64, 67, 70,
72, 75, 76, 78, 79, 80, 81, 81, 81, 81, 80, 80, 78, 77, 75,
73, 71, 68, 65, 62, 59, 55, 52, 48, 44, 39, 35, 30, 26, 21,
16, 11, 6, 1, -4, -9, -14, -19, -24, -28, -33, -38, -42, -46, -50,
-54, -58, -61, -64, -67, -70, -72, -74, -76, -78, -79, -80, -81, -81, -81,
-81, -80, -80, -78, -77, -75, -73, -71, -68, -66, -62, -59, -56, -52, -48,
-44, -40, -35, -31, -26, -21, -16, -11, -6, -1, 4, 9, 14, 19, 23,
28, 33, 37, 42, 46, 50, 54, 57, 61, 64, 67, 70, 72, 74, 76,
78, 79, 80, 81, 81, 81, 81, 81, 80, 79, 77, 75, 73, 71, 69,
66, 63, 59, 56, 52, 48, 44, 40, 35, 31, 26, 21, 16, 12, 7,
2, -3, -8, -13, -18, -23, -28, -32, -37, -41, -46, -50, -54, -57, -61,
-64, -67, -70, -72, -74, -76, -78, -79, -80, -81, -81, -81, -81, -81, -80,
-79, -77, -76, -74, -71, -69, -66, -63, -60, -56, -52, -48, -44, -40, -36,
-31, -26, -22, -17, -12, -7, 0, 2, 3, 5, 7, 8, 10, 12, 13,
15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28,
28, 28, 28, 28, 28, 27, 27, 26, 26, 25, 24, 23, 22, 21, 20,
19, 18, 16, 15, 13, 12, 10, 9, 7, 5, 4, 2, 0, -2, -3,
-5, -7, -8, -10, -12, -13, -15, -16, -17, -19, -20, -21, -22, -23, -24,
-25, -26, -26, -27, -27, -28, -28, -28, -28, -28, -28, -27, -27, -26, -26,
-25, -24, -23, -22, -21, -20, -19, -18, -16, -15, -13, -12, -10, -9, -7,
-5, -4, -2, 0, 1, 3, 5, 7, 8, 10, 11, 13, 15, 16, 17,
19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 28,
28, 28, 27, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16,
15, 13, 12, 10, 9, 7, 5, 4, 2, 0, -1, -3, -5, -6, -8,
-10, -11, -13, -14, -16, -17, -19, -20, -21, -22, -23, -24, -25, -26, -26,
-27, -27, -28, -28, -28, -28, -28, -28, -27, -27, -26, -26, -25, -24, -24,
-23, -21, -20, -19, -18, -16, -15, -14, -12, -10, -9, -7, -6, -4, -2,
0, 1, 3, 5, 6, 8, 10, 11, 13, 14, 16, 17, 18, 20, 21,
22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 28, 28, 28, 27,
27, 27, 26, 25, 24, 24, 23, 22, 20, 19, 18, 17, 15, 14, 12,
11, 9, 7, 6, 4, 2, 1, -1, -3, -5, -6, -8, -10, -11, -13,
-14, -16, -17, -18, -20, -21, -22, -23, -24, -25, -25, -26, -27, -27, -28,
-28, -28, -28, -28, -28, -27, -27, -27, -26, -25, -24, -24, -23, -22, -20,
-19, -18, -17, -15, -14, -12, -11, -9, -7, -6, -4, -2, -1, 1, 3,
4, 6, 8, 9, 11, 13, 14, 16, 17, 18, 20, 21, 22, 23, 24,
25, 25, 26, 27, 27, 27, 28, 28, 28, 28, 28, 27, 27, 27, 26,
25, 25, 24, 23, 22, 21, 19, 18, 17, 15, 14, 12, 11, 9, 8,
6, 4, 2, 1, -1, -3, -4, -6, -8, -9, -11, -13, -14, -15, -17,
-18, -19, -21, -22, -23, -24, -25, -25, -26, -27, -27, -27, -28, -28, -28,
-28, -28, -27, -27, -27, -26, -25, -25, -24, -23, -22, -21, -19, -18, -17,
-15, -14, -12, -11, -9, -8, -6, -4, -3, -1, 1, 3, 4, 6, 8,
9, 11, 12, 14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 25, 26,
27, 27, 27, 28, 28, 28, 28, 28, 27, 27, 27, 26, 25, 25, 24,
23, 22, 21, 20, 18, 17, 16, 14, 13, 11, 9, 8, 6, 4, 3,
1, -1, -2, -4, -6, -8, -9, -11, -12, -14, -15, -17, -18, -19, -21,
-22, -23, -24, -25, -25, -26, -27, -27, -27, -28, -28, -28, -28, -28, -27,
-27, -27, -26, -25, -25, -24, -23, -22, -21, -20, -18, -17, -16, -14, -13,
-11, -9, -8, -6, -5, -3, -1, 1, 2, 4, 6, 7, 9, 11, 12,
14, 15, 17, 18, 19, 20, 22, 23, 24, 24, 25, 26, 27, 27, 27,
28, 28, 28, 28, 28, 28, 27, 27, 26, 26, 25, 24, 23, 22, 21,
20, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 3, 1, -1, -2,
-4, -6, -7, -9, -11, -12, -14, -15, -17, -18, -19, -20, -22, -23, -24,
-24, -25, -26, -27, -27, -27, -28, -28, -28, -28, -28, -28, -27, -27, -26,
-26, -25, -24, -23, -22, -21, -20, -19, -17, -16, -14, -13, -11, -10, -8,
-6, -5, -3, -1, 0, 2, 4, 6, 7, 9, 10, 12, 14, 15, 16,
18, 19, 20, 21, 23, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28,
28, 28, 28, 27, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 17,
16, 14, 13, 11, 10, 8, 7, 5, 3, 1, 0, -2, -4, -5, -7,
-9, -10, -12, -13, -15, -16, -18, -19, -20, -21, -22, -23, -24, -25, -26,
-26, -27, -27, -28, -28, -28, -28, -28, -28, -27, -27, -26, -26, -25, -24,
-23, -22, -21, -20, -19, -17, -16, -15, -13, -11, -10, -8, -7, -5, -3,
-2, 0, 2, 4, 5, 7, 9, 10, 12, 13, 15, 16, 18, 19, 20,
21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 28, 28, 28,
27, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 17, 16, 15, 13,
12, 10, 8, 7, 5, 3, 2, 0, -2, -3, -5, -7, -9, -10, -12,
-13, -15, -16, -18, -19, -20, -21, -22, -23, -24, -25, -26, -26, -27, -27,
-28, -28, -28, -28, -28, -28, -27, -27, -26, -26, -25, -24, -23, -22, -21,
-20, -19, -18, -16, -15, -13, -12, -10, -8, -7, -5, -3, -2, 0, 2,
3, 5, 7, 8, 10, 12, 13, 15, 16, 17, 19, 20, 21, 22, 23,
24, 25, 26, 26, 27, 27, 28, 28, 28, 28, 28, 28, 27, 27, 26,
26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9,
7, 5, 4, 2, 0, -2, -3, -5, -7, -8, -10, -12, -13, -15, -16,
-17, -19, -20, -21, -22, -23, -24, -25, -26, -26, -27, -27, -28, -28, -28,
-28, -28, -28, -27, -27, -26, -26, -25, -24, -23, -22, -21, -20, -19, -18,
-16, -15, -13, -12, -10, -9, -7, -5, -4, -2, 0, -6, -12, -18, -24,
-30, -35, -41, -46, -51, -56, -61, -66, -70, -74, -78, -81, -85, -87, -90,
-92, -94, -95, -97, -97, -98, -98, -97, -97, -96, -94, -92, -90, -88, -85,
-82, -78, -74, -70, -66, -62, -57, -52, -47, -41, -36, -30, -24, -18, -12,
-6, 0, 6, 12, 18, 23, 29, 35, 40, 46, 51, 56, 61, 66, 70,
74, 78, 81, 84, 87, 90, 92, 94, 95, 97, 97, 98, 98, 97, 97,
96, 94, 92, 90, 88, 85, 82, 78, 75, 71, 66, 62, 57, 52, 47,
42, 36, 30, 25, 19, 13, 7, 1, -5, -11, -17, -23, -29, -35, -40,
-46, -51, -56, -61, -65, -70, -74, -77, -81, -84, -87, -90, -92, -94, -95,
-96, -97, -98, -98, -97, -97, -96, -94, -93, -90, -88, -85, -82, -79, -75,
-71, -67, -62, -57, -52, -47, -42, -36, -31, -25, -19, -13, -7, -1, 5,
11, 17, 23, 29, 34, 40, 45, 50, 55, 60, 65, 69, 73, 77, 81,
84, 87, 90, 92, 94, 95, 96, 97, 98, 98, 97, 97, 96, 94, 93,
91, 88, 85, 82, 79, 75, 71, 67, 62, 58, 53, 48, 42, 37, 31,
25, 19, 14, 8, 2, -4, -10, -16, -22, -28, -34, -39, -45, -50, -55,
-60, -65, -69, -73, -77, -81, -84, -87, -89, -92, -94, -95, -96, -97, -98,
-98, -98, -97, -96, -95, -93, -91, -88, -86, -82, -79, -75, -71, -67, -63,
-58, -53, -48, -43, -37, -31, -26, -20, -14, -8, 0
};
static const int8_t effect_2[] = {
1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4,
4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 16, 19,
22, 25, 28, 32, 36, 42, 48, 54, 61, 69, 78, 85,
92, 97, 102, 106, 110, 113, 115, 117, 119, 121, 121, 123,
123, 123, 124, 124, 124, 123, 123, 123, 122, 121, 121, 120,
119, 118, 117, 115, 114, 113, 112, 111, 109, 108, 106, 105,
103, 101, 99, 97, 95, 93, 91, 89, 86, 83, 80, 77,
73, 69, 64, 60, 54, 48, 41, 34, 25, 15, 4, -7,
-22, -37, -51, -64, -74, -83, -91, -99, -104, -109, -112, -115,
-119, -120, -122, -122, -123, -122, -122, -122, -120, -120, -118, -116,
-114, -112, -110, -107, -105, -103, -99, -97, -95, -91, -89, -86,
-83, -80, -77, -74, -71, -68, -64, -61, -58, -55, -52, -49,
-46, -43, -40, -36, -33, -29, -26, -22, -18, -14, -10, -5,
0, 6, 12, 19, 27, 35, 42, 47, 52, 57, 60, 63,
65, 66, 67, 68, 68, 67, 67, 66, 64, 62, 61, 58,
56, 53, 51, 49, 45, 43, 39, 35, 33, 29, 26, 22,
19, 15, 12, 8, 5, 1, -2, -5, -9, -12, -14, -17,
-20, -22, -25, -27, -28, -30, -32, -32, -34, -34, -34, -34,
-33, -31, -29, -27, -24, -21, -16, -11, -4, 2, 8, 14,
19, 23, 27, 31, 35, 38, 42, 45, 48, 51, 54, 56,
58, 62, 65, 67, 69, 72, 75, 78, 80, 83, 86, 88,
91, 94, 97, 99, 102, 104, 107, 109, 111, 114, 116, 118,
120, 121, 123, 124, 125, 126, 127, 127, 127, 127, 127, 126,
124, 123, 120, 117, 113, 109, 103, 96, 89, 80, 70, 58,
45, 32, 21, 11, 2, -6, -12, -18, -24, -29, -33, -37,
-41, -43, -47, -49, -51, -54, -56, -58, -59, -61, -62, -64,
-65, -66, -67, -68, -69, -70, -71, -72, -73, -74, -75, -76,
-77, -77, -78, -78, -79, -79, -80, -80, -80, -80, -80, -80,
-80, -80, -79, -79, -78, -77, -75, -74, -72, -70, -67, -64,
-61, -57, -53, -47, -42, -37, -32, -28, -25, -22, -19, -16,
-15, -12, -11, -10, -8, -7, -6, -6, -5, -4, -4, -3,
-3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -1, 0
};
1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6,
7, 8, 9, 10, 12, 13, 14, 16, 19, 22, 25, 28, 32, 36, 42,
48, 54, 61, 69, 78, 85, 92, 97, 102, 106, 110, 113, 115, 117, 119,
121, 121, 123, 123, 123, 124, 124, 124, 123, 123, 123, 122, 121, 121, 120,
119, 118, 117, 115, 114, 113, 112, 111, 109, 108, 106, 105, 103, 101, 99,
97, 95, 93, 91, 89, 86, 83, 80, 77, 73, 69, 64, 60, 54, 48,
41, 34, 25, 15, 4, -7, -22, -37, -51, -64, -74, -83, -91, -99, -104,
-109, -112, -115, -119, -120, -122, -122, -123, -122, -122, -122, -120, -120, -118, -116,
-114, -112, -110, -107, -105, -103, -99, -97, -95, -91, -89, -86, -83, -80, -77,
-74, -71, -68, -64, -61, -58, -55, -52, -49, -46, -43, -40, -36, -33, -29,
-26, -22, -18, -14, -10, -5, 0, 6, 12, 19, 27, 35, 42, 47, 52,
57, 60, 63, 65, 66, 67, 68, 68, 67, 67, 66, 64, 62, 61, 58,
56, 53, 51, 49, 45, 43, 39, 35, 33, 29, 26, 22, 19, 15, 12,
8, 5, 1, -2, -5, -9, -12, -14, -17, -20, -22, -25, -27, -28, -30,
-32, -32, -34, -34, -34, -34, -33, -31, -29, -27, -24, -21, -16, -11, -4,
2, 8, 14, 19, 23, 27, 31, 35, 38, 42, 45, 48, 51, 54, 56,
58, 62, 65, 67, 69, 72, 75, 78, 80, 83, 86, 88, 91, 94, 97,
99, 102, 104, 107, 109, 111, 114, 116, 118, 120, 121, 123, 124, 125, 126,
127, 127, 127, 127, 127, 126, 124, 123, 120, 117, 113, 109, 103, 96, 89,
80, 70, 58, 45, 32, 21, 11, 2, -6, -12, -18, -24, -29, -33, -37,
-41, -43, -47, -49, -51, -54, -56, -58, -59, -61, -62, -64, -65, -66, -67,
-68, -69, -70, -71, -72, -73, -74, -75, -76, -77, -77, -78, -78, -79, -79,
-80, -80, -80, -80, -80, -80, -80, -80, -79, -79, -78, -77, -75, -74, -72,
-70, -67, -64, -61, -57, -53, -47, -42, -37, -32, -28, -25, -22, -19, -16,
-15, -12, -11, -10, -8, -7, -6, -6, -5, -4, -4, -3, -3, -3, -3,
-2, -2, -2, -2, -2, -2, -2, -1, 0};
static const int8_t effect_3[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 2, 2, 3, 4, 6, 7, 9, 11, 14, 16, 19,
22, 26, 29, 33, 37, 41, 45, 49, 54, 58, 62, 66,
70, 74, 78, 81, 85, 88, 91, 94, 97, 99, 101, 103,
105, 106, 108, 108, 109, 110, 110, 110, 109, 109, 108, 107,
105, 104, 102, 100, 98, 96, 93, 90, 87, 84, 81, 78,
74, 70, 67, 63, 59, 54, 50, 46, 41, 37, 32, 28,
23, 18, 13, 9, 4, -1, -6, -11, -15, -20, -25, -29,
-34, -39, -43, -47, -52, -56, -60, -64, -68, -71, -75, -78,
-82, -85, -88, -90, -93, -95, -97, -99, -101, -103, -104, -106,
-107, -107, -108, -108, -108, -108, -108, -107, -107, -106, -105, -103,
-102, -100, -98, -96, -94, -91, -88, -86, -83, -79, -76, -72,
-69, -65, -61, -57, -53, -49, -44, -40, -35, -31, -26, -21,
-17, -12, -7, -2, 3, 7, 12, 17, 22, 27, 31, 36,
40, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 83,
86, 89, 91, 94, 96, 98, 100, 102, 104, 105, 106, 107,
108, 108, 108, 108, 108, 108, 107, 106, 105, 104, 103, 101,
99, 97, 95, 93, 90, 87, 84, 81, 75, 72, 68, 65,
61, 58, 54, 51, 47, 44, 41, 38, 35, 32, 30, 27,
24, 22, 19, 16, 14, 11, 8, 6, 3, 1, -2, -4,
-6, -8, -10, -11, -13, -14, -15, -16, -17, -18, -19, -20,
-20, -21, -21, -21, -21, -22, -22, -22, -22, -22, -22, -22,
-22, -22, -21, -21, -21, -21, -21, -20, -20, -20, -20, -19,
-19, -18, -18, -18, -17, -17, -16, -16, -15, -14, -14, -13,
-12, -12, -11, -10, -9, -9, -8, -7, -6, -5, -4, -3,
-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
8, 9, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17,
17, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 19,
19, 19, 18, 18, 17, 16, 16, 15, 15, 14, 13, 12,
12, 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2,
1, 0, -1, -2, -3, -4, -4, -5, -6, -7, -8, -9,
-10, -11, -11, -12, -13, -14, -14, -15, -16, -16, -17, -17,
-18, -18, -19, -19, -20, -20, -20, -20, -21, -21, -21, -21,
-21, -21, -21, -21, -21, -21, -20, -20, -20, -20, -19, -19,
-18, -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, -11,
-11, -10, -9, -8, -7, -6, -5, -4, -4, -3, -2, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10,
11, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18, 18,
19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18,
18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 10,
9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1,
-1, -2, -3, -4, -5, -6, -7, -8, -9, -9, -10, -11,
-12, -13, -13, -14, -15, -15, -16, -17, -17, -18, -18, -19,
-19, -19, -20, -20, -20, -21, -21, -21, -21, -21, -21, -21,
-21, -21, -21, -20, -20, -20, -20, -19, -19, -18, -18, -18,
-17, -16, -16, -15, -15, -14, -13, -12, -12, -11, -10, -9,
-8, -7, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2,
3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12,
13, 14, 14, 15, 16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 20, 20, 20, 20, 19, 19, 18, 18, 17, 17,
16, 16, 15, 14, 14, 13, 12, 11, 10, 10, 9, 8,
7, 6, 5, 4, 3, 3, 2, 1, 0, -1, -2, -3,
-4, -5, -6, -7, -8, -8, -10, -10, -11, -12, -13, -14,
-14, -15, -16, -16, -17, -17, -17, -17, -17, -17, -16, -14,
-12, -10, -7, -4, 0, 4, 8, 13, 19, 24, 30, 36,
42, 48, 53, 59, 64, 69, 74, 78, 82, 85, 87, 89,
91, 92, 92, 91, 89, 87, 83, 79, 73, 67, 60, 52,
44, 36, 27, 18, 10, 1, -7, -14, -22, -29, -36, -43,
-50, -56, -62, -69, -75, -81, -86, -92, -97, -102, -107, -111,
-115, -118, -121, -123, -124, -126, -127, -127, -127, -127, -127, -127,
-127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-126, -124, -122, -120, -117, -114, -110, -106, -101, -96, -90, -84,
-79, -73, -67, -60, -54, -48, -42, -36, -30, -24, -18, -13,
-7, -1, 4, 9, 14, 19, 24, 28, 33, 37, 41, 44,
48, 51, 54, 57, 60, 62, 64, 66, 68, 69, 70, 71,
72, 73, 73, 73, 73, 73, 73, 72, 71, 71, 70, 68,
67, 66, 64, 63, 61, 59, 57, 55, 53, 51, 49, 46,
44, 42, 39, 37, 35, 32, 30, 28, 25, 23, 21, 18,
16, 14, 12, 10, 8, 6, 4, 2, 1, -1, -3, -4,
-5, -7, -8, -9, -10, -11, -12, -13, -14, -15, -15, -16,
-16, -16, -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
-17, -16, -16, -15, -15, -15, -14, -14, -13, -13, -12, -11,
-11, -10, -10, -9, -8, -8, -7, -7, -6, -5, -5, -4,
-4, -3, -3, -2, -2, -1, -1, 0
};
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2,
3, 4, 6, 7, 9, 11, 14, 16, 19, 22, 26, 29, 33, 37, 41,
45, 49, 54, 58, 62, 66, 70, 74, 78, 81, 85, 88, 91, 94, 97,
99, 101, 103, 105, 106, 108, 108, 109, 110, 110, 110, 109, 109, 108, 107,
105, 104, 102, 100, 98, 96, 93, 90, 87, 84, 81, 78, 74, 70, 67,
63, 59, 54, 50, 46, 41, 37, 32, 28, 23, 18, 13, 9, 4, -1,
-6, -11, -15, -20, -25, -29, -34, -39, -43, -47, -52, -56, -60, -64, -68,
-71, -75, -78, -82, -85, -88, -90, -93, -95, -97, -99, -101, -103, -104, -106,
-107, -107, -108, -108, -108, -108, -108, -107, -107, -106, -105, -103, -102, -100, -98,
-96, -94, -91, -88, -86, -83, -79, -76, -72, -69, -65, -61, -57, -53, -49,
-44, -40, -35, -31, -26, -21, -17, -12, -7, -2, 3, 7, 12, 17, 22,
27, 31, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 83,
86, 89, 91, 94, 96, 98, 100, 102, 104, 105, 106, 107, 108, 108, 108,
108, 108, 108, 107, 106, 105, 104, 103, 101, 99, 97, 95, 93, 90, 87,
84, 81, 75, 72, 68, 65, 61, 58, 54, 51, 47, 44, 41, 38, 35,
32, 30, 27, 24, 22, 19, 16, 14, 11, 8, 6, 3, 1, -2, -4,
-6, -8, -10, -11, -13, -14, -15, -16, -17, -18, -19, -20, -20, -21, -21,
-21, -21, -22, -22, -22, -22, -22, -22, -22, -22, -22, -21, -21, -21, -21,
-21, -20, -20, -20, -20, -19, -19, -18, -18, -18, -17, -17, -16, -16, -15,
-14, -14, -13, -12, -12, -11, -10, -9, -9, -8, -7, -6, -5, -4, -3,
-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10,
11, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 19, 19,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,
20, 20, 19, 19, 19, 18, 18, 17, 16, 16, 15, 15, 14, 13, 12,
12, 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1,
-2, -3, -4, -4, -5, -6, -7, -8, -9, -10, -11, -11, -12, -13, -14,
-14, -15, -16, -16, -17, -17, -18, -18, -19, -19, -20, -20, -20, -20, -21,
-21, -21, -21, -21, -21, -21, -21, -21, -21, -20, -20, -20, -20, -19, -19,
-18, -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, -11, -11, -10, -9,
-8, -7, -6, -5, -4, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5,
6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 15, 16, 16,
17, 18, 18, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 17, 17,
16, 15, 15, 14, 13, 13, 12, 11, 10, 9, 9, 8, 7, 6, 5,
4, 3, 2, 1, 0, -1, -1, -2, -3, -4, -5, -6, -7, -8, -9,
-9, -10, -11, -12, -13, -13, -14, -15, -15, -16, -17, -17, -18, -18, -19,
-19, -19, -20, -20, -20, -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
-20, -20, -20, -20, -19, -19, -18, -18, -18, -17, -16, -16, -15, -15, -14,
-13, -12, -12, -11, -10, -9, -8, -7, -7, -6, -5, -4, -3, -2, -1,
0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12,
13, 14, 14, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 20,
20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20,
19, 19, 18, 18, 17, 17, 16, 16, 15, 14, 14, 13, 12, 11, 10,
10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 0, -1, -2, -3,
-4, -5, -6, -7, -8, -8, -10, -10, -11, -12, -13, -14, -14, -15, -16,
-16, -17, -17, -17, -17, -17, -17, -16, -14, -12, -10, -7, -4, 0, 4,
8, 13, 19, 24, 30, 36, 42, 48, 53, 59, 64, 69, 74, 78, 82,
85, 87, 89, 91, 92, 92, 91, 89, 87, 83, 79, 73, 67, 60, 52,
44, 36, 27, 18, 10, 1, -7, -14, -22, -29, -36, -43, -50, -56, -62,
-69, -75, -81, -86, -92, -97, -102, -107, -111, -115, -118, -121, -123, -124, -126,
-127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-127, -127, -127, -126, -124, -122, -120, -117, -114, -110, -106, -101, -96, -90, -84,
-79, -73, -67, -60, -54, -48, -42, -36, -30, -24, -18, -13, -7, -1, 4,
9, 14, 19, 24, 28, 33, 37, 41, 44, 48, 51, 54, 57, 60, 62,
64, 66, 68, 69, 70, 71, 72, 73, 73, 73, 73, 73, 73, 72, 71,
71, 70, 68, 67, 66, 64, 63, 61, 59, 57, 55, 53, 51, 49, 46,
44, 42, 39, 37, 35, 32, 30, 28, 25, 23, 21, 18, 16, 14, 12,
10, 8, 6, 4, 2, 1, -1, -3, -4, -5, -7, -8, -9, -10, -11,
-12, -13, -14, -15, -15, -16, -16, -16, -17, -17, -17, -17, -17, -17, -17,
-17, -17, -17, -17, -16, -16, -15, -15, -15, -14, -14, -13, -13, -12, -11,
-11, -10, -10, -9, -8, -8, -7, -7, -6, -5, -5, -4, -4, -3, -3,
-2, -2, -1, -1, 0};
static const int8_t effect_4[] = {
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2,
2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10,
12, 13, 15, 17, 19, 22, 25, 28, 32, 37, 42, 48,
55, 62, 70, 79, 86, 92, 97, 102, 107, 110, 113, 115,
117, 119, 121, 121, 123, 123, 123, 124, 124, 124, 123, 123,
123, 121, 121, 121, 119, 119, 118, 117, 115, 114, 113, 112,
110, 109, 107, 106, 105, 102, 101, 99, 97, 95, 93, 91,
89, 86, 83, 80, 77, 73, 69, 64, 60, 54, 48, 41,
33, 24, 14, 3, -9, -23, -38, -52, -65, -75, -84, -92,
-99, -104, -109, -113, -115, -119, -120, -122, -122, -123, -122, -122,
-121, -120, -119, -118, -116, -114, -112, -110, -107, -105, -102, -99,
-97, -94, -91, -88, -85, -82, -79, -76, -74, -70, -68, -64,
-61, -58, -55, -52, -49, -46, -43, -39, -36, -33, -29, -26,
-22, -18, -14, -10, -5, 0, 7, 13, 20, 28, 35, 42,
48, 53, 58, 60, 63, 65, 66, 67, 68, 68, 67, 67,
66, 64, 62, 61, 58, 56, 53, 51, 48, 45, 42, 38,
35, 33, 28, 26, 22, 19, 15, 12, 8, 5, 1, -2,
-5, -9, -12, -14, -17, -20, -22, -25, -28, -29, -30, -32,
-32, -34, -34, -34, -33, -33, -31, -29, -27, -24, -20, -16,
-10, -3, 3, 9, 14, 19, 24, 27, 32, 35, 38, 42,
45, 48, 51, 54, 57, 59, 62, 65, 68, 70, 73, 76,
78, 80, 84, 86, 88, 91, 94, 97, 99, 102, 104, 107,
109, 111, 114, 116, 118, 120, 121, 123, 124, 125, 126, 127,
127, 127, 127, 127, 125, 124, 123, 120, 117, 113, 108, 102,
96, 88, 79, 69, 57, 44, 31, 20, 10, 2, -6, -13,
-19, -24, -29, -33, -37, -41, -44, -47, -49, -52, -54, -56,
-58, -59, -61, -62, -64, -66, -66, -67, -68, -69, -70, -71,
-72, -73, -74, -75, -76, -77, -77, -78, -78, -79, -79, -80,
-80, -80, -80, -80, -80, -80, -80, -79, -79, -78, -77, -75,
-74, -72, -70, -67, -64, -61, -56, -52, -46, -41, -36, -31,
-27, -24, -21, -18, -16, -14, -12, -11, -9, -8, -7, -6,
-6, -5, -4, -4, -3, -3, -3, -3, -2, -2, -2, -2,
-2, -2, -2, -1, 0, 0, 0, 0, 0, 0, 0
};
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3,
3, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 19, 22,
25, 28, 32, 37, 42, 48, 55, 62, 70, 79, 86, 92, 97, 102, 107,
110, 113, 115, 117, 119, 121, 121, 123, 123, 123, 124, 124, 124, 123, 123,
123, 121, 121, 121, 119, 119, 118, 117, 115, 114, 113, 112, 110, 109, 107,
106, 105, 102, 101, 99, 97, 95, 93, 91, 89, 86, 83, 80, 77, 73,
69, 64, 60, 54, 48, 41, 33, 24, 14, 3, -9, -23, -38, -52, -65,
-75, -84, -92, -99, -104, -109, -113, -115, -119, -120, -122, -122, -123, -122, -122,
-121, -120, -119, -118, -116, -114, -112, -110, -107, -105, -102, -99, -97, -94, -91,
-88, -85, -82, -79, -76, -74, -70, -68, -64, -61, -58, -55, -52, -49, -46,
-43, -39, -36, -33, -29, -26, -22, -18, -14, -10, -5, 0, 7, 13, 20,
28, 35, 42, 48, 53, 58, 60, 63, 65, 66, 67, 68, 68, 67, 67,
66, 64, 62, 61, 58, 56, 53, 51, 48, 45, 42, 38, 35, 33, 28,
26, 22, 19, 15, 12, 8, 5, 1, -2, -5, -9, -12, -14, -17, -20,
-22, -25, -28, -29, -30, -32, -32, -34, -34, -34, -33, -33, -31, -29, -27,
-24, -20, -16, -10, -3, 3, 9, 14, 19, 24, 27, 32, 35, 38, 42,
45, 48, 51, 54, 57, 59, 62, 65, 68, 70, 73, 76, 78, 80, 84,
86, 88, 91, 94, 97, 99, 102, 104, 107, 109, 111, 114, 116, 118, 120,
121, 123, 124, 125, 126, 127, 127, 127, 127, 127, 125, 124, 123, 120, 117,
113, 108, 102, 96, 88, 79, 69, 57, 44, 31, 20, 10, 2, -6, -13,
-19, -24, -29, -33, -37, -41, -44, -47, -49, -52, -54, -56, -58, -59, -61,
-62, -64, -66, -66, -67, -68, -69, -70, -71, -72, -73, -74, -75, -76, -77,
-77, -78, -78, -79, -79, -80, -80, -80, -80, -80, -80, -80, -80, -79, -79,
-78, -77, -75, -74, -72, -70, -67, -64, -61, -56, -52, -46, -41, -36, -31,
-27, -24, -21, -18, -16, -14, -12, -11, -9, -8, -7, -6, -6, -5, -4,
-4, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -1, 0, 0,
0, 0, 0, 0, 0};
static const struct effect_stream effects[] = {
{
/* CLICK */
.effect_id = 0,
.data = effect_2,
.length = ARRAY_SIZE(effect_2),
.play_rate_hz = 24000,
},
{
/* CLICK */
.effect_id = 0,
.data = effect_2,
.length = ARRAY_SIZE(effect_2),
.play_rate_hz = 24000,
},
{
/* DOUBLE_CLICK */
.effect_id = 1,
.data = effect_1,
.length = ARRAY_SIZE(effect_1),
.play_rate_hz = 24000,
},
{
/* DOUBLE_CLICK */
.effect_id = 1,
.data = effect_1,
.length = ARRAY_SIZE(effect_1),
.play_rate_hz = 24000,
},
{
/* TICK */
.effect_id = 2,
.data = effect_2,
.length = ARRAY_SIZE(effect_2),
.play_rate_hz = 24000,
},
{
/* TICK */
.effect_id = 2,
.data = effect_2,
.length = ARRAY_SIZE(effect_2),
.play_rate_hz = 24000,
},
{
/* THUD */
.effect_id = 3,
.data = effect_3,
.length = ARRAY_SIZE(effect_3),
.play_rate_hz = 24000,
},
{
/* THUD */
.effect_id = 3,
.data = effect_3,
.length = ARRAY_SIZE(effect_3),
.play_rate_hz = 24000,
},
{
/* POP */
.effect_id = 4,
.data = effect_4,
.length = ARRAY_SIZE(effect_4),
.play_rate_hz = 24000,
},
{
/* POP */
.effect_id = 4,
.data = effect_4,
.length = ARRAY_SIZE(effect_4),
.play_rate_hz = 24000,
},
{
/* HEAVY_CLICK */
.effect_id = 5,
.data = effect_3,
.length = ARRAY_SIZE(effect_3),
.play_rate_hz = 24000,
},
{
/* HEAVY_CLICK */
.effect_id = 5,
.data = effect_3,
.length = ARRAY_SIZE(effect_3),
.play_rate_hz = 24000,
},
};

View File

@@ -32,12 +32,12 @@
#include <sys/types.h>
struct effect_stream {
uint32_t effect_id;
uint32_t length;
uint32_t play_rate_hz;
const int8_t *data;
uint32_t effect_id;
uint32_t length;
uint32_t play_rate_hz;
const int8_t* data;
};
const struct effect_stream *get_effect_stream(uint32_t effect_id);
const struct effect_stream* get_effect_stream(uint32_t effect_id);
#endif

View File

@@ -37,9 +37,9 @@ namespace hardware {
namespace vibrator {
class InputFFDevice {
public:
public:
InputFFDevice();
int playEffect(int effectId, EffectStrength es, long *playLengthMs);
int playEffect(int effectId, EffectStrength es, long* playLengthMs);
int on(int32_t timeoutMs);
int off();
int setAmplitude(uint8_t amplitude);
@@ -47,36 +47,37 @@ public:
bool mSupportEffects;
bool mSupportExternalControl;
bool mInExternalControl;
private:
int play(int effectId, uint32_t timeoutMs, long *playLengthMs);
private:
int play(int effectId, uint32_t timeoutMs, long* playLengthMs);
int mVibraFd;
int16_t mCurrAppId;
int16_t mCurrMagnitude;
};
class LedVibratorDevice {
public:
public:
LedVibratorDevice();
int on(int32_t timeoutMs);
int onWaveform(int waveformIndex);
int off();
bool mDetected;
int write_value(const char *file, const char *value);
int write_value(const char *file, int value);
int write_value(const char* file, const char* value);
int write_value(const char* file, int value);
};
class Vibrator : public BnVibrator {
public:
public:
class InputFFDevice ff;
class LedVibratorDevice ledVib;
ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
ndk::ScopedAStatus off() override;
ndk::ScopedAStatus on(int32_t timeoutMs,
const std::shared_ptr<IVibratorCallback>& callback) override;
const std::shared_ptr<IVibratorCallback>& callback) override;
ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
const std::shared_ptr<IVibratorCallback>& callback,
int32_t* _aidl_return) override;
const std::shared_ptr<IVibratorCallback>& callback,
int32_t* _aidl_return) override;
ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
ndk::ScopedAStatus setAmplitude(float amplitude) override;
ndk::ScopedAStatus setExternalControl(bool enabled) override;

View File

@@ -143,7 +143,7 @@ ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize __unused) {
}
ndk::ScopedAStatus Vibrator::getSupportedPrimitives(
std::vector<CompositePrimitive>* supported __unused) {
std::vector<CompositePrimitive>* supported __unused) {
return ndk::ScopedAStatus::ok();
}
@@ -157,7 +157,8 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composi
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return __unused) {
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(
std::vector<Effect>* _aidl_return __unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
@@ -203,7 +204,8 @@ ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking>* supported
}
ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle>& composite __unused,
const std::shared_ptr<IVibratorCallback>& callback __unused) {
const std::shared_ptr<IVibratorCallback>& callback
__unused) {
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}

View File

@@ -5,7 +5,7 @@
*/
#define LOG_TAG "audio_amplifier"
//#define LOG_NDEBUG 0
// #define LOG_NDEBUG 0
#include <cutils/str_parms.h>
#include <dlfcn.h>

28
dolby/Android.bp Normal file
View File

@@ -0,0 +1,28 @@
//
// Copyright (C) 2017-2021 The LineageOS Project
// (C) 2023-24 Paranoid Android
//
// SPDX-License-Identifier: Apache-2.0
//
android_app {
name: "OplusDolby",
srcs: ["src/**/*.kt"],
resource_dirs: ["res"],
certificate: "platform",
platform_apis: true,
system_ext_specific: true,
privileged: true,
overrides: ["MusicFX"],
static_libs: [
"SettingsLib",
"SpaLib",
"androidx.activity_activity-compose",
"androidx.compose.material3_material3",
"androidx.compose.runtime_runtime",
"androidx.preference_preference",
"org.lineageos.settings.resources",
],
}

79
dolby/AndroidManifest.xml Normal file
View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023-24 Paranoid Android
SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.aospa.dolby.oplus"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:label="@string/dolby_title"
android:persistent="true">
<receiver
android:name=".BootCompletedReceiver"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name=".DolbyActivity"
android:label="@string/dolby_title"
android:theme="@style/Theme.SubSettingsBase"
android:exported="true">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES"/>
</intent-filter>
<intent-filter>
<action android:name="android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.CATEGORY_CONTENT_MUSIC" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.sound" />
<meta-data android:name="com.android.settings.summary_uri"
android:value="content://co.aospa.dolby.oplus.summary/dolby" />
</activity>
<activity
android:name=".geq.EqualizerActivity"
android:label="@string/dolby_preset"
android:theme="@style/Theme.SubSettingsBase"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".DolbyTileService"
android:icon="@drawable/ic_dolby_qs"
android:label="@string/dolby_title"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
</service>
<provider
android:name=".SummaryProvider"
android:authorities="co.aospa.dolby.oplus.summary">
</provider>
</application>
</manifest>

5
dolby/dolby.mk Normal file
View File

@@ -0,0 +1,5 @@
# DolbyManager
PRODUCT_PACKAGES += \
OplusDolby
BOARD_VENDOR_SEPOLICY_DIRS += hardware/oplus/sepolicy/qti/dolby

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<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="#000000" android:pathData="M1,4.0214C2.2767,4.0743 3.5798,3.9866 4.8252,4.2063C8.8352,4.9133 11.4129,8.3489 11.0507,12.3402C10.7124,16.0695 7.3661,18.9511 3.3484,18.9651C2.5657,18.9678 1.7827,18.9441 1,18.9324L1,4.0214Z" android:strokeColor="#00000000" android:strokeWidth="1" android:fillType="evenOdd"/>
<group>
<clip-path android:pathData="M12.9332,4l10.0668,0l0,15l-10.0668,0z"/>
<path android:fillColor="#000000" android:pathData="M23,4.0924L23,18.8825C19.4973,19.298 16.399,18.6968 14.3366,15.6947C12.5148,13.043 12.4594,10.2265 14.2129,7.5241C16.244,4.394 19.3953,3.7204 23,4.0924" android:strokeColor="#00000000" android:strokeWidth="1" android:fillType="evenOdd"/>
</group>
</vector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#191c1e" android:pathData="M1,4.0214C2.2767,4.0743 3.5798,3.9866 4.8252,4.2063C8.8352,4.9133 11.4129,8.3489 11.0507,12.3402C10.7124,16.0695 7.3661,18.9511 3.3484,18.9651C2.5657,18.9678 1.7827,18.9441 1,18.9324L1,4.0214Z" android:strokeColor="#00000000" android:strokeWidth="1" android:fillType="evenOdd"/>
<group>
<clip-path android:pathData="M12.9332,4l10.0668,0l0,15l-10.0668,0z"/>
<path android:fillColor="#191c1e" android:pathData="M23,4.0924L23,18.8825C19.4973,19.298 16.399,18.6968 14.3366,15.6947C12.5148,13.043 12.4594,10.2265 14.2129,7.5241C16.244,4.394 19.3953,3.7204 23,4.0924" android:strokeColor="#00000000" android:strokeWidth="1" android:fillType="evenOdd"/>
</group>
</vector>

View File

@@ -0,0 +1,24 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="192dp"
android:height="192dp"
android:viewportWidth="192"
android:viewportHeight="192"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#000000"
android:pathData="M 69.584 66.547 L 63.792 70.797 L 38.646 71.697 L 13.5 72.597 L 13.5 89.723 C 13.5 99.143 13.865 111.999 14.313 118.292 L 15.124 129.734 L 178.5 129.734 L 178.5 102.234 L 121.248 102.234 L 99.203 82.234 C 87.078 71.234 76.756 62.248 76.266 62.266 C 75.776 62.282 72.769 64.209 69.584 66.547"
android:strokeWidth="1.25"/>
<path
android:fillColor="#000000"
android:pathData="M 69.125 67.065 L 62.875 71.921 L 38.188 71.99 L 13.5 72.06 L 13.504 81.122 C 13.506 86.106 13.876 99.044 14.325 109.872 L 15.141 129.56 L 178.5 129.56 L 178.5 103.31 L 122.126 103.31 L 99.675 82.997 C 87.326 71.826 76.808 62.577 76.299 62.446 C 75.791 62.315 72.563 64.394 69.125 67.065"
android:strokeWidth="1.25"/>
<path
android:fillColor="#000000"
android:pathData="M 69.854 67.249 L 63.237 72.187 L 13.311 72.187 L 14.119 84.374 C 14.562 91.077 14.929 104.016 14.932 113.124 L 14.939 129.687 L 178.689 129.687 L 178.689 103.437 L 150.251 103.428 L 121.814 103.418 L 99.143 82.865 L 76.471 62.313 L 69.854 67.249"
android:strokeWidth="1.25"/>
<path
android:fillColor="#000000"
android:pathData="M 69.141 67.266 L 63.221 71.609 L 45.888 71.609 C 36.354 71.609 25.238 71.956 21.184 72.378 L 13.813 73.147 L 14.115 93.316 C 14.281 104.408 14.748 117.001 15.151 121.297 L 15.886 129.109 L 178.188 129.109 L 178.188 102.859 L 120.703 102.859 L 98.696 82.859 C 86.594 71.859 76.324 62.873 75.876 62.891 C 75.429 62.907 72.399 64.876 69.141 67.266"
android:strokeWidth="1.25"/>
</vector>

Some files were not shown because too many files have changed in this diff Show More