Compare commits
329 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8e756f058 | |||
|
|
2aa14e5ac1 | ||
| a9e2434135 | |||
|
|
da7c6b9c7e | ||
|
|
8cb6a428b8 | ||
|
|
45fd68a691 | ||
|
|
b3debd299e | ||
|
|
3db4e37b15 | ||
|
|
d4ba636d79 | ||
|
|
b5f8313c8b | ||
|
|
4c7541801e | ||
|
|
3b46301002 | ||
|
|
4e0edb8439 | ||
|
|
8410207b70 | ||
|
|
6935b56b10 | ||
|
|
2e28ec3b3b | ||
|
|
d55ca3f36a | ||
|
|
677728e777 | ||
|
|
f35cc8024f | ||
|
|
b438c19749 | ||
|
|
36147f24ae | ||
|
|
318cf2d6ff | ||
|
|
d46d0988b8 | ||
|
|
fef9704087 | ||
|
|
2e27e3c870 | ||
|
|
288abfe34e | ||
|
|
d54bc9bfed | ||
|
|
476c579574 | ||
|
|
b11f1f6140 | ||
|
|
60e2c0d181 | ||
|
|
f5c7563592 | ||
|
|
134a96902f | ||
|
|
42d234e7b1 | ||
|
|
ff08d01f05 | ||
|
|
881b81c5c2 | ||
|
|
a4c3063285 | ||
|
|
3909e55d4b | ||
|
|
e66bd88a16 | ||
|
|
ba41fe2135 | ||
|
|
8cb1749612 | ||
|
|
84b4fe25ff | ||
|
|
3661ded51c | ||
|
|
1d14ee1e5f | ||
|
|
28eb866b92 | ||
|
|
dc5ca02c7f | ||
|
|
5afdf4ec66 | ||
|
|
4dc9d516ba | ||
|
|
0244760a19 | ||
|
|
885b44b3d9 | ||
|
|
f29feffced | ||
|
|
047a6d40c8 | ||
|
|
4d5ed80495 | ||
|
|
08ee047103 | ||
|
|
7a12b4421b | ||
|
|
544a7ca610 | ||
|
|
1beec6d6f3 | ||
|
|
c1c47ac781 | ||
|
|
64ebb13708 | ||
|
|
1bfa52f911 | ||
|
|
654834e74b | ||
|
|
ee7cba88ee | ||
|
|
621fafd73b | ||
|
|
9cb7b80752 | ||
|
|
b44d204d85 | ||
|
|
80718930bd | ||
|
|
0260b93f2b | ||
|
|
2da53565a3 | ||
|
|
4e09fa357f | ||
|
|
6018e025c7 | ||
|
|
7a26bb680c | ||
|
|
af8b5b2101 | ||
|
|
0d49bb00a4 | ||
|
|
e43e0de28e | ||
|
|
b0ef79cd22 | ||
|
|
596af28122 | ||
|
|
d83a84ebb1 | ||
|
|
c6a79c52fd | ||
|
|
4cc3e7943e | ||
|
|
7f38220274 | ||
|
|
91c90c1342 | ||
|
|
ad122eac26 | ||
|
|
40be66bfb5 | ||
|
|
2c50925ba0 | ||
|
|
e62303931d | ||
|
|
69680e9415 | ||
|
|
92ebe070ab | ||
|
|
e7b724bcdd | ||
|
|
3cfc3da1fb | ||
|
|
f6b76fd2b1 | ||
|
|
d06ec4e02d | ||
|
|
3e1566fc71 | ||
|
|
23ce8c26e0 | ||
|
|
0dc562da5b | ||
|
|
89c44a7134 | ||
|
|
67826581ba | ||
|
|
da408f0fae | ||
|
|
221a68029a | ||
|
|
5cb4faad74 | ||
|
|
b680eae9a3 | ||
|
|
ecae06e225 | ||
|
|
dae91ed770 | ||
|
|
975e175c8c | ||
|
|
b7529516af | ||
|
|
f7e54b5bb7 | ||
|
|
02cdcb3595 | ||
|
|
4787b5111f | ||
|
|
c2ac80b26e | ||
|
|
d42835de19 | ||
|
|
0ec5c7ee17 | ||
|
|
8cbc195c1c | ||
|
|
34bdc76ed5 | ||
|
|
dc68150e61 | ||
|
|
11a489b80b | ||
|
|
ea27d5578c | ||
|
|
2c2c666e79 | ||
|
|
0841cef5b7 | ||
|
|
70c27d3906 | ||
|
|
dda94bb591 | ||
|
|
cf4c32a0d2 | ||
|
|
7e77774f6d | ||
|
|
85030c32bc | ||
|
|
efcb0981b3 | ||
|
|
d219e9dab7 | ||
|
|
d72f26d697 | ||
|
|
30af5429c8 | ||
|
|
00bdb4360e | ||
|
|
b7f4ffe60f | ||
|
|
bf6353c94d | ||
|
|
9e1ddd8dff | ||
|
|
3ab7d3e54c | ||
|
|
1a5f653c9a | ||
|
|
3205e0b0f3 | ||
|
|
7192398f65 | ||
|
|
0b4cc238ab | ||
|
|
128d956db2 | ||
|
|
394aa2e793 | ||
|
|
14f7c432cb | ||
|
|
af5a26eb25 | ||
|
|
3f4a69a1dd | ||
|
|
f8ec485a1c | ||
|
|
8a602bf650 | ||
|
|
f90a565d15 | ||
|
|
1b685157fa | ||
|
|
77bf539b3b | ||
|
|
98429e3f13 | ||
|
|
f0a0026ed3 | ||
|
|
55e999831a | ||
|
|
ff1be84372 | ||
|
|
c5ae56b117 | ||
|
|
753f235c4a | ||
|
|
3bac36d457 | ||
|
|
a049bb7efd | ||
|
|
d4f9134f96 | ||
|
|
1ff60bfff0 | ||
|
|
859abb5626 | ||
|
|
05e3cba485 | ||
|
|
dba2aef92a | ||
|
|
15e343047f | ||
|
|
9f813549e9 | ||
|
|
d7b9c4c999 | ||
|
|
31a56b12f8 | ||
|
|
efa692f969 | ||
|
|
bb9a27add9 | ||
|
|
e4aec89ee9 | ||
|
|
526648fcf6 | ||
|
|
f1003ce752 | ||
|
|
3dedf9c959 | ||
|
|
9d4c72dc99 | ||
|
|
234c545bec | ||
|
|
e2162b65ed | ||
|
|
cbe70f6a98 | ||
|
|
d72e165e4f | ||
|
|
8d5d48166e | ||
|
|
ff7dfce91f | ||
|
|
01ac349af0 | ||
|
|
1a4ac49ba1 | ||
|
|
05339ef6d9 | ||
|
|
823b03ee9c | ||
|
|
b22e76db0f | ||
|
|
0782313698 | ||
|
|
a1e3f9b235 | ||
|
|
41973058e6 | ||
|
|
325c2ff0ef | ||
|
|
24045995ae | ||
|
|
62a590a3e0 | ||
|
|
0ce9e4d22e | ||
|
|
2321cf482d | ||
|
|
f565d7e6c2 | ||
|
|
14f773f0bc | ||
|
|
1998146e2f | ||
|
|
3dff3e1051 | ||
|
|
df2b12b0e2 | ||
|
|
a91b970b30 | ||
|
|
11a12b9fdd | ||
|
|
86ea694955 | ||
|
|
176876bce6 | ||
|
|
8552508a5f | ||
|
|
9695a5684a | ||
|
|
c976840bcd | ||
|
|
5768223b50 | ||
|
|
b28da47d8b | ||
|
|
4ee6ecda7e | ||
|
|
ef177ba4aa | ||
|
|
622f8070f3 | ||
|
|
55dd4cee89 | ||
|
|
fc992cd6c8 | ||
|
|
037413d7ac | ||
|
|
d3b35847b1 | ||
|
|
6be8136317 | ||
|
|
179e2abe46 | ||
|
|
5d5ed9cad8 | ||
|
|
0d8b5aa9d4 | ||
|
|
08ff2f8522 | ||
|
|
91ac590976 | ||
|
|
f9faa7d9ed | ||
|
|
5be9c6e55b | ||
|
|
29a150eca3 | ||
|
|
39ad2e265c | ||
|
|
8fa8bee879 | ||
|
|
9315077c67 | ||
|
|
a2bf842855 | ||
|
|
5da3fbb258 | ||
|
|
21cab7e9a9 | ||
|
|
3b02db249a | ||
|
|
8ae42047ec | ||
|
|
e8f2b8aacd | ||
|
|
f6bd8f76c4 | ||
|
|
d4cfb60cf7 | ||
|
|
d58d8728aa | ||
|
|
363fa24baa | ||
|
|
a18c5e4bd5 | ||
|
|
c890a7708a | ||
|
|
8c9358776c | ||
|
|
1a462ed83c | ||
|
|
74dbc92458 | ||
|
|
6c901c1bef | ||
|
|
12190ecbc4 | ||
|
|
b0fb5146b2 | ||
|
|
00f0edf25e | ||
|
|
165c5e47a9 | ||
|
|
8b6ff63e03 | ||
|
|
a6255edcb4 | ||
|
|
07c948a77c | ||
|
|
bb5f08081e | ||
|
|
e42da48bbd | ||
|
|
d9b3335f6a | ||
|
|
332e7e4baf | ||
|
|
a50f0d25f8 | ||
|
|
3f8e847483 | ||
|
|
f875d13162 | ||
|
|
a0c3a0b5fb | ||
|
|
b3c23f51f2 | ||
|
|
dc9a1d06e2 | ||
|
|
ae39496553 | ||
|
|
a79e50e87a | ||
|
|
cfceb7c1c3 | ||
|
|
90b33a8325 | ||
|
|
8e39a4f7a4 | ||
|
|
7f612125c2 | ||
|
|
c085cde213 | ||
|
|
ec00c65468 | ||
|
|
9ca0fcaa96 | ||
|
|
df48e72f9c | ||
|
|
406d2da3d3 | ||
|
|
4cdcb94010 | ||
|
|
1fc2c39807 | ||
|
|
93e25021b2 | ||
|
|
ba4c32da03 | ||
|
|
d5f168f6a8 | ||
|
|
fd03aaaed9 | ||
|
|
a6435e6bc0 | ||
|
|
18ef7dd547 | ||
|
|
41fb946c65 | ||
| e50dfe2d6c | |||
|
|
aaf90056ca | ||
|
|
7591d33cea | ||
|
|
63127da10c | ||
|
|
48f3da9e08 | ||
|
|
5134fa4830 | ||
|
|
9f1f2c1765 | ||
|
|
2f24de9fb5 | ||
|
|
c0e82d61b6 | ||
|
|
ee64733e0f | ||
|
|
fff84ef56b | ||
|
|
5a4c2cf7a4 | ||
|
|
1166219abe | ||
|
|
1177faa26d | ||
|
|
d6563515fa | ||
|
|
81d0ee9346 | ||
|
|
a4ba2641dd | ||
|
|
8d237bfc07 | ||
|
|
8aa74e5081 | ||
|
|
95e9749902 | ||
|
|
37688c9479 | ||
|
|
e3197d473f | ||
|
|
07bc326cf0 | ||
|
|
31ea1b8880 | ||
|
|
2ef6bca1a6 | ||
|
|
331acdbd34 | ||
|
|
c342915eda | ||
|
|
465fa45b1a | ||
|
|
71f8171439 | ||
|
|
ad80010b94 | ||
|
|
b2c137ff35 | ||
|
|
d2bc42dafc | ||
|
|
fe3c661e29 | ||
|
|
2823ba9b6c | ||
|
|
538d6790d0 | ||
|
|
32be43fe84 | ||
|
|
2ac71df739 | ||
|
|
309c373f06 | ||
|
|
566dd12b55 | ||
|
|
2194d3fbac | ||
|
|
5d9c06b541 | ||
|
|
cf82d4e147 | ||
|
|
ca7d3a1466 | ||
|
|
e773c45961 | ||
|
|
4d04a8c99b | ||
|
|
1da51d9614 | ||
|
|
cbbcc714d4 | ||
|
|
24eb056d25 | ||
|
|
8691a3526e | ||
|
|
d168819307 | ||
|
|
77522b8050 | ||
|
|
9bb70db51d | ||
|
|
3899884705 | ||
|
|
60f641a773 | ||
|
|
8b3ffd3d7b | ||
|
|
5acd6429ef |
13
.clang-format
Normal file
13
.clang-format
Normal 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
13
.github/workflows/build/action.yml
vendored
Normal 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
38
.github/workflows/gerrit.yml
vendored
Normal 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
20
.pre-commit-config.yaml
Normal 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]
|
||||
17
Android.bp
17
Android.bp
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2022-2023 The LineageOS Project
|
||||
// SPDX-FileCopyrightText: 2022-2026 The LineageOS Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@@ -7,7 +7,6 @@ soong_namespace {
|
||||
imports: [
|
||||
"hardware/google/interfaces",
|
||||
"hardware/google/pixel",
|
||||
"hardware/qcom-caf/bootctrl",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -17,3 +16,17 @@ prebuilt_hidl_interfaces {
|
||||
"vendor.oplus.hardware.cameraextension@1.0::ICameraExtensionService",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_hidl_interfaces {
|
||||
name: "hidl_pixelworks_feature_interface",
|
||||
interfaces: [
|
||||
"vendor.pixelworks.hardware.feature@1.0::IIrisFeature",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_hidl_interfaces {
|
||||
name: "hidl_zeku_explorer_interface",
|
||||
interfaces: [
|
||||
"vendor.zeku.hardware.explorer@1.0::IMmsProvider",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
ifneq ($(filter $(call my-dir),$(PRODUCT_SOONG_NAMESPACES)),)
|
||||
|
||||
include $(call all-subdir-makefiles)
|
||||
|
||||
endif
|
||||
39
DSPVolumeSynchronizer/Android.bp
Normal file
39
DSPVolumeSynchronizer/Android.bp
Normal 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,
|
||||
}
|
||||
30
DSPVolumeSynchronizer/AndroidManifest.xml
Normal file
30
DSPVolumeSynchronizer/AndroidManifest.xml
Normal 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>
|
||||
|
||||
5
DSPVolumeSynchronizer/config-dspvolume.xml
Normal file
5
DSPVolumeSynchronizer/config-dspvolume.xml
Normal 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>
|
||||
9
DSPVolumeSynchronizer/privapp-permissions-dspvolume.xml
Normal file
9
DSPVolumeSynchronizer/privapp-permissions-dspvolume.xml
Normal 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>
|
||||
5
DSPVolumeSynchronizer/res/values/strings.xml
Normal file
5
DSPVolumeSynchronizer/res/values/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- App Name -->
|
||||
<string name="app_name">DSP Volume Synchronizer</string>
|
||||
</resources>
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +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"],
|
||||
resource_dirs: ["res"],
|
||||
|
||||
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 {
|
||||
sub_dir: "permissions",
|
||||
name: "org.lineageos.euicc.xml",
|
||||
filename: "org.lineageos.euicc.xml",
|
||||
src: "org.lineageos.euicc.xml",
|
||||
product_specific: true,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
sub_dir: "sysconfig",
|
||||
name: "hidden-api-whitelist-org.lineageos.euicc.xml",
|
||||
filename: "hidden-api-whitelist-org.lineageos.euicc.xml",
|
||||
src: "hidden-api-whitelist-org.lineageos.euicc.xml",
|
||||
runtime_resource_overlay {
|
||||
name: "EuiccPolicyOplus",
|
||||
product_specific: true,
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<hidden-api-whitelisted-app package="org.lineageos.euicc" />
|
||||
</config>
|
||||
@@ -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>
|
||||
@@ -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
@@ -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\"],\"illustration_lottie\":\"sim_illustration_lottie_bottom\"}]}</string>
|
||||
<string name="sim_slot_mappings_json">{\"sim-slot-mappings\":[{\"devices\":[\"OP594DL1\"],\"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>
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
24
IFAAService/Android.bp
Normal file
24
IFAAService/Android.bp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright (C) 2022-2025 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
android_app {
|
||||
name: "IFAAService",
|
||||
srcs: [
|
||||
"src/**/*.kt",
|
||||
"src/**/*.aidl",
|
||||
],
|
||||
aidl: {
|
||||
local_include_dirs: ["src"],
|
||||
},
|
||||
|
||||
static_libs: [
|
||||
"vendor.oplus.hardware.biometrics.fingerprintpay-V1-java",
|
||||
],
|
||||
|
||||
certificate: "platform",
|
||||
platform_apis: true,
|
||||
system_ext_specific: true,
|
||||
}
|
||||
27
IFAAService/AndroidManifest.xml
Normal file
27
IFAAService/AndroidManifest.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2022-2025 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ifaa.aidl.manager">
|
||||
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:persistent="true">
|
||||
|
||||
<service
|
||||
android:name=".IfaaService"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="org.ifaa.aidl.manager.IfaaManagerService" />
|
||||
</intent-filter>
|
||||
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
8
IFAAService/res/values/strings.xml
Normal file
8
IFAAService/res/values/strings.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2022-2024 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">IFAAService</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Copyright (C) 2022 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package org.ifaa.aidl.manager;
|
||||
|
||||
interface IfaaManagerService {
|
||||
int getSupportBIOTypes();
|
||||
int startBIOManager(int authType);
|
||||
String getDeviceModel();
|
||||
byte[] processCmd(inout byte[] param);
|
||||
int getVersion();
|
||||
String getExtInfo(int authType, String keyExtInfo);
|
||||
void setExtInfo(int authType, String keyExtInfo, String valExtInfo);
|
||||
int getEnabled(int bioType);
|
||||
int[] getIDList(int bioType);
|
||||
}
|
||||
219
IFAAService/src/org/ifaa/aidl/manager/IfaaService.kt
Normal file
219
IFAAService/src/org/ifaa/aidl/manager/IfaaService.kt
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.ifaa.aidl.manager
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.graphics.Point
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.IBinder
|
||||
import android.os.ServiceManager
|
||||
import android.os.SystemProperties
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.WindowManager
|
||||
import org.json.JSONObject
|
||||
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 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
|
||||
}
|
||||
|
||||
else -> COMMAND_FAIL
|
||||
}
|
||||
|
||||
private val _deviceModel by lazy {
|
||||
SystemProperties.get(IFAA_MODEL_PROP, "OPLUS-Default")
|
||||
}
|
||||
|
||||
override fun getDeviceModel() = _deviceModel
|
||||
|
||||
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()) }
|
||||
|
||||
dim1?.let { Point(maxOf(dim1.x, dim2.x), maxOf(dim1.y, dim2.y)) } ?: dim2
|
||||
}
|
||||
|
||||
private val iconDiameter by lazy { SystemProperties.getInt(FP_ICON_SIZE_PROP, 190) }
|
||||
|
||||
// Coordinates of the upper left corner
|
||||
private val iconLocation by lazy {
|
||||
val iconLocationBottom = SystemProperties.getInt(FP_ICON_LOCATION_PROP, 278)
|
||||
Point(
|
||||
(defaultDisplayDimension.x - iconDiameter) / 2,
|
||||
defaultDisplayDimension.y - iconLocationBottom - iconDiameter / 2,
|
||||
)
|
||||
}
|
||||
|
||||
private fun initExtString() = run {
|
||||
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,
|
||||
)
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG_TAG = IfaaService::class.simpleName!!
|
||||
|
||||
private const val AUTH_TYPE_NOT_SUPPORT = 0
|
||||
private const val AUTH_TYPE_FINGERPRINT = 1
|
||||
private const val AUTH_TYPE_OPTICAL_FINGERPRINT = 1.shl(4).or(AUTH_TYPE_FINGERPRINT)
|
||||
|
||||
private const val BIOMETRIC_USE_READY = 1000
|
||||
private const val BIOMETRIC_NOUSE_SYSTEMLOCKED = 1001
|
||||
private const val BIOMETRIC_NOUSE_NOT_ENROLLED = 1002
|
||||
private const val BIOMETRIC_NOUSE_NOSET_KEYGUARD = 1003
|
||||
|
||||
private const val COMMAND_OK = 0
|
||||
private const val COMMAND_FAIL = -1
|
||||
|
||||
// Populated by fingerprint HAL
|
||||
private const val FP_TYPE_PROP = "persist.vendor.fingerprint.sensor_type"
|
||||
private const val FP_ICON_SIZE_PROP = "persist.vendor.fingerprint.optical.iconsize"
|
||||
private const val FP_ICON_LOCATION_PROP = "persist.vendor.fingerprint.optical.iconlocation"
|
||||
|
||||
// NOTE: Populate ifaaModel from /my_stock/etc/sys_alipay_model_list.json
|
||||
private const val IFAA_MODEL_PROP = "sys.oplus.ifaa.model"
|
||||
|
||||
private const val KEY_GET_SENSOR_LOCATION = "org.ifaa.ext.key.GET_SENSOR_LOCATION"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ android_app {
|
||||
name: "KeyHandler",
|
||||
|
||||
srcs: ["src/**/*.kt"],
|
||||
resource_dirs: ["res"],
|
||||
|
||||
certificate: "platform",
|
||||
platform_apis: true,
|
||||
@@ -13,7 +12,9 @@ android_app {
|
||||
],
|
||||
|
||||
optimize: {
|
||||
optimize: true,
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
shrink_resources: true,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
21
KeyHandler/res/values-bg/strings.xml
Normal file
21
KeyHandler/res/values-bg/strings.xml
Normal 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>
|
||||
21
KeyHandler/res/values-fa/strings.xml
Normal file
21
KeyHandler/res/values-fa/strings.xml
Normal 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>
|
||||
@@ -4,5 +4,18 @@
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="alert_slider_category_title">Sleamhnán foláirimh</string>
|
||||
<string name="alert_slider_selection_dialog_title">Gníomh</string>
|
||||
<string name="alert_slider_top_position">Seasamh barr</string>
|
||||
<string name="alert_slider_middle_position">Seasamh meánach</string>
|
||||
<string name="alert_slider_bottom_position">Seasamh bun</string>
|
||||
<string name="alert_slider_mode_none">Dada</string>
|
||||
<string name="alert_slider_mode_silent">Ciúin</string>
|
||||
<string name="alert_slider_mode_normal">Gnáth</string>
|
||||
<string name="alert_slider_mode_vibration">Creathadh</string>
|
||||
<string name="alert_slider_mode_dnd_priority_only">Tosaíocht amháin</string>
|
||||
<string name="alert_slider_mode_dnd_total_silence">Ciúnas iomlán</string>
|
||||
<string name="alert_slider_mode_dnd_alarms_only">Aláraim amháin</string>
|
||||
<string name="alert_slider_mute_media_title">Balbhaigh meáin</string>
|
||||
<string name="alert_slider_mute_media_summary">Balbhaigh na meáin nuair a bhíonn tú ag aistriú chuig an gciúin</string>
|
||||
</resources>
|
||||
|
||||
21
KeyHandler/res/values-iw/strings.xml
Normal file
21
KeyHandler/res/values-iw/strings.xml
Normal 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>
|
||||
@@ -17,5 +17,5 @@
|
||||
<string name="alert_slider_mode_dnd_total_silence">Silêncio total</string>
|
||||
<string name="alert_slider_mode_dnd_alarms_only">Somente alarmes</string>
|
||||
<string name="alert_slider_mute_media_title">Silenciar mídia</string>
|
||||
<string name="alert_slider_mute_media_summary">Silenciar mídia ao mudar para modo silencioso</string>
|
||||
<string name="alert_slider_mute_media_summary">Silenciar mídia ao mudar para o modo silencioso</string>
|
||||
</resources>
|
||||
|
||||
19
KeyHandler/res/values-sc-rIT/strings.xml
Normal file
19
KeyHandler/res/values-sc-rIT/strings.xml
Normal 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>
|
||||
@@ -4,5 +4,10 @@
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="alert_slider_selection_dialog_title">Åtgärd</string>
|
||||
<string name="alert_slider_mode_none">Inget</string>
|
||||
<string name="alert_slider_mode_normal">Normal</string>
|
||||
<string name="alert_slider_mode_vibration">Vibration</string>
|
||||
<string name="alert_slider_mode_dnd_priority_only">Endast prioritet</string>
|
||||
<string name="alert_slider_mode_dnd_alarms_only">Endast alarm</string>
|
||||
</resources>
|
||||
|
||||
12
KeyHandler/res/values-ta/strings.xml
Normal file
12
KeyHandler/res/values-ta/strings.xml
Normal 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>
|
||||
21
KeyHandler/res/values-ug/strings.xml
Normal file
21
KeyHandler/res/values-ug/strings.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
30
Pen/Android.bp
Normal file
30
Pen/Android.bp
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
android_app {
|
||||
name: "OplusPen",
|
||||
|
||||
srcs: ["src/**/*.kt"],
|
||||
|
||||
certificate: "platform",
|
||||
platform_apis: true,
|
||||
privileged: true,
|
||||
system_ext_specific: true,
|
||||
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
},
|
||||
required: [
|
||||
"default-permissions_org.lineageos.pen",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "default-permissions_org.lineageos.pen",
|
||||
system_ext_specific: true,
|
||||
src: "default-permissions_org.lineageos.pen.xml",
|
||||
sub_dir: "default-permissions",
|
||||
filename_from_src: true,
|
||||
}
|
||||
33
Pen/AndroidManifest.xml
Normal file
33
Pen/AndroidManifest.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.lineageos.pen">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<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"
|
||||
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>
|
||||
<service
|
||||
android:exported="false"
|
||||
android:name=".PenService" />
|
||||
</application>
|
||||
</manifest>
|
||||
12
Pen/default-permissions_org.lineageos.pen.xml
Normal file
12
Pen/default-permissions_org.lineageos.pen.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<exceptions>
|
||||
<exception package="org.lineageos.pen">
|
||||
<permission name="android.permission.BLUETOOTH_CONNECT" fixed="false" />
|
||||
<permission name="android.permission.BLUETOOTH_SCAN" fixed="false" />
|
||||
<permission name="android.permission.POST_NOTIFICATIONS" fixed="false" />
|
||||
</exception>
|
||||
</exceptions>
|
||||
3
Pen/proguard.flags
Normal file
3
Pen/proguard.flags
Normal file
@@ -0,0 +1,3 @@
|
||||
-keep class org.lineageos.pen.* {
|
||||
*;
|
||||
}
|
||||
15
Pen/res/drawable/ic_stylus.xml
Normal file
15
Pen/res/drawable/ic_stylus.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: Material Design Authors / Google LLC
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#000000"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M167,840Q146,845 130.5,829.5Q115,814 120,793L160,602L358,800L167,840ZM358,800L160,602L618,144Q641,121 675,121Q709,121 732,144L816,228Q839,251 839,285Q839,319 816,342L358,800ZM675,200L261,614L346,699L760,285Q760,285 760,285Q760,285 760,285L675,200Q675,200 675,200Q675,200 675,200Z" />
|
||||
</vector>
|
||||
9
Pen/res/values-az/strings.xml
Normal file
9
Pen/res/values-az/strings.xml
Normal 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>
|
||||
9
Pen/res/values-bg/strings.xml
Normal file
9
Pen/res/values-bg/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ca/strings.xml
Normal file
9
Pen/res/values-ca/strings.xml
Normal 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>
|
||||
9
Pen/res/values-cs/strings.xml
Normal file
9
Pen/res/values-cs/strings.xml
Normal 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>
|
||||
9
Pen/res/values-el/strings.xml
Normal file
9
Pen/res/values-el/strings.xml
Normal 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>
|
||||
9
Pen/res/values-en-rAU/strings.xml
Normal file
9
Pen/res/values-en-rAU/strings.xml
Normal 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>
|
||||
9
Pen/res/values-en-rCA/strings.xml
Normal file
9
Pen/res/values-en-rCA/strings.xml
Normal 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>
|
||||
9
Pen/res/values-en-rGB/strings.xml
Normal file
9
Pen/res/values-en-rGB/strings.xml
Normal 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>
|
||||
9
Pen/res/values-en-rIN/strings.xml
Normal file
9
Pen/res/values-en-rIN/strings.xml
Normal 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>
|
||||
9
Pen/res/values-es/strings.xml
Normal file
9
Pen/res/values-es/strings.xml
Normal 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>
|
||||
9
Pen/res/values-fa/strings.xml
Normal file
9
Pen/res/values-fa/strings.xml
Normal 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>
|
||||
9
Pen/res/values-fr/strings.xml
Normal file
9
Pen/res/values-fr/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ga-rIE/strings.xml
Normal file
9
Pen/res/values-ga-rIE/strings.xml
Normal 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>
|
||||
9
Pen/res/values-hu/strings.xml
Normal file
9
Pen/res/values-hu/strings.xml
Normal 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>
|
||||
9
Pen/res/values-it/strings.xml
Normal file
9
Pen/res/values-it/strings.xml
Normal 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>
|
||||
9
Pen/res/values-iw/strings.xml
Normal file
9
Pen/res/values-iw/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ja/strings.xml
Normal file
9
Pen/res/values-ja/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ka/strings.xml
Normal file
9
Pen/res/values-ka/strings.xml
Normal 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>
|
||||
9
Pen/res/values-pl/strings.xml
Normal file
9
Pen/res/values-pl/strings.xml
Normal 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>
|
||||
9
Pen/res/values-pt-rBR/strings.xml
Normal file
9
Pen/res/values-pt-rBR/strings.xml
Normal 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>
|
||||
9
Pen/res/values-pt-rPT/strings.xml
Normal file
9
Pen/res/values-pt-rPT/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ro/strings.xml
Normal file
9
Pen/res/values-ro/strings.xml
Normal 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>
|
||||
8
Pen/res/values-ru/strings.xml
Normal file
8
Pen/res/values-ru/strings.xml
Normal 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>
|
||||
9
Pen/res/values-sc-rIT/strings.xml
Normal file
9
Pen/res/values-sc-rIT/strings.xml
Normal 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>
|
||||
9
Pen/res/values-sl/strings.xml
Normal file
9
Pen/res/values-sl/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ta/strings.xml
Normal file
9
Pen/res/values-ta/strings.xml
Normal 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>
|
||||
9
Pen/res/values-ug/strings.xml
Normal file
9
Pen/res/values-ug/strings.xml
Normal 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>
|
||||
9
Pen/res/values-vi/strings.xml
Normal file
9
Pen/res/values-vi/strings.xml
Normal 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>
|
||||
9
Pen/res/values-zh-rCN/strings.xml
Normal file
9
Pen/res/values-zh-rCN/strings.xml
Normal 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>
|
||||
9
Pen/res/values/config.xml
Normal file
9
Pen/res/values/config.xml
Normal 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>
|
||||
10
Pen/res/values/strings.xml
Normal file
10
Pen/res/values/strings.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">OplusPen</string>
|
||||
<string name="pen_attached">Pen attached</string>
|
||||
<string name="tap_to_connect">Tap to connect</string>
|
||||
</resources>
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The LineageOS Project
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.lineageos.euicc
|
||||
package org.lineageos.pen
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
@@ -13,10 +13,10 @@ import android.util.Log
|
||||
class BootCompletedReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Log.d(TAG, "Received boot completed intent")
|
||||
EuiccDisabler.enableOrDisableEuicc(context)
|
||||
context.startService(Intent(context, PenService::class.java))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "OplusEuiccBootReceiver"
|
||||
private const val TAG = "OplusPenBootReceiver"
|
||||
}
|
||||
}
|
||||
232
Pen/src/org/lineageos/pen/PenService.kt
Normal file
232
Pen/src/org/lineageos/pen/PenService.kt
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.lineageos.pen
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
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 penSupportedRefreshRate by lazy {
|
||||
getString(R.string.config_penSupportedRefreshRate)
|
||||
}
|
||||
|
||||
private val handler by lazy { Handler(mainLooper) }
|
||||
|
||||
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) }
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
private fun bondBtDevice(pencilAddr: String) {
|
||||
val adapter = bluetoothManager.adapter
|
||||
@Suppress("DEPRECATION") adapter.enable()
|
||||
|
||||
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)
|
||||
.setReportDelay(0L)
|
||||
.build(),
|
||||
object : ScanCallback() {
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
super.onScanResult(callbackType, result)
|
||||
scanner.stopScan(this)
|
||||
|
||||
result.device.createBond()
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: MutableList<ScanResult>) {
|
||||
super.onBatchScanResults(results)
|
||||
scanner.stopScan(this)
|
||||
}
|
||||
|
||||
override fun onScanFailed(errorCode: Int) {
|
||||
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
|
||||
|
||||
if (adapter.bondedDevices.contains(adapter.getRemoteDevice(pencilAddr))) {
|
||||
Log.e(TAG, "$pencilAddr already bonded, bailing out")
|
||||
return
|
||||
}
|
||||
|
||||
if (notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) {
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_ID,
|
||||
NOTIFICATION_CHANNEL_ID,
|
||||
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 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)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "OplusPenService"
|
||||
|
||||
private const val EXTRA_PENCIL_ADDR = "pencil_addr"
|
||||
|
||||
private const val NOTIFICATION_CHANNEL_ID = "OplusPen"
|
||||
private const val NOTIFICATION_ID = 1000
|
||||
}
|
||||
}
|
||||
18
README.md
Normal file
18
README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# hardware/oplus
|
||||
|
||||
## Soong options
|
||||
|
||||
| Namespace | Variable | Description | Default |
|
||||
| --------- | -------- | ----------- | ------- |
|
||||
| OPLUS_LINEAGE_LIVEDISPLAY_HAL | ENABLE_AB | Enable AdaptiveBacklight feature | false |
|
||||
| OPLUS_LINEAGE_LIVEDISPLAY_HAL | ENABLE_AF | Enable AntiFlicker feature | false |
|
||||
| OPLUS_LINEAGE_LIVEDISPLAY_HAL | ENABLE_DM | Enable DisplayModes feature | false |
|
||||
| OPLUS_LINEAGE_LIVEDISPLAY_HAL | ENABLE_PA | Enable PictureAdjustment feature | true |
|
||||
| OPLUS_LINEAGE_LIVEDISPLAY_HAL | ENABLE_SE | Enable SunlightEnhancement feature | true |
|
||||
| OPLUS_LINEAGE_TOUCH_HAL | ENABLE_GM | Enable GloveMode feature | false |
|
||||
| OPLUS_LINEAGE_TOUCH_HAL | ENABLE_HTPR | Enable HighTouchPollingRate feature | true |
|
||||
| OPLUS_LINEAGE_TOUCH_HAL | ENABLE_TG | Enable TouchscreenGesture feature | true |
|
||||
| OPLUS_LINEAGE_TOUCH_HAL | INCLUDE_DIR | Device specific include dir path | |
|
||||
| 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 |
|
||||
22
aidl/commondcs/Android.bp
Normal file
22
aidl/commondcs/Android.bp
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Copyright (C) 2025 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
name: "vendor.oplus.hardware.commondcs-service",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["vendor.oplus.hardware.commondcs-service.rc"],
|
||||
vintf_fragments: ["vendor.oplus.hardware.commondcs-service.xml"],
|
||||
srcs: [
|
||||
"CommonDcsAidlHalService.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"vendor.oplus.hardware.commondcs-V1-ndk",
|
||||
],
|
||||
}
|
||||
26
aidl/commondcs/CommonDcsAidlHalService.cpp
Normal file
26
aidl/commondcs/CommonDcsAidlHalService.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "CommonDcsAidlHalService.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace oplus {
|
||||
namespace hardware {
|
||||
namespace commondcs {
|
||||
|
||||
ndk::ScopedAStatus CommonDcsAidlHalService::notifyMsgToCommonDcs(
|
||||
const std::vector<StringPair>& data, const std::string& logTag, const std::string& eventId,
|
||||
int32_t* _aidl_return) {
|
||||
*_aidl_return = 0;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace commondcs
|
||||
} // namespace hardware
|
||||
} // namespace oplus
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
27
aidl/commondcs/CommonDcsAidlHalService.h
Normal file
27
aidl/commondcs/CommonDcsAidlHalService.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/vendor/oplus/hardware/commondcs/BnCommonDcsAidlHalService.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace oplus {
|
||||
namespace hardware {
|
||||
namespace commondcs {
|
||||
|
||||
struct CommonDcsAidlHalService : public BnCommonDcsAidlHalService {
|
||||
ndk::ScopedAStatus notifyMsgToCommonDcs(const std::vector<StringPair>& data,
|
||||
const std::string& logTag, const std::string& eventId,
|
||||
int32_t* _aidl_return) final;
|
||||
};
|
||||
|
||||
} // namespace commondcs
|
||||
} // namespace hardware
|
||||
} // namespace oplus
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
27
aidl/commondcs/service.cpp
Normal file
27
aidl/commondcs/service.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "CommonDcsAidlHalService.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using ::aidl::vendor::oplus::hardware::commondcs::CommonDcsAidlHalService;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<CommonDcsAidlHalService> service =
|
||||
ndk::SharedRefBase::make<CommonDcsAidlHalService>();
|
||||
|
||||
const std::string instance = std::string() + CommonDcsAidlHalService::descriptor + "/default";
|
||||
binder_status_t status =
|
||||
AServiceManager_addService(service->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
service vendor.commondcs /vendor/bin/hw/vendor.oplus.hardware.commondcs-service
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>vendor.oplus.hardware.commondcs</name>
|
||||
<version>1</version>
|
||||
<fqname>ICommonDcsAidlHalService/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
19
aidl/ir/Android.bp
Normal file
19
aidl/ir/Android.bp
Normal file
@@ -0,0 +1,19 @@
|
||||
cc_binary {
|
||||
name: "android.hardware.ir-service.oplus",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["android.hardware.ir-service.oplus.rc"],
|
||||
vintf_fragments: ["android.hardware.ir-service.xml"],
|
||||
srcs: [
|
||||
"ConsumerIr.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.ir-V1-ndk",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
],
|
||||
header_libs: [
|
||||
"kernel_headers.oplus",
|
||||
],
|
||||
}
|
||||
77
aidl/ir/ConsumerIr.cpp
Normal file
77
aidl/ir/ConsumerIr.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ConsumerIr.h"
|
||||
|
||||
#include <aidl/android/hardware/ir/ConsumerIrFreqRange.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <oplus/oplus_ir_core.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace ir {
|
||||
|
||||
static constexpr int32_t MAX_PATTERN_TIME = 2000000;
|
||||
static constexpr int32_t MIN_FREQ = 20000;
|
||||
static constexpr int32_t MAX_FREQ = 60000;
|
||||
|
||||
ConsumerIr::ConsumerIr() : supportedFreqs({{MIN_FREQ, MAX_FREQ}}) {}
|
||||
|
||||
::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) {
|
||||
*_aidl_return = supportedFreqs;
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::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 : pattern) {
|
||||
if (value < 0) {
|
||||
LOG(ERROR) << "Invalid pattern value: " << value;
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
totalTime += value;
|
||||
}
|
||||
|
||||
if (totalTime > MAX_PATTERN_TIME) {
|
||||
LOG(ERROR) << "Pattern is too long: " << totalTime << " us";
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
::android::base::unique_fd fd(open("/dev/oplus_consumer_ir", O_WRONLY));
|
||||
if (!fd.ok()) {
|
||||
LOG(ERROR) << "Failed to open /dev/oplus_consumer_ir: " << strerror(errno);
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
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) {
|
||||
LOG(ERROR) << "Failed to allocate memory for IR params";
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
return result < 0 ? ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)
|
||||
: ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
30
aidl/ir/ConsumerIr.h
Normal file
30
aidl/ir/ConsumerIr.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/ir/BnConsumerIr.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace ir {
|
||||
|
||||
class ConsumerIr : public BnConsumerIr {
|
||||
public:
|
||||
ConsumerIr();
|
||||
|
||||
private:
|
||||
::ndk::ScopedAStatus getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) override;
|
||||
::ndk::ScopedAStatus transmit(int32_t carrierFreqHz,
|
||||
const std::vector<int32_t>& pattern) override;
|
||||
|
||||
std::vector<ConsumerIrFreqRange> supportedFreqs;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
9
aidl/ir/android.hardware.ir-service.oplus.rc
Normal file
9
aidl/ir/android.hardware.ir-service.oplus.rc
Normal file
@@ -0,0 +1,9 @@
|
||||
on boot
|
||||
chown system system /dev/oplus_consumer_ir
|
||||
chmod 0644 /dev/oplus_consumer_ir
|
||||
|
||||
service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.oplus
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
interface aidl android.hardware.ir.IConsumerIr/default
|
||||
7
aidl/ir/android.hardware.ir-service.xml
Normal file
7
aidl/ir/android.hardware.ir-service.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.ir</name>
|
||||
<version>1</version>
|
||||
<fqname>IConsumerIr/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
25
aidl/ir/service.cpp
Normal file
25
aidl/ir/service.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ConsumerIr.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using ::aidl::android::hardware::ir::ConsumerIr;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<ConsumerIr> consumerIr = ndk::SharedRefBase::make<ConsumerIr>();
|
||||
|
||||
const std::string instance = std::string() + ConsumerIr::descriptor + "/default";
|
||||
binder_status_t status =
|
||||
AServiceManager_addService(consumerIr->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
46
aidl/livedisplay/AdaptiveBacklight.cpp
Normal file
46
aidl/livedisplay/AdaptiveBacklight.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AdaptiveBacklightService"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fcntl.h>
|
||||
#include <livedisplay/oplus/AdaptiveBacklight.h>
|
||||
#include <oplus/oplus_display_panel.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace livedisplay {
|
||||
|
||||
AdaptiveBacklight::AdaptiveBacklight() : mOplusDisplayFd(open("/dev/oplus_display", O_RDWR)) {}
|
||||
|
||||
ndk::ScopedAStatus AdaptiveBacklight::getEnabled(bool* _aidl_return) {
|
||||
unsigned int value;
|
||||
if (ioctl(mOplusDisplayFd, PANEL_IOCTL_GET_CABC_STATUS, &value) != 0) {
|
||||
LOG(ERROR) << "Failed to read current AdaptiveBacklight state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
*_aidl_return = value > 0;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AdaptiveBacklight::setEnabled(bool enabled) {
|
||||
bool isEnabled;
|
||||
if (auto status = getEnabled(&isEnabled); !status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
unsigned int value = enabled;
|
||||
if (isEnabled != enabled && ioctl(mOplusDisplayFd, PANEL_IOCTL_SET_CABC_STATUS, &value) != 0) {
|
||||
LOG(ERROR) << "Failed to set AdaptiveBacklight state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace livedisplay
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
90
aidl/livedisplay/Android.bp
Normal file
90
aidl/livedisplay/Android.bp
Normal file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2019-2025 The LineageOS Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
filegroup {
|
||||
name: "vendor.lineage.livedisplay-oplus-ab",
|
||||
srcs: ["AdaptiveBacklight.cpp"],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "vendor.lineage.livedisplay-oplus-af",
|
||||
srcs: ["AntiFlicker.cpp"],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "vendor.lineage.livedisplay-oplus-dm",
|
||||
srcs: ["DisplayModes.cpp"],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "vendor.lineage.livedisplay-oplus-se",
|
||||
srcs: ["SunlightEnhancement.cpp"],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "vendor.lineage.livedisplay-oplus-headers",
|
||||
vendor_available: true,
|
||||
export_include_dirs: ["include"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "vendor.lineage.livedisplay-service.oplus",
|
||||
init_rc: ["vendor.lineage.livedisplay-service.oplus.rc"],
|
||||
vintf_fragments: select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_AB"), {
|
||||
"true": ["vendor.lineage.livedisplay-service.oplus-ab.xml"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_AF"), {
|
||||
"true": ["vendor.lineage.livedisplay-service.oplus-af.xml"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_DM"), {
|
||||
"true": ["vendor.lineage.livedisplay-service.oplus-dm.xml"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_PA"), {
|
||||
"false": [],
|
||||
default: ["vendor.lineage.livedisplay-service.oplus-pa.xml"],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_SE"), {
|
||||
"false": [],
|
||||
default: ["vendor.lineage.livedisplay-service.oplus-se.xml"],
|
||||
}),
|
||||
relative_install_path: "hw",
|
||||
srcs: [
|
||||
":vendor.lineage.livedisplay-sdm-pa",
|
||||
":vendor.lineage.livedisplay-sdm-utils",
|
||||
":vendor.lineage.livedisplay-oplus-ab",
|
||||
":vendor.lineage.livedisplay-oplus-af",
|
||||
":vendor.lineage.livedisplay-oplus-dm",
|
||||
":vendor.lineage.livedisplay-oplus-se",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libbinder",
|
||||
"libutils",
|
||||
"vendor.lineage.livedisplay-V1-ndk",
|
||||
],
|
||||
header_libs: [
|
||||
"kernel_headers.oplus",
|
||||
"vendor.lineage.livedisplay-sdm-headers",
|
||||
"vendor.lineage.livedisplay-oplus-headers",
|
||||
],
|
||||
cflags: select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_AB"), {
|
||||
"true": ["-DENABLE_AB=true"],
|
||||
default: ["-DENABLE_AB=false"],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_AF"), {
|
||||
"true": ["-DENABLE_AF=true"],
|
||||
default: ["-DENABLE_AF=false"],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_DM"), {
|
||||
"true": ["-DENABLE_DM=true"],
|
||||
default: ["-DENABLE_DM=false"],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_PA"), {
|
||||
"false": ["-DENABLE_PA=false"],
|
||||
default: ["-DENABLE_PA=true"],
|
||||
}) + select(soong_config_variable("OPLUS_LINEAGE_LIVEDISPLAY_HAL", "ENABLE_SE"), {
|
||||
"false": ["-DENABLE_SE=false"],
|
||||
default: ["-DENABLE_SE=true"],
|
||||
}),
|
||||
proprietary: true,
|
||||
}
|
||||
50
aidl/livedisplay/AntiFlicker.cpp
Normal file
50
aidl/livedisplay/AntiFlicker.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AntiFlickerService"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fcntl.h>
|
||||
#include <livedisplay/oplus/AntiFlicker.h>
|
||||
#include <oplus/oplus_display_panel.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace livedisplay {
|
||||
|
||||
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_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);
|
||||
}
|
||||
*_aidl_return = value > 0;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AntiFlicker::setEnabled(bool enabled) {
|
||||
bool isEnabled;
|
||||
if (auto status = getEnabled(&isEnabled); !status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
unsigned int value = 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);
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace livedisplay
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user