Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd7c47e793 | ||
|
|
02dd7c3c56 | ||
|
|
f62a2c9eeb | ||
|
|
4e2ce1d8d8 | ||
|
|
230888e2bf | ||
|
|
36013e8d1e | ||
|
|
d94967c306 | ||
|
|
7e0d5aee84 | ||
|
|
a047cd0e9c | ||
|
|
ce2e14c9cb | ||
|
|
070b86f599 | ||
|
|
5afba6fd79 | ||
|
|
1d8c9ea4be | ||
|
|
5c60662e3e | ||
|
|
93279a0cd0 | ||
|
|
57366c40d5 | ||
|
|
dd598de4bc | ||
|
|
fab72f6b5b | ||
|
|
c2e5046b68 | ||
|
|
46e5d2d42b | ||
|
|
30d76ef466 | ||
|
|
c8d7bb56f5 | ||
|
|
a0aa2970a7 | ||
|
|
be34cb1415 | ||
|
|
caaf1534cf | ||
|
|
ce9b047f39 | ||
|
|
ce324574da | ||
|
|
126ff7676b | ||
|
|
70a27f6856 | ||
|
|
785a2b1d9d | ||
|
|
bba31b00d2 | ||
|
|
505310f835 | ||
|
|
b14334f2d5 | ||
|
|
0b6822d5f3 | ||
|
|
598db92c74 | ||
|
|
6a4f5955bb | ||
|
|
8324f4930e | ||
|
|
2ed020295d | ||
|
|
9034fe2625 | ||
|
|
c89510a83d | ||
|
|
37ad6f91a8 | ||
|
|
f103b97ebb | ||
|
|
f8ba52c219 | ||
|
|
1ca613f5fc | ||
|
|
de18245d3d | ||
|
|
fc3cea066b | ||
|
|
a8358855a7 | ||
|
|
55e2934dd1 | ||
|
|
6af2127ff2 | ||
|
|
933e0e1264 | ||
|
|
7538a10c0e | ||
|
|
3f91fa1724 | ||
|
|
98cf605161 | ||
|
|
f5b202281a | ||
|
|
636ce206a0 | ||
|
|
33a419e8c1 | ||
|
|
064c24617e | ||
|
|
4d7a952308 | ||
|
|
06bfc823ef | ||
|
|
641b58600b | ||
|
|
6454f6c267 | ||
|
|
6785f93e35 | ||
|
|
3bb55820e8 | ||
|
|
0b8722e673 | ||
|
|
3a4813d67b | ||
|
|
1300e116bc | ||
|
|
88247d9e05 | ||
|
|
bb6f814a3d | ||
|
|
b56de4957c | ||
|
|
dc3069c44b | ||
|
|
c8cd550f87 | ||
|
|
35d550916c | ||
|
|
1b81776dd7 | ||
|
|
864199e705 | ||
|
|
94ac6370ad | ||
|
|
ba11fe6f76 | ||
|
|
4ed4bb5c77 | ||
|
|
1c49eb9f6c |
48
DSPVolumeSynchronizer/Android.bp
Normal file
48
DSPVolumeSynchronizer/Android.bp
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// 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",
|
||||
"preinstalled-packages-platform-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,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "preinstalled-packages-platform-dspvolume",
|
||||
relative_install_path: "sysconfig",
|
||||
src: "preinstalled-packages-platform-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>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2025 crDroid Android Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<config>
|
||||
|
||||
<!-- Dolby -->
|
||||
<install-in-user-type package="org.lineageos.dspvolume.xiaomi">
|
||||
<install-in user-type="FULL" />
|
||||
<install-in user-type="PROFILE" />
|
||||
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
|
||||
<do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
|
||||
</install-in-user-type>
|
||||
</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);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,43 @@ android_app {
|
||||
required: [
|
||||
"co.aospa.euicc.xml",
|
||||
"hidden-api-whitelist-co.aospa.euicc.xml",
|
||||
"EuiccGoogle",
|
||||
],
|
||||
}
|
||||
|
||||
android_app_import {
|
||||
name: "EuiccGoogle",
|
||||
owner: "xiaomi",
|
||||
apk: "proprietary/product/priv-app/EuiccGoogle/EuiccGoogle.apk",
|
||||
preprocessed: true,
|
||||
presigned: true,
|
||||
dex_preopt: {
|
||||
enabled: false,
|
||||
},
|
||||
privileged: true,
|
||||
product_specific: true,
|
||||
required: [
|
||||
"default-permissions-euicc.xml",
|
||||
"privapp-permissions-euiccgoogle.xml",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
sub_dir: "default-permissions",
|
||||
name: "default-permissions-euicc.xml",
|
||||
filename: "default-permissions-euicc.xml",
|
||||
src: "default-permissions-euicc.xml",
|
||||
product_specific: true,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
sub_dir: "permissions",
|
||||
name: "privapp-permissions-euiccgoogle.xml",
|
||||
filename: "privapp-permissions-euiccgoogle.xml",
|
||||
src: "privapp-permissions-euiccgoogle.xml",
|
||||
product_specific: true,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
sub_dir: "permissions",
|
||||
name: "co.aospa.euicc.xml",
|
||||
|
||||
40
Euicc/default-permissions-euicc.xml
Normal file
40
Euicc/default-permissions-euicc.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
|
||||
<!-- Copyright (C) 2019 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file contains permissions to be granted by default. Default
|
||||
permissions are granted to special platform components and to apps
|
||||
that are approved to get default grants. The special components
|
||||
are apps that are expected tto work out-of-the-box as they provide
|
||||
core use cases such as default dialer, default email, etc. These
|
||||
grants are managed by the platform. The apps that are additionally
|
||||
approved for default grants are ones that provide carrier specific
|
||||
functionality, ones legally required at some location, ones providing
|
||||
alternative disclosure and opt-out UI, ones providing highlight features
|
||||
of a dedicated device, etc. This file contains only the latter exceptions.
|
||||
Fixed permissions cannot be controlled by the user and need a special
|
||||
approval. Typically these are to ensure either legally mandated functions
|
||||
or the app is considered a part of the OS.
|
||||
-->
|
||||
|
||||
<exceptions>
|
||||
<exception
|
||||
package="com.google.android.euicc">
|
||||
<!-- Notifications -->
|
||||
<permission name="android.permission.POST_NOTIFICATIONS" fixed="false"/>
|
||||
</exception>
|
||||
</exceptions>
|
||||
25
Euicc/privapp-permissions-euiccgoogle.xml
Normal file
25
Euicc/privapp-permissions-euiccgoogle.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<permissions>
|
||||
<privapp-permissions package="com.google.android.euicc">
|
||||
<permission name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
|
||||
<permission name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<permission name="android.permission.MODIFY_PHONE_STATE"/>
|
||||
<permission name="android.permission.INTERNET"/>
|
||||
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
||||
<permission name="android.permission.REBOOT"/>
|
||||
<permission name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
|
||||
<permission name="android.permission.VIBRATE"/>
|
||||
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
|
||||
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
<permission name="com.android.permission.INSTALL_EXISTING_PACKAGES"/>
|
||||
<permission name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
|
||||
<permission name="com.android.permission.INSTALL_EXISTING_PACKAGES" />
|
||||
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
|
||||
<permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
|
||||
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
|
||||
<permission name="com.google.android.setupwizard.SETUP_COMPAT_SERVICE"/>
|
||||
<permission name="com.google.android.permission.USE_GRIL" />
|
||||
</privapp-permissions>
|
||||
</permissions>
|
||||
BIN
Euicc/proprietary/product/priv-app/EuiccGoogle/EuiccGoogle.apk
Normal file
BIN
Euicc/proprietary/product/priv-app/EuiccGoogle/EuiccGoogle.apk
Normal file
Binary file not shown.
@@ -4,6 +4,6 @@
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="sim_illustration_lottie_mappings_json">{\"sim_illustration_lottie_mappings\":[{\"devices\":[\"diting\"],\"illustration_lottie\":\"sim_illustration_lottie_bottom\"}]}</string>
|
||||
<string name="sim_slot_mappings_json">{\"sim-slot-mappings\":[{\"devices\":[\"diting\"],\"esim-slot-ids\":[1],\"psim-slot-ids\":[0]}]}</string>
|
||||
<string name="sim_illustration_lottie_mappings_json">{\"sim_illustration_lottie_mappings\":[{\"devices\":[\"diting\",\"ziyi\",\"nuwa\",\"fuxi\"],\"illustration_lottie\":\"sim_illustration_lottie_bottom\"}]}</string>
|
||||
<string name="sim_slot_mappings_json">{\"sim-slot-mappings\":[{\"devices\":[\"diting\",\"ziyi\",\"nuwa\",\"fuxi\"],\"esim-slot-ids\":[1],\"psim-slot-ids\":[0]}]}</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The LineageOS Project
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,7 @@ package co.aospa.euicc
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.PackageInfoFlags
|
||||
import android.content.pm.PackageManager.ApplicationInfoFlags
|
||||
import android.util.Log
|
||||
|
||||
object EuiccDisabler {
|
||||
@@ -25,14 +25,14 @@ object EuiccDisabler {
|
||||
)
|
||||
|
||||
private fun isInstalled(pm: PackageManager, pkgName: String) = runCatching {
|
||||
val info = pm.getPackageInfo(pkgName, PackageInfoFlags.of(0))
|
||||
info.applicationInfo.flags and ApplicationInfo.FLAG_INSTALLED != 0
|
||||
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.getPackageInfo(pkgName, PackageInfoFlags.of(0))
|
||||
Log.d(TAG, "package $pkgName installed, enabled = ${info.applicationInfo.enabled}")
|
||||
info.applicationInfo.enabled
|
||||
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) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 The LineageOS Project
|
||||
* SPDX-FileCopyrightText: 2022-2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -46,11 +46,11 @@ class IfaaService : Service() {
|
||||
|
||||
override fun startBIOManager(authType: Int) = when (authType) {
|
||||
AUTH_TYPE_FINGERPRINT -> {
|
||||
val intent = Intent(Settings.ACTION_SECURITY_SETTINGS).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
applicationContext.startActivity(intent)
|
||||
applicationContext.startActivity(
|
||||
Intent(Settings.ACTION_SECURITY_SETTINGS).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
)
|
||||
|
||||
COMMAND_OK
|
||||
}
|
||||
|
||||
10
README.md
Normal file
10
README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# hardware/xiaomi
|
||||
|
||||
## Soong options
|
||||
|
||||
| Namespace | Variable | Description | Default |
|
||||
| --------- | -------- | ----------- | ------- |
|
||||
| XIAOMI_BIOMETRICS_FINGERPRINT | RUN_32BIT | Opt to run service in 32-bit mode only | false |
|
||||
| XIAOMI_TOUCH | HIGH_TOUCH_POLLING_PATH | HighTouchPollingRate feature control path | |
|
||||
| XIAOMI_TOUCH | KEY_DISABLER_CONTROL_PATH | KeyDisabler feature control path | |
|
||||
| XIAOMI_TOUCH | KEY_SWAPPER_CONTROL_PATH | KeySwapper feature control path | |
|
||||
74
aidl/fingerprint/Android.bp
Normal file
74
aidl/fingerprint/Android.bp
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Copyright (C) 2024-2025 The LineageOS Project
|
||||
// 2024 Paranoid Android
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
soong_config_module_type {
|
||||
name: "xiaomi_hardware_biometrics_config_default",
|
||||
module_type: "cc_defaults",
|
||||
config_namespace: "XIAOMI_BIOMETRICS_FINGERPRINT",
|
||||
bool_variables: [
|
||||
"RUN_32BIT",
|
||||
],
|
||||
properties: ["compile_multilib"],
|
||||
}
|
||||
|
||||
xiaomi_hardware_biometrics_config_default {
|
||||
name: "xiaomi_hardware_biometrics_config_default",
|
||||
|
||||
soong_config_variables: {
|
||||
RUN_32BIT: {
|
||||
conditions_default: {
|
||||
compile_multilib: "64",
|
||||
},
|
||||
compile_multilib: "prefer32",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.fingerprint-service.xiaomi",
|
||||
defaults: ["xiaomi_hardware_biometrics_config_default"],
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["android.hardware.biometrics.fingerprint-service.xiaomi.rc"],
|
||||
vintf_fragments: ["android.hardware.biometrics.fingerprint-service.xiaomi.xml"],
|
||||
srcs: [
|
||||
"CancellationSignal.cpp",
|
||||
"Fingerprint.cpp",
|
||||
"FingerprintConfig.cpp",
|
||||
"LockoutTracker.cpp",
|
||||
"Session.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
local_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libcutils",
|
||||
"libhardware",
|
||||
"libdl",
|
||||
"liblog",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.Props",
|
||||
"libudfpshandlerfactory",
|
||||
],
|
||||
vendor: true,
|
||||
header_libs: ["xiaomifingerprint_headers"],
|
||||
}
|
||||
|
||||
sysprop_library {
|
||||
name: "android.hardware.biometrics.fingerprint.Props",
|
||||
srcs: ["fingerprint.sysprop"],
|
||||
property_owner: "Vendor",
|
||||
vendor: true,
|
||||
}
|
||||
17
aidl/fingerprint/CancellationSignal.cpp
Normal file
17
aidl/fingerprint/CancellationSignal.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "CancellationSignal.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
CancellationSignal::CancellationSignal(Session* session) : mSession(session) {}
|
||||
|
||||
ndk::ScopedAStatus CancellationSignal::cancel() {
|
||||
return mSession->cancel();
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
25
aidl/fingerprint/CancellationSignal.h
Normal file
25
aidl/fingerprint/CancellationSignal.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
|
||||
|
||||
#include "Session.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class CancellationSignal
|
||||
: public ::aidl::android::hardware::biometrics::common::BnCancellationSignal {
|
||||
public:
|
||||
CancellationSignal(Session* session);
|
||||
ndk::ScopedAStatus cancel() override;
|
||||
|
||||
private:
|
||||
Session* mSession;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
255
aidl/fingerprint/Fingerprint.cpp
Normal file
255
aidl/fingerprint/Fingerprint.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 The LineageOS Project
|
||||
* 2024 Paranoid Android
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Fingerprint.h"
|
||||
|
||||
#include <android-base/properties.h>
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include "util/Util.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
using ::android::base::SetProperty;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
namespace {
|
||||
constexpr int MAX_ENROLLMENTS_PER_USER = 5;
|
||||
constexpr char HW_COMPONENT_ID[] = "fingerprintSensor";
|
||||
constexpr char HW_VERSION[] = "vendor/model/revision";
|
||||
constexpr char FW_VERSION[] = "1.01";
|
||||
constexpr char SERIAL_NUMBER[] = "00000001";
|
||||
constexpr char SW_COMPONENT_ID[] = "matchingAlgorithm";
|
||||
constexpr char SW_VERSION[] = "vendor/version/revision";
|
||||
|
||||
typedef struct fingerprint_hal {
|
||||
const char* class_name;
|
||||
} fingerprint_hal_t;
|
||||
|
||||
static const fingerprint_hal_t kModules[] = {
|
||||
{"fortsense"}, {"fpc"}, {"fpc_fod"}, {"goodix"}, {"goodix:gf_fingerprint"},
|
||||
{"goodix_fod"}, {"goodix_fod6"}, {"silead"}, {"syna"},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1);
|
||||
static Fingerprint* sInstance;
|
||||
|
||||
Fingerprint::Fingerprint(std::shared_ptr<FingerprintConfig> config) : mConfig(std::move(config)) {
|
||||
sInstance = this; // keep track of the most recent instance
|
||||
|
||||
if (mDevice) {
|
||||
ALOGI("fingerprint HAL already opened");
|
||||
} else {
|
||||
for (auto& [module] : kModules) {
|
||||
std::string class_name;
|
||||
std::string class_module_id;
|
||||
|
||||
auto parts = ::android::base::Split(module, ":");
|
||||
|
||||
if (parts.size() == 2) {
|
||||
class_name = parts[0];
|
||||
class_module_id = parts[1];
|
||||
} else {
|
||||
class_name = module;
|
||||
class_module_id = FINGERPRINT_HARDWARE_MODULE_ID;
|
||||
}
|
||||
|
||||
mDevice = openFingerprintHal(class_name.c_str(), class_module_id.c_str());
|
||||
if (!mDevice) {
|
||||
ALOGE("Can't open HAL module, class: %s, module_id: %s", class_name.c_str(),
|
||||
class_module_id.c_str());
|
||||
continue;
|
||||
}
|
||||
ALOGI("Opened fingerprint HAL, class: %s, module_id: %s", class_name.c_str(),
|
||||
class_module_id.c_str());
|
||||
SetProperty("persist.vendor.sys.fp.vendor", class_name);
|
||||
break;
|
||||
}
|
||||
if (!mDevice) {
|
||||
ALOGE("Can't open any fingerprint HAL module");
|
||||
SetProperty("persist.vendor.sys.fp.vendor", "none");
|
||||
}
|
||||
}
|
||||
|
||||
std::string sensorTypeProp = mConfig->get<std::string>("type");
|
||||
if (sensorTypeProp == "udfps" || sensorTypeProp == "udfps_optical") {
|
||||
SetProperty("ro.hardware.fp.udfps", "true");
|
||||
|
||||
if (sensorTypeProp == "udfps") {
|
||||
mSensorType = FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC;
|
||||
} else {
|
||||
mSensorType = FingerprintSensorType::UNDER_DISPLAY_OPTICAL;
|
||||
}
|
||||
mUdfpsHandlerFactory = getUdfpsHandlerFactory();
|
||||
if (!mUdfpsHandlerFactory) {
|
||||
ALOGE("Can't get UdfpsHandlerFactory");
|
||||
} else {
|
||||
mUdfpsHandler = mUdfpsHandlerFactory->create();
|
||||
if (!mUdfpsHandler) {
|
||||
ALOGE("Can't create UdfpsHandler");
|
||||
} else {
|
||||
mUdfpsHandler->init(mDevice);
|
||||
}
|
||||
}
|
||||
} else if (sensorTypeProp == "side") {
|
||||
mSensorType = FingerprintSensorType::POWER_BUTTON;
|
||||
} else if (sensorTypeProp == "home") {
|
||||
mSensorType = FingerprintSensorType::HOME_BUTTON;
|
||||
} else if (sensorTypeProp == "rear") {
|
||||
mSensorType = FingerprintSensorType::REAR;
|
||||
} else {
|
||||
mSensorType = FingerprintSensorType::UNKNOWN;
|
||||
UNIMPLEMENTED(FATAL) << "unrecognized or unimplemented fingerprint behavior: "
|
||||
<< sensorTypeProp;
|
||||
}
|
||||
ALOGI("sensorTypeProp: %s", sensorTypeProp.c_str());
|
||||
}
|
||||
|
||||
Fingerprint::~Fingerprint() {
|
||||
ALOGV("~Fingerprint()");
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandlerFactory->destroy(mUdfpsHandler);
|
||||
}
|
||||
if (mDevice == nullptr) {
|
||||
ALOGE("No valid device");
|
||||
return;
|
||||
}
|
||||
int err;
|
||||
if (0 != (err = mDevice->common.close(reinterpret_cast<hw_device_t*>(mDevice)))) {
|
||||
ALOGE("Can't close fingerprint module, error: %d", err);
|
||||
return;
|
||||
}
|
||||
mDevice = nullptr;
|
||||
}
|
||||
|
||||
fingerprint_device_t* Fingerprint::openFingerprintHal(const char* class_name,
|
||||
const char* module_id) {
|
||||
const hw_module_t* hw_mdl = nullptr;
|
||||
|
||||
ALOGD("Opening fingerprint hal library...");
|
||||
if (hw_get_module_by_class(module_id, class_name, &hw_mdl) != 0) {
|
||||
ALOGE("Can't open fingerprint HW Module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!hw_mdl) {
|
||||
ALOGE("No valid fingerprint module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto module = reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
|
||||
if (!module->common.methods->open) {
|
||||
ALOGE("No valid open method");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hw_device_t* device = nullptr;
|
||||
if (module->common.methods->open(hw_mdl, nullptr, &device) != 0) {
|
||||
ALOGE("Can't open fingerprint methods");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto fp_device = reinterpret_cast<fingerprint_device_t*>(device);
|
||||
if (fp_device->set_notify(fp_device, Fingerprint::notify) != 0) {
|
||||
ALOGE("Can't register fingerprint module callback");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fp_device;
|
||||
}
|
||||
|
||||
std::vector<SensorLocation> Fingerprint::getSensorLocations() {
|
||||
std::vector<SensorLocation> locations;
|
||||
|
||||
auto loc = mConfig->get<std::string>("sensor_location");
|
||||
auto entries = ::android::base::Split(loc, ",");
|
||||
|
||||
for (const auto& entry : entries) {
|
||||
auto isValidStr = false;
|
||||
auto dim = ::android::base::Split(entry, "|");
|
||||
|
||||
if (dim.size() != 3 and dim.size() != 4) {
|
||||
if (!loc.empty()) {
|
||||
ALOGE("Invalid sensor location input (x|y|radius) or (x|y|radius|display): %s",
|
||||
loc.c_str());
|
||||
}
|
||||
} else {
|
||||
int32_t x, y, r;
|
||||
std::string d;
|
||||
isValidStr = ParseInt(dim[0], &x) && ParseInt(dim[1], &y) && ParseInt(dim[2], &r);
|
||||
if (dim.size() == 4) {
|
||||
d = dim[3];
|
||||
isValidStr = isValidStr && !d.empty();
|
||||
}
|
||||
if (isValidStr)
|
||||
locations.push_back({.sensorLocationX = x,
|
||||
.sensorLocationY = y,
|
||||
.sensorRadius = r,
|
||||
.display = d});
|
||||
}
|
||||
}
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
void Fingerprint::notify(const fingerprint_msg_t* msg) {
|
||||
Fingerprint* thisPtr = sInstance;
|
||||
if (thisPtr == nullptr || thisPtr->mSession == nullptr || thisPtr->mSession->isClosed()) {
|
||||
ALOGE("Receiving callbacks before a session is opened.");
|
||||
return;
|
||||
}
|
||||
thisPtr->mSession->notify(msg);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
|
||||
std::vector<common::ComponentInfo> componentInfo = {
|
||||
{HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */},
|
||||
{SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
|
||||
"" /* serialNumber */, SW_VERSION}};
|
||||
auto sensorId = mConfig->get<std::int32_t>("sensor_id");
|
||||
auto sensorStrength = mConfig->get<std::int32_t>("sensor_strength");
|
||||
auto navigationGuesture = mConfig->get<bool>("navigation_gesture");
|
||||
auto detectInteraction = mConfig->get<bool>("detect_interaction");
|
||||
auto displayTouch = mConfig->get<bool>("display_touch");
|
||||
auto controlIllumination = mConfig->get<bool>("control_illumination");
|
||||
|
||||
common::CommonProps commonProps = {sensorId, (common::SensorStrength)sensorStrength,
|
||||
MAX_ENROLLMENTS_PER_USER, componentInfo};
|
||||
|
||||
std::vector<SensorLocation> sensorLocations = getSensorLocations();
|
||||
|
||||
std::vector<std::string> sensorLocationStrings;
|
||||
std::transform(sensorLocations.begin(), sensorLocations.end(),
|
||||
std::back_inserter(sensorLocationStrings),
|
||||
[](const SensorLocation& obj) { return obj.toString(); });
|
||||
|
||||
ALOGI("sensor type: %s, location: %s", ::android::internal::ToString(mSensorType).c_str(),
|
||||
::android::base::Join(sensorLocationStrings, ", ").c_str());
|
||||
|
||||
*out = {{commonProps, mSensorType, sensorLocations, navigationGuesture, detectInteraction,
|
||||
displayTouch, controlIllumination, std::nullopt}};
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Fingerprint::createSession(int32_t /*sensorId*/, int32_t userId,
|
||||
const std::shared_ptr<ISessionCallback>& cb,
|
||||
std::shared_ptr<ISession>* out) {
|
||||
CHECK(mSession == nullptr || mSession->isClosed()) << "Open session already exists!";
|
||||
|
||||
mSession = SharedRefBase::make<Session>(mDevice, mUdfpsHandler, userId, cb, mLockoutTracker);
|
||||
*out = mSession;
|
||||
|
||||
mSession->linkToDeath(cb->asBinder().get());
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
49
aidl/fingerprint/Fingerprint.h
Normal file
49
aidl/fingerprint/Fingerprint.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
* 2024 Paranoid Android
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
|
||||
|
||||
#include "FingerprintConfig.h"
|
||||
#include "LockoutTracker.h"
|
||||
#include "Session.h"
|
||||
#include "UdfpsHandler.h"
|
||||
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType;
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::ISession;
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::ISessionCallback;
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::SensorProps;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class Fingerprint : public BnFingerprint {
|
||||
public:
|
||||
Fingerprint(std::shared_ptr<FingerprintConfig> config);
|
||||
~Fingerprint();
|
||||
|
||||
ndk::ScopedAStatus getSensorProps(std::vector<SensorProps>* _aidl_return) override;
|
||||
ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
|
||||
const std::shared_ptr<ISessionCallback>& cb,
|
||||
std::shared_ptr<ISession>* out) override;
|
||||
|
||||
private:
|
||||
fingerprint_device_t* openFingerprintHal(const char* class_name, const char* module_id);
|
||||
std::vector<SensorLocation> getSensorLocations();
|
||||
static void notify(const fingerprint_msg_t* msg);
|
||||
|
||||
std::shared_ptr<FingerprintConfig> mConfig;
|
||||
std::shared_ptr<Session> mSession;
|
||||
LockoutTracker mLockoutTracker;
|
||||
FingerprintSensorType mSensorType;
|
||||
|
||||
fingerprint_device_t* mDevice;
|
||||
UdfpsHandlerFactory* mUdfpsHandlerFactory;
|
||||
UdfpsHandler* mUdfpsHandler;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
56
aidl/fingerprint/FingerprintConfig.cpp
Normal file
56
aidl/fingerprint/FingerprintConfig.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
* 2024 Paranoid Android
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "FingerprintConfig"
|
||||
|
||||
#include "FingerprintConfig.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <fingerprint.sysprop.h>
|
||||
|
||||
using namespace ::android::fingerprint::xiaomi;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
// Wrapper to system property access functions
|
||||
#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_) \
|
||||
ConfigValue _NAME_##Getter() { \
|
||||
return FingerprintHalProperties::_NAME_(); \
|
||||
} \
|
||||
bool _NAME_##Setter(const ConfigValue& v) { \
|
||||
return FingerprintHalProperties::_NAME_(std::get<_T_>(v)); \
|
||||
}
|
||||
|
||||
CREATE_GETTER_SETTER_WRAPPER(type, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(sensor_id, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(sensor_location, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(sensor_strength, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(navigation_gesture, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(detect_interaction, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(display_touch, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(control_illumination, OptBool)
|
||||
|
||||
// Name, Getter, Setter, Parser and default value
|
||||
#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
|
||||
static Config::Data configData[] = {
|
||||
{NGS(type), &Config::parseString, ""},
|
||||
{NGS(sensor_id), &Config::parseInt32, "0"},
|
||||
{NGS(sensor_location), &Config::parseString, ""},
|
||||
{NGS(sensor_strength), &Config::parseInt32, "2"}, // STRONG
|
||||
{NGS(navigation_gesture), &Config::parseBool, "false"},
|
||||
{NGS(detect_interaction), &Config::parseBool, "false"},
|
||||
{NGS(display_touch), &Config::parseBool, "false"},
|
||||
{NGS(control_illumination), &Config::parseBool, "false"},
|
||||
};
|
||||
|
||||
Config::Data* FingerprintConfig::getConfigData(int* size) {
|
||||
*size = sizeof(configData) / sizeof(configData[0]);
|
||||
return configData;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
18
aidl/fingerprint/FingerprintConfig.h
Normal file
18
aidl/fingerprint/FingerprintConfig.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
* 2024 Paranoid Android
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config/Config.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class FingerprintConfig : public Config {
|
||||
Config::Data* getConfigData(int* size) override;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
62
aidl/fingerprint/LockoutTracker.cpp
Normal file
62
aidl/fingerprint/LockoutTracker.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
* 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "LockoutTracker.h"
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include "Fingerprint.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::fingerprint::xiaomi;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
void LockoutTracker::reset(bool clearAttemptCounter) {
|
||||
if (clearAttemptCounter) {
|
||||
mFailedCount = 0;
|
||||
}
|
||||
mLockoutTimedStart = 0;
|
||||
mCurrentMode = LockoutMode::kNone;
|
||||
}
|
||||
|
||||
void LockoutTracker::addFailedAttempt() {
|
||||
mFailedCount++;
|
||||
if (mFailedCount >= LOCKOUT_PERMANENT_THRESHOLD) {
|
||||
mCurrentMode = LockoutMode::kPermanent;
|
||||
} else if (mFailedCount >= LOCKOUT_TIMED_THRESHOLD) {
|
||||
if (mCurrentMode == LockoutMode::kNone) {
|
||||
mCurrentMode = LockoutMode::kTimed;
|
||||
mLockoutTimedStart = Util::getSystemNanoTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LockoutTracker::LockoutMode LockoutTracker::getMode() {
|
||||
if (mCurrentMode == LockoutMode::kTimed) {
|
||||
if (Util::hasElapsed(mLockoutTimedStart, LOCKOUT_TIMED_DURATION)) {
|
||||
mCurrentMode = LockoutMode::kNone;
|
||||
mLockoutTimedStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return mCurrentMode;
|
||||
}
|
||||
|
||||
int64_t LockoutTracker::getLockoutTimeLeft() {
|
||||
int64_t res = 0;
|
||||
|
||||
if (mLockoutTimedStart > 0) {
|
||||
auto now = Util::getSystemNanoTime();
|
||||
auto elapsed = (now - mLockoutTimedStart) / 1000000LL;
|
||||
res = LOCKOUT_TIMED_DURATION - elapsed;
|
||||
LOG(INFO) << "elapsed=" << elapsed << " now = " << now
|
||||
<< " mLockoutTimedStart=" << mLockoutTimedStart << " res=" << res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
46
aidl/fingerprint/LockoutTracker.h
Normal file
46
aidl/fingerprint/LockoutTracker.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
* 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/binder_to_string.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#define LOCKOUT_TIMED_THRESHOLD 5
|
||||
#define LOCKOUT_TIMED_DURATION 10000
|
||||
#define LOCKOUT_PERMANENT_THRESHOLD 20
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class LockoutTracker {
|
||||
public:
|
||||
LockoutTracker() : mFailedCount(0) {}
|
||||
~LockoutTracker() {}
|
||||
|
||||
enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
|
||||
|
||||
void reset(bool clearAttemptCounter);
|
||||
LockoutMode getMode();
|
||||
void addFailedAttempt();
|
||||
int64_t getLockoutTimeLeft();
|
||||
inline std::string toString() const {
|
||||
std::ostringstream os;
|
||||
os << "----- LockoutTracker:: -----" << std::endl;
|
||||
os << "LockoutTracker::mFailedCount:" << mFailedCount;
|
||||
os << ", LockoutTracker::mCurrentMode:" << (int)mCurrentMode;
|
||||
os << std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t mFailedCount;
|
||||
int64_t mLockoutTimedStart;
|
||||
LockoutMode mCurrentMode;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
394
aidl/fingerprint/Session.cpp
Normal file
394
aidl/fingerprint/Session.cpp
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "Legacy2Aidl.h"
|
||||
#include "Session.h"
|
||||
|
||||
#include "CancellationSignal.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
void onClientDeath(void* cookie) {
|
||||
ALOGI("FingerprintService has died");
|
||||
Session* session = static_cast<Session*>(cookie);
|
||||
if (session && !session->isClosed()) {
|
||||
session->close();
|
||||
}
|
||||
}
|
||||
|
||||
Session::Session(fingerprint_device_t* device, UdfpsHandler* udfpsHandler, int userId,
|
||||
std::shared_ptr<ISessionCallback> cb, LockoutTracker lockoutTracker)
|
||||
: mDevice(device),
|
||||
mLockoutTracker(lockoutTracker),
|
||||
mUserId(userId),
|
||||
mCb(cb),
|
||||
mUdfpsHandler(udfpsHandler) {
|
||||
mDeathRecipient = AIBinder_DeathRecipient_new(onClientDeath);
|
||||
|
||||
auto path = std::format("/data/vendor_de/{}/fpdata/", userId);
|
||||
mDevice->set_active_group(mDevice, mUserId, path.c_str());
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::generateChallenge() {
|
||||
uint64_t challenge = mDevice->pre_enroll(mDevice);
|
||||
ALOGI("generateChallenge: %ld", challenge);
|
||||
mCb->onChallengeGenerated(challenge);
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
|
||||
ALOGI("revokeChallenge: %ld", challenge);
|
||||
mDevice->post_enroll(mDevice);
|
||||
mCb->onChallengeRevoked(challenge);
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::enroll(const HardwareAuthToken& hat,
|
||||
std::shared_ptr<ICancellationSignal>* out) {
|
||||
hw_auth_token_t authToken;
|
||||
translate(hat, authToken);
|
||||
int error = mDevice->enroll(mDevice, &authToken, mUserId, 60);
|
||||
if (error) {
|
||||
ALOGE("enroll failed: %d", error);
|
||||
mCb->onError(Error::UNABLE_TO_PROCESS, error);
|
||||
}
|
||||
|
||||
*out = SharedRefBase::make<CancellationSignal>(this);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::authenticate(int64_t operationId,
|
||||
std::shared_ptr<ICancellationSignal>* out) {
|
||||
checkSensorLockout();
|
||||
int error = mDevice->authenticate(mDevice, operationId, mUserId);
|
||||
if (error) {
|
||||
ALOGE("authenticate failed: %d", error);
|
||||
mCb->onError(Error::UNABLE_TO_PROCESS, error);
|
||||
}
|
||||
|
||||
*out = SharedRefBase::make<CancellationSignal>(this);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<ICancellationSignal>* out) {
|
||||
ALOGD("Detect interaction is not supported");
|
||||
mCb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
|
||||
*out = SharedRefBase::make<CancellationSignal>(this);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::enumerateEnrollments() {
|
||||
int error = mDevice->enumerate(mDevice);
|
||||
if (error) {
|
||||
ALOGE("enumerate failed: %d", error);
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
|
||||
ALOGI("removeEnrollments, size: %zu", enrollmentIds.size());
|
||||
|
||||
for (int32_t fid : enrollmentIds) {
|
||||
int error = mDevice->remove(mDevice, mUserId, fid);
|
||||
if (error) {
|
||||
ALOGE("remove failed: %d", error);
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::getAuthenticatorId() {
|
||||
uint64_t auth_id = mDevice->get_authenticator_id(mDevice);
|
||||
ALOGI("getAuthenticatorId: %ld", auth_id);
|
||||
mCb->onAuthenticatorIdRetrieved(auth_id);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
|
||||
uint64_t auth_id = mDevice->get_authenticator_id(mDevice);
|
||||
ALOGI("invalidateAuthenticatorId: %ld", auth_id);
|
||||
mCb->onAuthenticatorIdInvalidated(auth_id);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::resetLockout(const HardwareAuthToken& /*hat*/) {
|
||||
clearLockout(true);
|
||||
if (mIsLockoutTimerStarted) mIsLockoutTimerAborted = true;
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onPointerDown(int32_t /*pointerId*/, int32_t x, int32_t y, float minor,
|
||||
float major) {
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->onFingerDown(x, y, minor, major);
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onPointerUp(int32_t /*pointerId*/) {
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->onFingerUp();
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onUiReady() {
|
||||
// TODO: stub
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::authenticateWithContext(
|
||||
int64_t operationId, const common::OperationContext& /*context*/,
|
||||
std::shared_ptr<common::ICancellationSignal>* out) {
|
||||
return authenticate(operationId, out);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::enrollWithContext(const keymaster::HardwareAuthToken& hat,
|
||||
const common::OperationContext& /*context*/,
|
||||
std::shared_ptr<common::ICancellationSignal>* out) {
|
||||
return enroll(hat, out);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::detectInteractionWithContext(
|
||||
const common::OperationContext& /*context*/,
|
||||
std::shared_ptr<common::ICancellationSignal>* out) {
|
||||
return detectInteraction(out);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onPointerDownWithContext(const PointerContext& context) {
|
||||
return onPointerDown(context.pointerId, context.x, context.y, context.minor, context.major);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onPointerUpWithContext(const PointerContext& context) {
|
||||
return onPointerUp(context.pointerId);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onContextChanged(const common::OperationContext& /*context*/) {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::onPointerCancelWithContext(const PointerContext& /*context*/) {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::setIgnoreDisplayTouches(bool /*shouldIgnore*/) {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::cancel() {
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->cancel();
|
||||
}
|
||||
|
||||
int ret = mDevice->cancel(mDevice);
|
||||
|
||||
if (ret == 0) {
|
||||
mCb->onError(Error::CANCELED, 0 /* vendorCode */);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::fromServiceSpecificError(ret);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Session::close() {
|
||||
mClosed = true;
|
||||
mCb->onSessionClosed();
|
||||
AIBinder_DeathRecipient_delete(mDeathRecipient);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
binder_status_t Session::linkToDeath(AIBinder* binder) {
|
||||
return AIBinder_linkToDeath(binder, mDeathRecipient, this);
|
||||
}
|
||||
|
||||
bool Session::isClosed() {
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
// Translate from errors returned by traditional HAL (see fingerprint.h) to
|
||||
// AIDL-compliant Error
|
||||
Error Session::VendorErrorFilter(int32_t error, int32_t* vendorCode) {
|
||||
*vendorCode = 0;
|
||||
|
||||
switch (error) {
|
||||
case FINGERPRINT_ERROR_HW_UNAVAILABLE:
|
||||
return Error::HW_UNAVAILABLE;
|
||||
case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
|
||||
return Error::UNABLE_TO_PROCESS;
|
||||
case FINGERPRINT_ERROR_TIMEOUT:
|
||||
return Error::TIMEOUT;
|
||||
case FINGERPRINT_ERROR_NO_SPACE:
|
||||
return Error::NO_SPACE;
|
||||
case FINGERPRINT_ERROR_CANCELED:
|
||||
return Error::CANCELED;
|
||||
case FINGERPRINT_ERROR_UNABLE_TO_REMOVE:
|
||||
return Error::UNABLE_TO_REMOVE;
|
||||
case FINGERPRINT_ERROR_LOCKOUT: {
|
||||
*vendorCode = FINGERPRINT_ERROR_LOCKOUT;
|
||||
return Error::VENDOR;
|
||||
}
|
||||
default:
|
||||
if (error >= FINGERPRINT_ERROR_VENDOR_BASE) {
|
||||
// vendor specific code.
|
||||
*vendorCode = error - FINGERPRINT_ERROR_VENDOR_BASE;
|
||||
return Error::VENDOR;
|
||||
}
|
||||
}
|
||||
ALOGE("Unknown error from fingerprint vendor library: %d", error);
|
||||
return Error::UNABLE_TO_PROCESS;
|
||||
}
|
||||
|
||||
// Translate acquired messages returned by traditional HAL (see fingerprint.h)
|
||||
// to AIDL-compliant AcquiredInfo
|
||||
AcquiredInfo Session::VendorAcquiredFilter(int32_t info, int32_t* vendorCode) {
|
||||
*vendorCode = 0;
|
||||
|
||||
switch (info) {
|
||||
case FINGERPRINT_ACQUIRED_GOOD:
|
||||
return AcquiredInfo::GOOD;
|
||||
case FINGERPRINT_ACQUIRED_PARTIAL:
|
||||
return AcquiredInfo::PARTIAL;
|
||||
case FINGERPRINT_ACQUIRED_INSUFFICIENT:
|
||||
return AcquiredInfo::INSUFFICIENT;
|
||||
case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
|
||||
return AcquiredInfo::SENSOR_DIRTY;
|
||||
case FINGERPRINT_ACQUIRED_TOO_SLOW:
|
||||
return AcquiredInfo::TOO_SLOW;
|
||||
case FINGERPRINT_ACQUIRED_TOO_FAST:
|
||||
return AcquiredInfo::TOO_FAST;
|
||||
default:
|
||||
if (info >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
|
||||
// vendor specific code.
|
||||
*vendorCode = info - FINGERPRINT_ACQUIRED_VENDOR_BASE;
|
||||
return AcquiredInfo::VENDOR;
|
||||
}
|
||||
}
|
||||
ALOGE("Unknown acquired message from fingerprint vendor library: %d", info);
|
||||
return AcquiredInfo::UNKNOWN;
|
||||
}
|
||||
|
||||
bool Session::checkSensorLockout() {
|
||||
LockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
|
||||
if (lockoutMode == LockoutTracker::LockoutMode::kPermanent) {
|
||||
ALOGE("Fail: lockout permanent");
|
||||
mCb->onLockoutPermanent();
|
||||
mIsLockoutTimerAborted = true;
|
||||
return true;
|
||||
}
|
||||
if (lockoutMode == LockoutTracker::LockoutMode::kTimed) {
|
||||
int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
|
||||
ALOGE("Fail: lockout timed: %ld", timeLeft);
|
||||
mCb->onLockoutTimed(timeLeft);
|
||||
if (!mIsLockoutTimerStarted) startLockoutTimer(timeLeft);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Session::clearLockout(bool clearAttemptCounter) {
|
||||
mLockoutTracker.reset(clearAttemptCounter);
|
||||
mCb->onLockoutCleared();
|
||||
}
|
||||
|
||||
void Session::startLockoutTimer(int64_t timeout) {
|
||||
std::function<void()> action = std::bind(&Session::lockoutTimerExpired, this);
|
||||
std::thread([timeout, action]() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
|
||||
action();
|
||||
}).detach();
|
||||
|
||||
mIsLockoutTimerStarted = true;
|
||||
}
|
||||
|
||||
void Session::lockoutTimerExpired() {
|
||||
if (!mIsLockoutTimerAborted) clearLockout(false);
|
||||
|
||||
mIsLockoutTimerStarted = false;
|
||||
mIsLockoutTimerAborted = false;
|
||||
}
|
||||
|
||||
void Session::notify(const fingerprint_msg_t* msg) {
|
||||
// const uint64_t devId = reinterpret_cast<uint64_t>(mDevice);
|
||||
switch (msg->type) {
|
||||
case FINGERPRINT_ERROR: {
|
||||
int32_t vendorCode = 0;
|
||||
Error result = VendorErrorFilter(msg->data.error, &vendorCode);
|
||||
ALOGD("onError(%hhd, %d)", result, vendorCode);
|
||||
mCb->onError(result, vendorCode);
|
||||
} break;
|
||||
case FINGERPRINT_ACQUIRED: {
|
||||
int32_t vendorCode = 0;
|
||||
AcquiredInfo result =
|
||||
VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
|
||||
ALOGD("onAcquired(%hhd, %d)", result, vendorCode);
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->onAcquired(static_cast<int32_t>(result), vendorCode);
|
||||
}
|
||||
// don't process vendor messages further since frameworks try to disable
|
||||
// udfps display mode on vendor acquired messages but our sensors send a
|
||||
// vendor message during processing...
|
||||
if (result != AcquiredInfo::VENDOR) {
|
||||
mCb->onAcquired(result, vendorCode);
|
||||
}
|
||||
} break;
|
||||
case FINGERPRINT_TEMPLATE_ENROLLING: {
|
||||
ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)", msg->data.enroll.finger.fid,
|
||||
msg->data.enroll.finger.gid, msg->data.enroll.samples_remaining);
|
||||
mCb->onEnrollmentProgress(msg->data.enroll.finger.fid,
|
||||
msg->data.enroll.samples_remaining);
|
||||
} break;
|
||||
case FINGERPRINT_TEMPLATE_REMOVED: {
|
||||
ALOGD("onRemove(fid=%d, gid=%d, rem=%d)", msg->data.removed.finger.fid,
|
||||
msg->data.removed.finger.gid, msg->data.removed.remaining_templates);
|
||||
std::vector<int> enrollments;
|
||||
enrollments.push_back(msg->data.removed.finger.fid);
|
||||
mCb->onEnrollmentsRemoved(enrollments);
|
||||
} break;
|
||||
case FINGERPRINT_AUTHENTICATED: {
|
||||
ALOGD("onAuthenticated(fid=%d, gid=%d)", msg->data.authenticated.finger.fid,
|
||||
msg->data.authenticated.finger.gid);
|
||||
if (msg->data.authenticated.finger.fid != 0) {
|
||||
const hw_auth_token_t hat = msg->data.authenticated.hat;
|
||||
HardwareAuthToken authToken;
|
||||
translate(hat, authToken);
|
||||
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->onAuthenticationSucceeded();
|
||||
}
|
||||
mCb->onAuthenticationSucceeded(msg->data.authenticated.finger.fid, authToken);
|
||||
mLockoutTracker.reset(true);
|
||||
} else {
|
||||
if (mUdfpsHandler) {
|
||||
mUdfpsHandler->onAuthenticationFailed();
|
||||
}
|
||||
mCb->onAuthenticationFailed();
|
||||
mLockoutTracker.addFailedAttempt();
|
||||
checkSensorLockout();
|
||||
}
|
||||
} break;
|
||||
case FINGERPRINT_TEMPLATE_ENUMERATING: {
|
||||
ALOGD("onEnumerate(fid=%d, gid=%d, rem=%d)", msg->data.enumerated.finger.fid,
|
||||
msg->data.enumerated.finger.gid, msg->data.enumerated.remaining_templates);
|
||||
static std::vector<int> enrollments;
|
||||
enrollments.push_back(msg->data.enumerated.finger.fid);
|
||||
if (msg->data.enumerated.remaining_templates == 0) {
|
||||
mCb->onEnrollmentsEnumerated(enrollments);
|
||||
enrollments.clear();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
100
aidl/fingerprint/Session.h
Normal file
100
aidl/fingerprint/Session.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define LOG_TAG "android.hardware.biometrics.fingerprint-service.xiaomi"
|
||||
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnSession.h>
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
|
||||
#include <android/log.h>
|
||||
#include <hardware/hardware.h>
|
||||
#include <log/log.h>
|
||||
#include "fingerprint.h"
|
||||
|
||||
#include "LockoutTracker.h"
|
||||
#include "UdfpsHandler.h"
|
||||
|
||||
using ::aidl::android::hardware::biometrics::common::ICancellationSignal;
|
||||
using ::aidl::android::hardware::biometrics::common::OperationContext;
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::PointerContext;
|
||||
using ::aidl::android::hardware::keymaster::HardwareAuthToken;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
void onClientDeath(void* cookie);
|
||||
|
||||
class Session : public BnSession {
|
||||
public:
|
||||
Session(fingerprint_device_t* device, UdfpsHandler* udfpsHandler, int userId,
|
||||
std::shared_ptr<ISessionCallback> cb, LockoutTracker lockoutTracker);
|
||||
ndk::ScopedAStatus generateChallenge() override;
|
||||
ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
|
||||
ndk::ScopedAStatus enroll(const HardwareAuthToken& hat,
|
||||
std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus authenticate(int64_t operationId,
|
||||
std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus detectInteraction(std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus enumerateEnrollments() override;
|
||||
ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
|
||||
ndk::ScopedAStatus getAuthenticatorId() override;
|
||||
ndk::ScopedAStatus invalidateAuthenticatorId() override;
|
||||
ndk::ScopedAStatus resetLockout(const HardwareAuthToken& hat) override;
|
||||
ndk::ScopedAStatus close() override;
|
||||
ndk::ScopedAStatus onPointerDown(int32_t pointerId, int32_t x, int32_t y, float minor,
|
||||
float major) override;
|
||||
ndk::ScopedAStatus onPointerUp(int32_t pointerId) override;
|
||||
ndk::ScopedAStatus onUiReady() override;
|
||||
ndk::ScopedAStatus authenticateWithContext(int64_t operationId, const OperationContext& context,
|
||||
std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus enrollWithContext(const HardwareAuthToken& hat,
|
||||
const OperationContext& context,
|
||||
std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus detectInteractionWithContext(
|
||||
const OperationContext& context, std::shared_ptr<ICancellationSignal>* out) override;
|
||||
ndk::ScopedAStatus onPointerDownWithContext(const PointerContext& context) override;
|
||||
ndk::ScopedAStatus onPointerUpWithContext(const PointerContext& context) override;
|
||||
ndk::ScopedAStatus onContextChanged(const OperationContext& context) override;
|
||||
ndk::ScopedAStatus onPointerCancelWithContext(const PointerContext& context) override;
|
||||
ndk::ScopedAStatus setIgnoreDisplayTouches(bool shouldIgnore) override;
|
||||
|
||||
ndk::ScopedAStatus cancel();
|
||||
binder_status_t linkToDeath(AIBinder* binder);
|
||||
bool isClosed();
|
||||
void notify(const fingerprint_msg_t* msg);
|
||||
|
||||
private:
|
||||
fingerprint_device_t* mDevice;
|
||||
LockoutTracker mLockoutTracker;
|
||||
bool mClosed = false;
|
||||
|
||||
// static ndk::ScopedAStatus ErrorFilter(int32_t error);
|
||||
static Error VendorErrorFilter(int32_t error, int32_t* vendorCode);
|
||||
static AcquiredInfo VendorAcquiredFilter(int32_t info, int32_t* vendorCode);
|
||||
|
||||
bool checkSensorLockout();
|
||||
void clearLockout(bool clearAttemptCounter);
|
||||
void startLockoutTimer(int64_t timeout);
|
||||
void lockoutTimerExpired();
|
||||
|
||||
// lockout timer
|
||||
bool mIsLockoutTimerStarted = false;
|
||||
bool mIsLockoutTimerAborted = false;
|
||||
|
||||
// The user ID for which this session was created.
|
||||
int32_t mUserId;
|
||||
|
||||
// Callback for talking to the framework. This callback must only be called from non-binder
|
||||
// threads to prevent nested binder calls and consequently a binder thread exhaustion.
|
||||
// Practically, it means that this callback should always be called from the worker thread.
|
||||
std::shared_ptr<ISessionCallback> mCb;
|
||||
|
||||
// Binder death handler.
|
||||
AIBinder_DeathRecipient* mDeathRecipient;
|
||||
|
||||
UdfpsHandler* mUdfpsHandler;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
@@ -0,0 +1,9 @@
|
||||
service vendor.fingerprint-default /vendor/bin/hw/android.hardware.biometrics.fingerprint-service.xiaomi
|
||||
# "class hal" causes a race condition on some devices due to files created
|
||||
# in /data. As a workaround, postpone startup until later in boot once
|
||||
# /data is mounted.
|
||||
class late_start
|
||||
user system
|
||||
group system input uhid
|
||||
capabilities SYS_NICE
|
||||
shutdown critical
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.biometrics.fingerprint</name>
|
||||
<version>4</version>
|
||||
<fqname>IFingerprint/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
79
aidl/fingerprint/fingerprint.sysprop
Normal file
79
aidl/fingerprint/fingerprint.sysprop
Normal file
@@ -0,0 +1,79 @@
|
||||
# fingerprint.sysprop
|
||||
# module becomes static class (Java) / namespace (C++) for serving API
|
||||
module: "android.fingerprint.xiaomi.FingerprintHalProperties"
|
||||
owner: Vendor
|
||||
|
||||
# type of fingerprint sensor (default: none)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.type"
|
||||
type: String
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
enum_values: "udfps|udfps_optical|side|home|rear"
|
||||
api_name: "type"
|
||||
}
|
||||
|
||||
# sensor location
|
||||
# <x>|<y>|<radius>|<display> in pixel, can have multiple values separated by comma
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.sensor_location"
|
||||
type: String
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_location"
|
||||
}
|
||||
|
||||
# sensor id (default: 0)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.sensor_id"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_id"
|
||||
}
|
||||
|
||||
# sensor strength (default: 2)
|
||||
# [0=CONVENIENCE, 1=WEAK, 2=STRONG]
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.sensor_strength"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_strength"
|
||||
}
|
||||
|
||||
# whether support navigation guestures (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.navigation_gesture"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "navigation_gesture"
|
||||
}
|
||||
|
||||
# whether support detect interaction (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.detect_interaction"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "detect_interaction"
|
||||
}
|
||||
|
||||
# whether support display touch by hal (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.udfps.display_touch"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "display_touch"
|
||||
}
|
||||
|
||||
# whether support illumination control by hal (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.udfps.control_illumination"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "control_illumination"
|
||||
}
|
||||
41
aidl/fingerprint/include/Legacy2Aidl.h
Normal file
41
aidl/fingerprint/include/Legacy2Aidl.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
|
||||
|
||||
#include <hardware/hw_auth_token.h>
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
inline void translate(const ::aidl::android::hardware::keymaster::HardwareAuthToken& authToken,
|
||||
hw_auth_token_t& hat) {
|
||||
hat.challenge = authToken.challenge;
|
||||
hat.user_id = authToken.userId;
|
||||
hat.authenticator_id = authToken.authenticatorId;
|
||||
// these are in host order: translate to network order
|
||||
hat.authenticator_type = htobe32(static_cast<uint32_t>(authToken.authenticatorType));
|
||||
hat.timestamp = htobe64(authToken.timestamp.milliSeconds);
|
||||
std::copy(authToken.mac.begin(), authToken.mac.end(), hat.hmac);
|
||||
}
|
||||
|
||||
inline void translate(const hw_auth_token_t& hat,
|
||||
::aidl::android::hardware::keymaster::HardwareAuthToken& authToken) {
|
||||
authToken.challenge = hat.challenge;
|
||||
authToken.userId = hat.user_id;
|
||||
authToken.authenticatorId = hat.authenticator_id;
|
||||
// these are in network order: translate to host
|
||||
authToken.authenticatorType =
|
||||
static_cast<::aidl::android::hardware::keymaster::HardwareAuthenticatorType>(
|
||||
be32toh(hat.authenticator_type));
|
||||
authToken.timestamp.milliSeconds = be64toh(hat.timestamp);
|
||||
authToken.mac.insert(authToken.mac.begin(), std::begin(hat.hmac), std::end(hat.hmac));
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
32
aidl/fingerprint/service.cpp
Normal file
32
aidl/fingerprint/service.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Fingerprint.h"
|
||||
#include "FingerprintConfig.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::Fingerprint;
|
||||
using ::aidl::android::hardware::biometrics::fingerprint::FingerprintConfig;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
|
||||
std::shared_ptr<FingerprintConfig> config = std::make_shared<FingerprintConfig>();
|
||||
config->init();
|
||||
|
||||
std::shared_ptr<Fingerprint> fingerprint = ndk::SharedRefBase::make<Fingerprint>(config);
|
||||
|
||||
const std::string instance = std::string() + Fingerprint::descriptor + "/default";
|
||||
binder_status_t status =
|
||||
AServiceManager_addService(fingerprint->asBinder().get(), instance.c_str());
|
||||
CHECK(status == STATUS_OK);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
<!--
|
||||
Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
-->
|
||||
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.health</name>
|
||||
<version>1</version>
|
||||
<version>3</version>
|
||||
<fqname>IHealth/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2024 The LineageOS Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.ir-service.xiaomi",
|
||||
relative_install_path: "hw",
|
||||
vendor: true,
|
||||
init_rc: ["android.hardware.ir-service.xiaomi.rc"],
|
||||
vintf_fragments: ["android.hardware.ir-service.xiaomi.xml"],
|
||||
srcs: [
|
||||
"ConsumerIr.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"android.hardware.ir-V1-ndk",
|
||||
],
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2024 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "ConsumerIr"
|
||||
|
||||
#include "ConsumerIr.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/lirc.h>
|
||||
#include <string>
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace ir {
|
||||
|
||||
static const std::string kIrDevice = "/dev/lirc0";
|
||||
|
||||
static vector<ConsumerIrFreqRange> kRangeVec{
|
||||
{.minHz = 30000, .maxHz = 60000},
|
||||
};
|
||||
|
||||
::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(vector<ConsumerIrFreqRange>* _aidl_return) {
|
||||
*_aidl_return = kRangeVec;
|
||||
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus ConsumerIr::transmit(int32_t carrierFreqHz, const vector<int32_t>& pattern) {
|
||||
size_t entries = pattern.size();
|
||||
|
||||
if (entries == 0) {
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
int fd = open(kIrDevice.c_str(), O_RDWR);
|
||||
if (fd < 0) {
|
||||
LOG(ERROR) << "Failed to open " << kIrDevice << ", error " << fd;
|
||||
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
int rc = ioctl(fd, LIRC_SET_SEND_CARRIER, &carrierFreqHz);
|
||||
if (rc < 0) {
|
||||
LOG(ERROR) << "Failed to set carrier " << carrierFreqHz << ", error: " << errno;
|
||||
|
||||
close(fd);
|
||||
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
if ((entries & 1) != 0) {
|
||||
rc = write(fd, pattern.data(), entries * sizeof(int32_t));
|
||||
} else {
|
||||
rc = write(fd, pattern.data(), (entries - 1) * sizeof(int32_t));
|
||||
usleep(pattern[entries - 1]);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
LOG(ERROR) << "Failed to write pattern, " << entries << " entries, error: " << errno;
|
||||
|
||||
close(fd);
|
||||
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 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:
|
||||
::ndk::ScopedAStatus getCarrierFreqs(
|
||||
::std::vector<::aidl::android::hardware::ir::ConsumerIrFreqRange>* _aidl_return)
|
||||
override;
|
||||
::ndk::ScopedAStatus transmit(int32_t carrierFreqHz,
|
||||
const ::std::vector<int32_t>& pattern) override;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2024 The LineageOS Project
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
on early-boot
|
||||
# IR device
|
||||
chown system system /dev/lirc0
|
||||
|
||||
service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.xiaomi
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
shutdown critical
|
||||
@@ -1,11 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2024 The LineageOS Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.ir</name>
|
||||
<version>1</version>
|
||||
<fqname>IConsumerIr/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 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> hal = ::ndk::SharedRefBase::make<ConsumerIr>();
|
||||
|
||||
const std::string instance = std::string(ConsumerIr::descriptor) + "/default";
|
||||
binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2021-2024 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.light-service.xiaomi",
|
||||
defaults: ["hidl_defaults"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["android.hardware.light-service.xiaomi.rc"],
|
||||
vintf_fragments: ["android.hardware.light-service.xiaomi.xml"],
|
||||
srcs: [
|
||||
"BacklightDevice.cpp",
|
||||
"Devices.cpp",
|
||||
"LedDevice.cpp",
|
||||
"Lights.cpp",
|
||||
"RgbLedDevice.cpp",
|
||||
"Utils.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"android.hardware.light-V2-ndk",
|
||||
],
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "BacklightDevice.h"
|
||||
|
||||
#define LOG_TAG "BacklightDevice"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fstream>
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
static const std::string kBacklightBasePath = "/sys/class/backlight/";
|
||||
static const uint32_t kDefaultMaxBrightness = 255;
|
||||
|
||||
static const std::string kBrightnessNode = "brightness";
|
||||
static const std::string kMaxBrightnessNode = "max_brightness";
|
||||
|
||||
BacklightDevice::BacklightDevice(std::string name)
|
||||
: mName(name), mBasePath(kBacklightBasePath + name + "/") {
|
||||
if (!readFromFile(mBasePath + kMaxBrightnessNode, mMaxBrightness)) {
|
||||
mMaxBrightness = kDefaultMaxBrightness;
|
||||
}
|
||||
};
|
||||
|
||||
std::string BacklightDevice::getName() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
bool BacklightDevice::exists() const {
|
||||
return std::ifstream(mBasePath + kBrightnessNode).good();
|
||||
}
|
||||
|
||||
bool BacklightDevice::setBrightness(uint8_t value) {
|
||||
return writeToFile(mBasePath + kBrightnessNode, scaleBrightness(value, mMaxBrightness));
|
||||
}
|
||||
|
||||
void BacklightDevice::dump(int fd) const {
|
||||
dprintf(fd, "Name: %s", mName.c_str());
|
||||
dprintf(fd, ", exists: %d", exists());
|
||||
dprintf(fd, ", base path: %s", mBasePath.c_str());
|
||||
dprintf(fd, ", max brightness: %u", mMaxBrightness);
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "IDumpable.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
/**
|
||||
* A Linux backlight device.
|
||||
* @see https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
|
||||
*/
|
||||
class BacklightDevice : public IDumpable {
|
||||
public:
|
||||
BacklightDevice() = delete;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name The name of the backlight device
|
||||
*/
|
||||
BacklightDevice(std::string name);
|
||||
|
||||
/**
|
||||
* Get the name of the backlight device.
|
||||
*
|
||||
* @return std::string The name of the backlight device
|
||||
*/
|
||||
std::string getName() const;
|
||||
|
||||
/**
|
||||
* Return whether this backlight device exists.
|
||||
*
|
||||
* @return bool true if the backlight device exists, false otherwise
|
||||
*/
|
||||
bool exists() const;
|
||||
|
||||
/**
|
||||
* Set the brightness of this backlight device.
|
||||
*
|
||||
* @param value The brightness value to set
|
||||
* @return bool true if the brightness was set successfully, false otherwise
|
||||
*/
|
||||
bool setBrightness(uint8_t value);
|
||||
|
||||
void dump(int fd) const override;
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
std::string mBasePath;
|
||||
uint32_t mMaxBrightness;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Devices.h"
|
||||
|
||||
#define LOG_TAG "Devices"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
static const std::string kBacklightDevices[] = {
|
||||
"backlight",
|
||||
"panel0-backlight",
|
||||
};
|
||||
|
||||
static std::vector<BacklightDevice> getBacklightDevices() {
|
||||
std::vector<BacklightDevice> devices;
|
||||
|
||||
for (const auto& device : kBacklightDevices) {
|
||||
BacklightDevice backlight(device);
|
||||
if (backlight.exists()) {
|
||||
LOG(INFO) << "Found backlight device: " << backlight.getName();
|
||||
devices.push_back(backlight);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
static const std::string kLedBacklightDevices[] = {
|
||||
"lcd-backlight",
|
||||
};
|
||||
|
||||
static std::vector<LedDevice> getBacklightLedDevices() {
|
||||
std::vector<LedDevice> devices;
|
||||
|
||||
for (const auto& device : kLedBacklightDevices) {
|
||||
LedDevice backlight(device);
|
||||
if (backlight.exists()) {
|
||||
LOG(INFO) << "Found backlight LED device: " << backlight.getName();
|
||||
devices.push_back(backlight);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
static const std::string kButtonLedDevices[] = {
|
||||
"button-backlight",
|
||||
"button-backlight1",
|
||||
"button-backlight2",
|
||||
};
|
||||
|
||||
static std::vector<LedDevice> getButtonLedDevices() {
|
||||
std::vector<LedDevice> devices;
|
||||
|
||||
for (const auto& device : kButtonLedDevices) {
|
||||
LedDevice button(device);
|
||||
if (button.exists()) {
|
||||
LOG(INFO) << "Found button LED device: " << button.getName();
|
||||
devices.emplace_back(button);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
static const std::string kRgbLedDevices[][4] = {
|
||||
{"red", "green", "blue", "/sys/class/leds/rgb/rgb_blink"},
|
||||
};
|
||||
|
||||
static std::vector<RgbLedDevice> getNotificationRgbLedDevices() {
|
||||
std::vector<RgbLedDevice> devices;
|
||||
|
||||
for (const auto& device : kRgbLedDevices) {
|
||||
LedDevice red(device[0]);
|
||||
LedDevice green(device[1]);
|
||||
LedDevice blue(device[2]);
|
||||
|
||||
RgbLedDevice rgbLedDevice(red, green, blue, device[3]);
|
||||
if (rgbLedDevice.exists()) {
|
||||
LOG(INFO) << "Found notification RGB LED device: " << red.getName() << ", "
|
||||
<< green.getName() << ", " << blue.getName();
|
||||
devices.emplace_back(red, green, blue, device[3]);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
static const std::string kNotificationLedDevices[] = {
|
||||
"left",
|
||||
"white",
|
||||
};
|
||||
|
||||
static std::vector<LedDevice> getNotificationLedDevices() {
|
||||
std::vector<LedDevice> devices;
|
||||
|
||||
for (const auto& device : kNotificationLedDevices) {
|
||||
LedDevice notification(device);
|
||||
if (notification.exists()) {
|
||||
LOG(INFO) << "Found notification LED device: " << notification.getName();
|
||||
devices.emplace_back(notification);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
Devices::Devices()
|
||||
: mBacklightDevices(getBacklightDevices()),
|
||||
mBacklightLedDevices(getBacklightLedDevices()),
|
||||
mButtonLedDevices(getButtonLedDevices()),
|
||||
mNotificationRgbLedDevices(getNotificationRgbLedDevices()),
|
||||
mNotificationLedDevices(getNotificationLedDevices()) {
|
||||
if (!hasBacklightDevices()) {
|
||||
LOG(INFO) << "No backlight devices found";
|
||||
}
|
||||
|
||||
if (!hasButtonDevices()) {
|
||||
LOG(INFO) << "No button devices found";
|
||||
}
|
||||
|
||||
if (!hasNotificationDevices()) {
|
||||
LOG(INFO) << "No notification devices found";
|
||||
}
|
||||
}
|
||||
|
||||
bool Devices::hasBacklightDevices() const {
|
||||
return !mBacklightDevices.empty() || !mBacklightLedDevices.empty();
|
||||
}
|
||||
|
||||
bool Devices::hasButtonDevices() const {
|
||||
return !mButtonLedDevices.empty();
|
||||
}
|
||||
|
||||
bool Devices::hasNotificationDevices() const {
|
||||
return !mNotificationRgbLedDevices.empty() || !mNotificationLedDevices.empty();
|
||||
}
|
||||
|
||||
void Devices::setBacklightColor(rgb color) {
|
||||
for (auto& device : mBacklightDevices) {
|
||||
device.setBrightness(color.toBrightness());
|
||||
}
|
||||
for (auto& device : mBacklightLedDevices) {
|
||||
device.setBrightness(color.toBrightness());
|
||||
}
|
||||
}
|
||||
|
||||
void Devices::setButtonsColor(rgb color) {
|
||||
for (auto& device : mButtonLedDevices) {
|
||||
device.setBrightness(color.toBrightness());
|
||||
}
|
||||
}
|
||||
|
||||
void Devices::setNotificationColor(rgb color, LightMode mode, uint32_t flashOnMs,
|
||||
uint32_t flashOffMs) {
|
||||
for (auto& device : mNotificationRgbLedDevices) {
|
||||
device.setBrightness(color, mode, flashOnMs, flashOffMs);
|
||||
}
|
||||
|
||||
for (auto& device : mNotificationLedDevices) {
|
||||
device.setBrightness(color.toBrightness(), mode, flashOnMs, flashOffMs);
|
||||
}
|
||||
}
|
||||
|
||||
void Devices::dump(int fd) const {
|
||||
dprintf(fd, "Backlight devices:\n");
|
||||
for (const auto& device : mBacklightDevices) {
|
||||
dprintf(fd, "- ");
|
||||
device.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Backlight LED devices:\n");
|
||||
for (const auto& device : mBacklightLedDevices) {
|
||||
dprintf(fd, "- ");
|
||||
device.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Button LED devices:\n");
|
||||
for (const auto& device : mButtonLedDevices) {
|
||||
dprintf(fd, "- ");
|
||||
device.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Notification RGB LED devices:\n");
|
||||
for (const auto& device : mNotificationRgbLedDevices) {
|
||||
dprintf(fd, "- ");
|
||||
device.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Notification LED devices:\n");
|
||||
for (const auto& device : mNotificationLedDevices) {
|
||||
dprintf(fd, "- ");
|
||||
device.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "BacklightDevice.h"
|
||||
#include "IDumpable.h"
|
||||
#include "LedDevice.h"
|
||||
#include "RgbLedDevice.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
class Devices : public IDumpable {
|
||||
public:
|
||||
Devices();
|
||||
|
||||
bool hasBacklightDevices() const;
|
||||
bool hasButtonDevices() const;
|
||||
bool hasNotificationDevices() const;
|
||||
|
||||
void setBacklightColor(rgb color);
|
||||
void setButtonsColor(rgb color);
|
||||
void setNotificationColor(rgb color, LightMode mode = LightMode::STATIC, uint32_t flashOnMs = 0,
|
||||
uint32_t flashOffMs = 0);
|
||||
|
||||
void dump(int fd) const override;
|
||||
|
||||
private:
|
||||
// Backlight
|
||||
std::vector<BacklightDevice> mBacklightDevices;
|
||||
std::vector<LedDevice> mBacklightLedDevices;
|
||||
|
||||
// Buttons
|
||||
std::vector<LedDevice> mButtonLedDevices;
|
||||
|
||||
// Notifications
|
||||
std::vector<RgbLedDevice> mNotificationRgbLedDevices;
|
||||
std::vector<LedDevice> mNotificationLedDevices;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
/**
|
||||
* Interface for dumpable objects using AIDL dump()'s file descriptor.
|
||||
*/
|
||||
class IDumpable {
|
||||
public:
|
||||
virtual ~IDumpable() = default;
|
||||
|
||||
/**
|
||||
* Write information regarding this object to the given file descriptor using dprintf().
|
||||
* You should avoid ending newline, since the caller will add it.
|
||||
* @param fd The file descriptor to write to.
|
||||
*/
|
||||
virtual void dump(int fd) const = 0;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "LedDevice.h"
|
||||
|
||||
#define LOG_TAG "LedDevice"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fstream>
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
static const uint32_t kDefaultMaxBrightness = 255;
|
||||
|
||||
static const std::string kBaseLedsPath = "/sys/class/leds/";
|
||||
|
||||
static const std::string kBrightnessNode = "brightness";
|
||||
static const std::string kMaxBrightnessNode = "max_brightness";
|
||||
|
||||
static const std::string kBreathNodes[] = {
|
||||
"breath",
|
||||
"blink",
|
||||
};
|
||||
|
||||
static const std::string kBlinkNode = "blink";
|
||||
static const std::string kStartIdxNode = "start_idx";
|
||||
static const std::string kDutyPctsNode = "duty_pcts";
|
||||
static const std::string kPauseLoNode = "pause_lo";
|
||||
static const std::string kPauseHiNode = "pause_hi";
|
||||
static const std::string kRampStepMsNode = "ramp_step_ms";
|
||||
|
||||
static constexpr int kRampSteps = 8;
|
||||
static constexpr int kRampMaxStepDurationMs = 50;
|
||||
|
||||
LedDevice::LedDevice(std::string name)
|
||||
: mName(name), mIdx(0), mBasePath(kBaseLedsPath + name + "/") {
|
||||
if (!readFromFile(mBasePath + kMaxBrightnessNode, mMaxBrightness)) {
|
||||
mMaxBrightness = kDefaultMaxBrightness;
|
||||
}
|
||||
|
||||
for (const auto& node : kBreathNodes) {
|
||||
if (std::ifstream(mBasePath + node).good()) {
|
||||
mBreathNode = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mSupportsTimed = std::ifstream(mBasePath + kBlinkNode).good() &&
|
||||
std::ifstream(mBasePath + kStartIdxNode).good() &&
|
||||
std::ifstream(mBasePath + kDutyPctsNode).good() &&
|
||||
std::ifstream(mBasePath + kPauseLoNode).good() &&
|
||||
std::ifstream(mBasePath + kPauseHiNode).good() &&
|
||||
std::ifstream(mBasePath + kRampStepMsNode).good();
|
||||
}
|
||||
|
||||
std::string LedDevice::getName() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
bool LedDevice::supportsBreath() const {
|
||||
return !mBreathNode.empty();
|
||||
}
|
||||
|
||||
bool LedDevice::supportsTimed() const {
|
||||
return mSupportsTimed;
|
||||
}
|
||||
|
||||
bool LedDevice::exists() const {
|
||||
return std::ifstream(mBasePath + kBrightnessNode).good();
|
||||
}
|
||||
|
||||
static std::string getScaledDutyPercent(uint8_t brightness) {
|
||||
std::string output;
|
||||
for (int i = 0; i < kRampSteps; i++) {
|
||||
if (i != 0) {
|
||||
output += ",";
|
||||
}
|
||||
output += std::to_string(i * 100 * brightness / (0xFF * kRampSteps));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
bool LedDevice::setBrightness(uint8_t value, LightMode mode, uint32_t flashOnMs,
|
||||
uint32_t flashOffMs) {
|
||||
// Disable current blinking
|
||||
if (mSupportsTimed) {
|
||||
writeToFile(mBasePath + kBlinkNode, 0);
|
||||
}
|
||||
if (supportsBreath()) {
|
||||
writeToFile(mBasePath + mBreathNode, 0);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case LightMode::TIMED:
|
||||
if (mSupportsTimed) {
|
||||
int32_t stepDuration = kRampMaxStepDurationMs;
|
||||
int32_t pauseLo = flashOffMs;
|
||||
int32_t pauseHi = flashOnMs - (stepDuration * kRampSteps * 2);
|
||||
|
||||
if (pauseHi < 0) {
|
||||
stepDuration = flashOnMs / (kRampSteps * 2);
|
||||
pauseHi = 0;
|
||||
}
|
||||
|
||||
return writeToFile(mBasePath + kStartIdxNode, mIdx * kRampSteps) &&
|
||||
writeToFile(mBasePath + kDutyPctsNode, getScaledDutyPercent(value)) &&
|
||||
writeToFile(mBasePath + kPauseLoNode, pauseLo) &&
|
||||
writeToFile(mBasePath + kPauseHiNode, pauseHi) &&
|
||||
writeToFile(mBasePath + kRampStepMsNode, stepDuration) &&
|
||||
writeToFile(mBasePath + kBlinkNode, 1);
|
||||
}
|
||||
|
||||
// Fallthrough to breath mode if timed is not supported
|
||||
FALLTHROUGH_INTENDED;
|
||||
case LightMode::BREATH:
|
||||
if (supportsBreath()) {
|
||||
return writeToFile(mBasePath + mBreathNode, value > 0 ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Fallthrough to static mode if breath is not supported
|
||||
FALLTHROUGH_INTENDED;
|
||||
case LightMode::STATIC:
|
||||
return writeToFile(mBasePath + kBrightnessNode, scaleBrightness(value, mMaxBrightness));
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown mode: " << mode;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevice::setIdx(int idx) {
|
||||
mIdx = idx;
|
||||
}
|
||||
|
||||
void LedDevice::dump(int fd) const {
|
||||
dprintf(fd, "Name: %s", mName.c_str());
|
||||
dprintf(fd, ", index: %d", mIdx);
|
||||
dprintf(fd, ", exists: %d", exists());
|
||||
dprintf(fd, ", base path: %s", mBasePath.c_str());
|
||||
dprintf(fd, ", max brightness: %u", mMaxBrightness);
|
||||
dprintf(fd, ", supports breath: %d", supportsBreath());
|
||||
dprintf(fd, ", supports timed: %d", supportsTimed());
|
||||
dprintf(fd, ", breath node: %s", mBreathNode.c_str());
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "IDumpable.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
enum LightMode {
|
||||
STATIC,
|
||||
BREATH,
|
||||
TIMED,
|
||||
};
|
||||
|
||||
/**
|
||||
* A Linux LED device.
|
||||
* @see https://docs.kernel.org/leds/leds-class.html
|
||||
*/
|
||||
class LedDevice : public IDumpable {
|
||||
public:
|
||||
LedDevice() = delete;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name The name of the LED device
|
||||
*/
|
||||
LedDevice(std::string name);
|
||||
|
||||
/**
|
||||
* Get the name of the LED device.
|
||||
*
|
||||
* @return std::string The name of the LED device
|
||||
*/
|
||||
std::string getName() const;
|
||||
|
||||
/**
|
||||
* Return whether this LED device exists.
|
||||
*
|
||||
* @return bool true if the LED device exists, false otherwise
|
||||
*/
|
||||
bool exists() const;
|
||||
|
||||
/**
|
||||
* Return whether this LED device supports breathing.
|
||||
* When it doesn't, calling setBrightness with LightMode::BREATH will behave like
|
||||
* LightMode::STATIC.
|
||||
*
|
||||
* @return bool true if the LED device supports breathing, false otherwise
|
||||
*/
|
||||
bool supportsBreath() const;
|
||||
|
||||
/**
|
||||
* Return whether this LED device supports timed mode.
|
||||
* When it doesn't, calling setBrightness with LightMode::TIMED will behave like
|
||||
* LightMode::BREATH.
|
||||
*
|
||||
* @return bool true if the LED device supports timed mode, false otherwise
|
||||
*/
|
||||
bool supportsTimed() const;
|
||||
|
||||
/**
|
||||
* Set the brightness of the LED device.
|
||||
*
|
||||
* @param value The brightness value to set
|
||||
* @param mode The light mode to use
|
||||
* @return bool true if the brightness was set successfully, false otherwise
|
||||
*/
|
||||
bool setBrightness(uint8_t value, LightMode mode = LightMode::STATIC, uint32_t flashOnMs = 0,
|
||||
uint32_t flashOffMs = 0);
|
||||
|
||||
/**
|
||||
* Set the index of the LED device.
|
||||
*
|
||||
* @param idx The index to set
|
||||
*/
|
||||
void setIdx(int idx);
|
||||
|
||||
void dump(int fd) const override;
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
int mIdx;
|
||||
std::string mBasePath;
|
||||
uint32_t mMaxBrightness;
|
||||
std::string mBreathNode;
|
||||
bool mSupportsTimed;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Lights.h"
|
||||
|
||||
#define LOG_TAG "Lights"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
#define AutoHwLight(light) \
|
||||
{ .id = static_cast<int32_t>(light), .ordinal = 0, .type = light }
|
||||
|
||||
Lights::Lights() {
|
||||
if (mDevices.hasBacklightDevices()) {
|
||||
mLights.push_back(AutoHwLight(LightType::BACKLIGHT));
|
||||
}
|
||||
|
||||
if (mDevices.hasButtonDevices()) {
|
||||
mLights.push_back(AutoHwLight(LightType::BUTTONS));
|
||||
}
|
||||
|
||||
if (mDevices.hasNotificationDevices()) {
|
||||
mLights.push_back(AutoHwLight(LightType::BATTERY));
|
||||
mLights.push_back(AutoHwLight(LightType::NOTIFICATIONS));
|
||||
mLights.push_back(AutoHwLight(LightType::ATTENTION));
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Lights::setLightState(int32_t id, const HwLightState& state) {
|
||||
rgb color(state.color);
|
||||
|
||||
LightType type = static_cast<LightType>(id);
|
||||
switch (type) {
|
||||
case LightType::BACKLIGHT:
|
||||
mDevices.setBacklightColor(color);
|
||||
break;
|
||||
case LightType::BUTTONS:
|
||||
mDevices.setButtonsColor(color);
|
||||
break;
|
||||
case LightType::BATTERY:
|
||||
mLastBatteryState = state;
|
||||
updateNotificationColor();
|
||||
break;
|
||||
case LightType::NOTIFICATIONS:
|
||||
mLastNotificationsState = state;
|
||||
updateNotificationColor();
|
||||
break;
|
||||
case LightType::ATTENTION:
|
||||
mLastAttentionState = state;
|
||||
updateNotificationColor();
|
||||
break;
|
||||
default:
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
break;
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* _aidl_return) {
|
||||
for (const auto& light : mLights) {
|
||||
_aidl_return->push_back(light);
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
binder_status_t Lights::dump(int fd, const char** /*args*/, uint32_t /*numArgs*/) {
|
||||
dprintf(fd, "Lights AIDL:\n");
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Lights:\n");
|
||||
for (const auto& light : mLights) {
|
||||
dprintf(fd, "- %d: LightType::%s\n", light.id, toString(light.type).c_str());
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Devices:\n");
|
||||
mDevices.dump(fd);
|
||||
dprintf(fd, "\n");
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
void Lights::updateNotificationColor() {
|
||||
std::lock_guard<std::mutex> lock(mLedMutex);
|
||||
|
||||
bool isBatteryLit = rgb(mLastBatteryState.color).isLit();
|
||||
bool isAttentionLit = rgb(mLastAttentionState.color).isLit();
|
||||
bool isNotificationsLit = rgb(mLastNotificationsState.color).isLit();
|
||||
|
||||
const HwLightState state = isNotificationsLit ? mLastNotificationsState
|
||||
: isAttentionLit ? mLastAttentionState
|
||||
: isBatteryLit ? mLastBatteryState
|
||||
: HwLightState();
|
||||
|
||||
rgb color(state.color);
|
||||
|
||||
LightMode lightMode;
|
||||
switch (state.flashMode) {
|
||||
case FlashMode::NONE:
|
||||
lightMode = LightMode::STATIC;
|
||||
break;
|
||||
case FlashMode::TIMED:
|
||||
lightMode = LightMode::TIMED;
|
||||
break;
|
||||
case FlashMode::HARDWARE:
|
||||
lightMode = LightMode::BREATH;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown flash mode: " << static_cast<int>(state.flashMode);
|
||||
lightMode = LightMode::STATIC;
|
||||
break;
|
||||
}
|
||||
|
||||
mDevices.setNotificationColor(color, lightMode, state.flashOnMs, state.flashOffMs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/light/BnLights.h>
|
||||
#include <mutex>
|
||||
#include "Devices.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
class Lights : public BnLights {
|
||||
public:
|
||||
Lights();
|
||||
|
||||
ndk::ScopedAStatus setLightState(int32_t id, const HwLightState& state) override;
|
||||
ndk::ScopedAStatus getLights(std::vector<HwLight>* _aidl_return) override;
|
||||
|
||||
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
|
||||
|
||||
private:
|
||||
std::vector<HwLight> mLights;
|
||||
|
||||
Devices mDevices;
|
||||
|
||||
HwLightState mLastBatteryState;
|
||||
HwLightState mLastNotificationsState;
|
||||
HwLightState mLastAttentionState;
|
||||
std::mutex mLedMutex;
|
||||
|
||||
void updateNotificationColor();
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "RgbLedDevice.h"
|
||||
|
||||
#define LOG_TAG "RgbLedDevice"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
RgbLedDevice::RgbLedDevice(LedDevice red, LedDevice green, LedDevice blue, std::string rgbSyncNode)
|
||||
: mRed(red), mGreen(green), mBlue(blue), mRgbSyncNode(rgbSyncNode), mColors(Color::NONE) {
|
||||
if (mRed.exists()) {
|
||||
mColors |= Color::RED;
|
||||
}
|
||||
if (mGreen.exists()) {
|
||||
mColors |= Color::GREEN;
|
||||
}
|
||||
if (mBlue.exists()) {
|
||||
mColors |= Color::BLUE;
|
||||
}
|
||||
if (supportsRgbSync()) {
|
||||
mRed.setIdx(0);
|
||||
mGreen.setIdx(1);
|
||||
mBlue.setIdx(2);
|
||||
}
|
||||
}
|
||||
|
||||
bool RgbLedDevice::exists() const {
|
||||
return mColors != Color::NONE;
|
||||
}
|
||||
|
||||
bool RgbLedDevice::supportsBreath() const {
|
||||
return (!mRed.exists() || mRed.supportsBreath()) &&
|
||||
(!mGreen.exists() || mGreen.supportsBreath()) &&
|
||||
(!mBlue.exists() || mBlue.supportsBreath());
|
||||
}
|
||||
|
||||
bool RgbLedDevice::supportsTimed() const {
|
||||
return (!mRed.exists() || mRed.supportsTimed()) &&
|
||||
(!mGreen.exists() || mGreen.supportsTimed()) &&
|
||||
(!mBlue.exists() || mBlue.supportsTimed());
|
||||
}
|
||||
|
||||
bool RgbLedDevice::supportsRgbSync() const {
|
||||
return std::ifstream(mRgbSyncNode).good();
|
||||
}
|
||||
|
||||
bool RgbLedDevice::setBrightness(rgb color, LightMode mode, uint32_t flashOnMs,
|
||||
uint32_t flashOffMs) {
|
||||
bool rc = true;
|
||||
|
||||
if (mColors == Color::NONE) {
|
||||
LOG(ERROR) << "No LEDs found";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == LightMode::TIMED && !supportsTimed()) {
|
||||
// Not all LEDs support timed mode, force breathing mode
|
||||
mode = LightMode::BREATH;
|
||||
}
|
||||
|
||||
if (mode == LightMode::BREATH && !supportsBreath()) {
|
||||
// Not all LEDs support breathing, force static mode
|
||||
mode = LightMode::STATIC;
|
||||
}
|
||||
|
||||
if (mode == LightMode::TIMED && supportsRgbSync()) {
|
||||
rc &= writeToFile(mRgbSyncNode, 0);
|
||||
}
|
||||
|
||||
if (mColors == Color::ALL) {
|
||||
rc &= mRed.setBrightness(color.red, mode, flashOnMs, flashOffMs);
|
||||
rc &= mGreen.setBrightness(color.green, mode, flashOnMs, flashOffMs);
|
||||
rc &= mBlue.setBrightness(color.blue, mode, flashOnMs, flashOffMs);
|
||||
} else {
|
||||
// Check if we have only one LED
|
||||
if (mColors == Color::RED) {
|
||||
rc &= mRed.setBrightness(color.toBrightness(), mode, flashOnMs, flashOffMs);
|
||||
} else if (mColors == Color::GREEN) {
|
||||
rc &= mGreen.setBrightness(color.toBrightness(), mode, flashOnMs, flashOffMs);
|
||||
} else if (mColors == Color::BLUE) {
|
||||
rc &= mBlue.setBrightness(color.toBrightness(), mode, flashOnMs, flashOffMs);
|
||||
} else {
|
||||
// We only have two LEDs, blend the missing color in the other two
|
||||
if ((mColors & Color::RED) == Color::NONE) {
|
||||
rc &= mBlue.setBrightness((color.blue + color.red) / 2, mode, flashOnMs,
|
||||
flashOffMs);
|
||||
rc &= mGreen.setBrightness((color.green + color.red) / 2, mode, flashOnMs,
|
||||
flashOffMs);
|
||||
} else if ((mColors & Color::GREEN) == Color::NONE) {
|
||||
rc &= mRed.setBrightness((color.red + color.green) / 2, mode, flashOnMs,
|
||||
flashOffMs);
|
||||
rc &= mBlue.setBrightness((color.blue + color.green) / 2, mode, flashOnMs,
|
||||
flashOffMs);
|
||||
} else if ((mColors & Color::BLUE) == Color::NONE) {
|
||||
rc &= mRed.setBrightness((color.red + color.blue) / 2, mode, flashOnMs, flashOffMs);
|
||||
rc &= mGreen.setBrightness((color.green + color.blue) / 2, mode, flashOnMs,
|
||||
flashOffMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == LightMode::TIMED && supportsRgbSync()) {
|
||||
rc &= writeToFile(mRgbSyncNode, 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void RgbLedDevice::dump(int fd) const {
|
||||
dprintf(fd, "Exists: %d", exists());
|
||||
dprintf(fd, ", supports breath: %d", supportsBreath());
|
||||
dprintf(fd, ", supports timed: %d", supportsTimed());
|
||||
dprintf(fd, ", supports RGB sync: %d", supportsRgbSync());
|
||||
dprintf(fd, ", colors:");
|
||||
if (mColors != Color::NONE) {
|
||||
if (mColors & Color::RED) {
|
||||
dprintf(fd, "\nRed: ");
|
||||
mRed.dump(fd);
|
||||
}
|
||||
if (mColors & Color::GREEN) {
|
||||
dprintf(fd, "\nGreen: ");
|
||||
mGreen.dump(fd);
|
||||
}
|
||||
if (mColors & Color::BLUE) {
|
||||
dprintf(fd, "\nBlue: ");
|
||||
mBlue.dump(fd);
|
||||
}
|
||||
} else {
|
||||
dprintf(fd, " None");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDumpable.h"
|
||||
#include "LedDevice.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
/**
|
||||
* A pool of LED devices that will be toggled based on the wanted color.
|
||||
* Support all types of LED combinations, with a maximum of 3 LEDs.
|
||||
* Also supports 2 color LEDs (*cough* ASUS *cough*).
|
||||
*/
|
||||
class RgbLedDevice : public IDumpable {
|
||||
public:
|
||||
RgbLedDevice() = delete;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param red The red LED device
|
||||
* @param green The green LED device
|
||||
* @param blue The blue LED device
|
||||
* @param rgbSyncNode The path to RGB sync trigger
|
||||
*/
|
||||
RgbLedDevice(LedDevice red, LedDevice green, LedDevice blue, std::string rgbSyncNode);
|
||||
|
||||
/**
|
||||
* Return whether this RGB LED device exists.
|
||||
* This is true when at least one of the LEDs exists.
|
||||
*
|
||||
* @return bool true if the RGB LED device exists, false otherwise
|
||||
*/
|
||||
bool exists() const;
|
||||
|
||||
/**
|
||||
* Return whether this RGB LED device supports breathing.
|
||||
* This is true when all existing LEDs support breathing.
|
||||
* In case this is false, calling setBrightness with LightMode::BREATH will behave like
|
||||
* LightMode::STATIC.
|
||||
*
|
||||
* @return bool true if the RGB LED device supports breathing, false otherwise
|
||||
*/
|
||||
bool supportsBreath() const;
|
||||
|
||||
/**
|
||||
* Return whether this RGB LED device supports timed mode.
|
||||
* This is true when all existing LEDs support timed mode.
|
||||
* In case this is false, calling setBrightness with LightMode::TIMED will behave like
|
||||
* LightMode::BREATH.
|
||||
*
|
||||
* @return bool true if the RGB LED device supports timed mode, false otherwise
|
||||
*/
|
||||
bool supportsTimed() const;
|
||||
|
||||
/**
|
||||
* Return whether this RGB LED device supports RGB sync.
|
||||
*
|
||||
* @return bool true if the RGB LED device supports RGB sync, false otherwise
|
||||
*/
|
||||
bool supportsRgbSync() const;
|
||||
|
||||
/**
|
||||
* Set the brightness of this RGB LED device.
|
||||
*
|
||||
* @param color The color to set
|
||||
* @param mode The mode to set
|
||||
* @return bool true if the brightness was set successfully, false otherwise
|
||||
*/
|
||||
bool setBrightness(rgb color, LightMode mode = LightMode::STATIC, uint32_t flashOnMs = 0,
|
||||
uint32_t flashOffMs = 0);
|
||||
|
||||
void dump(int fd) const override;
|
||||
|
||||
enum Color {
|
||||
NONE = 0,
|
||||
RED = 1 << 0,
|
||||
GREEN = 1 << 1,
|
||||
BLUE = 1 << 2,
|
||||
ALL = RED | GREEN | BLUE,
|
||||
};
|
||||
|
||||
private:
|
||||
LedDevice mRed;
|
||||
LedDevice mGreen;
|
||||
LedDevice mBlue;
|
||||
std::string mRgbSyncNode;
|
||||
|
||||
int mColors;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
rgb::rgb() : red(0), green(0), blue(0) {}
|
||||
|
||||
rgb::rgb(uint8_t r, uint8_t g, uint8_t b) : red(r), green(g), blue(b){};
|
||||
|
||||
rgb::rgb(uint32_t color) {
|
||||
// Extract brightness from AARRGGBB.
|
||||
uint8_t alpha = (color >> 24) & 0xFF;
|
||||
|
||||
// Retrieve each of the RGB colors
|
||||
red = (color >> 16) & 0xFF;
|
||||
green = (color >> 8) & 0xFF;
|
||||
blue = color & 0xFF;
|
||||
|
||||
// Scale RGB colors if a brightness has been applied by the user
|
||||
if (alpha > 0 && alpha < 0xFF) {
|
||||
red = red * alpha / 0xFF;
|
||||
green = green * alpha / 0xFF;
|
||||
blue = blue * alpha / 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
bool rgb::isLit() {
|
||||
return !!red || !!green || !!blue;
|
||||
}
|
||||
|
||||
static constexpr uint8_t kRedWeight = 77;
|
||||
static constexpr uint8_t kGreenWeight = 150;
|
||||
static constexpr uint8_t kBlueWeight = 29;
|
||||
|
||||
uint8_t rgb::toBrightness() {
|
||||
return (kRedWeight * red + kGreenWeight * green + kBlueWeight * blue) >> 8;
|
||||
}
|
||||
|
||||
uint32_t scaleBrightness(uint8_t brightness, uint32_t maxBrightness) {
|
||||
return brightness * maxBrightness / 0xFF;
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace light {
|
||||
|
||||
struct rgb {
|
||||
rgb();
|
||||
rgb(uint8_t r, uint8_t g, uint8_t b);
|
||||
rgb(uint32_t color);
|
||||
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
|
||||
bool isLit();
|
||||
uint8_t toBrightness();
|
||||
};
|
||||
|
||||
uint32_t scaleBrightness(uint8_t brightness, uint32_t maxBrightness);
|
||||
|
||||
template <typename T>
|
||||
bool readFromFile(const std::string& file, T& content) {
|
||||
std::ifstream fileStream(file);
|
||||
|
||||
if (!fileStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fileStream >> content;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool writeToFile(const std::string& file, const T content) {
|
||||
std::ofstream fileStream(file);
|
||||
|
||||
if (!fileStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fileStream << content;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -1,106 +0,0 @@
|
||||
on early-boot
|
||||
# Backlight devices
|
||||
chown system system /sys/class/backlight/backlight/brightness
|
||||
chown system system /sys/class/backlight/backlight/max_brightness
|
||||
|
||||
chown system system /sys/class/backlight/panel0-backlight/brightness
|
||||
chown system system /sys/class/backlight/panel0-backlight/max_brightness
|
||||
|
||||
# LED devices
|
||||
chown system system /sys/class/leds/blue/blink
|
||||
chown system system /sys/class/leds/blue/breath
|
||||
chown system system /sys/class/leds/blue/brightness
|
||||
chown system system /sys/class/leds/blue/duty_pcts
|
||||
chown system system /sys/class/leds/blue/max_brightness
|
||||
chown system system /sys/class/leds/blue/pause_hi
|
||||
chown system system /sys/class/leds/blue/pause_lo
|
||||
chown system system /sys/class/leds/blue/ramp_step_ms
|
||||
chown system system /sys/class/leds/blue/start_idx
|
||||
|
||||
chown system system /sys/class/leds/button-backlight/blink
|
||||
chown system system /sys/class/leds/button-backlight/breath
|
||||
chown system system /sys/class/leds/button-backlight/brightness
|
||||
chown system system /sys/class/leds/button-backlight/duty_pcts
|
||||
chown system system /sys/class/leds/button-backlight/max_brightness
|
||||
chown system system /sys/class/leds/button-backlight/pause_hi
|
||||
chown system system /sys/class/leds/button-backlight/pause_lo
|
||||
chown system system /sys/class/leds/button-backlight/ramp_step_ms
|
||||
chown system system /sys/class/leds/button-backlight/start_idx
|
||||
|
||||
chown system system /sys/class/leds/button-backlight1/blink
|
||||
chown system system /sys/class/leds/button-backlight1/breath
|
||||
chown system system /sys/class/leds/button-backlight1/brightness
|
||||
chown system system /sys/class/leds/button-backlight1/duty_pcts
|
||||
chown system system /sys/class/leds/button-backlight1/max_brightness
|
||||
chown system system /sys/class/leds/button-backlight1/pause_hi
|
||||
chown system system /sys/class/leds/button-backlight1/pause_lo
|
||||
chown system system /sys/class/leds/button-backlight1/ramp_step_ms
|
||||
chown system system /sys/class/leds/button-backlight1/start_idx
|
||||
|
||||
chown system system /sys/class/leds/button-backlight2/blink
|
||||
chown system system /sys/class/leds/button-backlight2/breath
|
||||
chown system system /sys/class/leds/button-backlight2/brightness
|
||||
chown system system /sys/class/leds/button-backlight2/duty_pcts
|
||||
chown system system /sys/class/leds/button-backlight2/max_brightness
|
||||
chown system system /sys/class/leds/button-backlight2/pause_hi
|
||||
chown system system /sys/class/leds/button-backlight2/pause_lo
|
||||
chown system system /sys/class/leds/button-backlight2/ramp_step_ms
|
||||
chown system system /sys/class/leds/button-backlight2/start_idx
|
||||
|
||||
chown system system /sys/class/leds/green/blink
|
||||
chown system system /sys/class/leds/green/breath
|
||||
chown system system /sys/class/leds/green/brightness
|
||||
chown system system /sys/class/leds/green/duty_pcts
|
||||
chown system system /sys/class/leds/green/max_brightness
|
||||
chown system system /sys/class/leds/green/pause_hi
|
||||
chown system system /sys/class/leds/green/pause_lo
|
||||
chown system system /sys/class/leds/green/ramp_step_ms
|
||||
chown system system /sys/class/leds/green/start_idx
|
||||
|
||||
chown system system /sys/class/leds/lcd-backlight/blink
|
||||
chown system system /sys/class/leds/lcd-backlight/breath
|
||||
chown system system /sys/class/leds/lcd-backlight/brightness
|
||||
chown system system /sys/class/leds/lcd-backlight/duty_pcts
|
||||
chown system system /sys/class/leds/lcd-backlight/max_brightness
|
||||
chown system system /sys/class/leds/lcd-backlight/pause_hi
|
||||
chown system system /sys/class/leds/lcd-backlight/pause_lo
|
||||
chown system system /sys/class/leds/lcd-backlight/ramp_step_ms
|
||||
chown system system /sys/class/leds/lcd-backlight/start_idx
|
||||
|
||||
chown system system /sys/class/leds/left/blink
|
||||
chown system system /sys/class/leds/left/breath
|
||||
chown system system /sys/class/leds/left/brightness
|
||||
chown system system /sys/class/leds/left/duty_pcts
|
||||
chown system system /sys/class/leds/left/max_brightness
|
||||
chown system system /sys/class/leds/left/pause_hi
|
||||
chown system system /sys/class/leds/left/pause_lo
|
||||
chown system system /sys/class/leds/left/ramp_step_ms
|
||||
chown system system /sys/class/leds/left/start_idx
|
||||
|
||||
chown system system /sys/class/leds/red/blink
|
||||
chown system system /sys/class/leds/red/breath
|
||||
chown system system /sys/class/leds/red/brightness
|
||||
chown system system /sys/class/leds/red/duty_pcts
|
||||
chown system system /sys/class/leds/red/max_brightness
|
||||
chown system system /sys/class/leds/red/pause_hi
|
||||
chown system system /sys/class/leds/red/pause_lo
|
||||
chown system system /sys/class/leds/red/ramp_step_ms
|
||||
chown system system /sys/class/leds/red/start_idx
|
||||
|
||||
chown system system /sys/class/leds/rgb/rgb_blink
|
||||
|
||||
chown system system /sys/class/leds/white/blink
|
||||
chown system system /sys/class/leds/white/breath
|
||||
chown system system /sys/class/leds/white/brightness
|
||||
chown system system /sys/class/leds/white/duty_pcts
|
||||
chown system system /sys/class/leds/white/max_brightness
|
||||
chown system system /sys/class/leds/white/pause_hi
|
||||
chown system system /sys/class/leds/white/pause_lo
|
||||
chown system system /sys/class/leds/white/ramp_step_ms
|
||||
chown system system /sys/class/leds/white/start_idx
|
||||
|
||||
service vendor.light-default /vendor/bin/hw/android.hardware.light-service.xiaomi
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
shutdown critical
|
||||
@@ -1,7 +0,0 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.light</name>
|
||||
<version>2</version>
|
||||
<fqname>ILights/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "Lights.h"
|
||||
|
||||
#define LOG_TAG "android.hardware.light-service.xiaomi"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using ::aidl::android::hardware::light::Lights;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
|
||||
if (!lights) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const std::string instance = std::string() + Lights::descriptor + "/default";
|
||||
binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
|
||||
CHECK(status == STATUS_OK);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
@@ -38,7 +38,7 @@ cc_binary {
|
||||
"android.hardware.sensors@2.0-ScopedWakelock",
|
||||
"android.hardware.sensors@2.0",
|
||||
"android.hardware.sensors@2.1",
|
||||
"android.hardware.sensors-V2-ndk",
|
||||
"android.hardware.sensors-V3-ndk",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.sensors</name>
|
||||
<version>2</version>
|
||||
<version>3</version>
|
||||
<fqname>ISensors/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
|
||||
48
aidl/touch/Android.bp
Normal file
48
aidl/touch/Android.bp
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
name: "vendor.lineage.touch-service.xiaomi",
|
||||
init_rc: ["vendor.lineage.touch-service.xiaomi.rc"],
|
||||
vintf_fragments: select(soong_config_variable("XIAOMI_TOUCH", "HIGH_TOUCH_POLLING_PATH"), {
|
||||
any: ["vendor.lineage.touch-service.xiaomi-htpr.xml"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_DISABLER_CONTROL_PATH"), {
|
||||
any: ["vendor.lineage.touch-service.xiaomi-kd.xml"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_SWAPPER_CONTROL_PATH"), {
|
||||
any: ["vendor.lineage.touch-service.xiaomi-ks.xml"],
|
||||
default: [],
|
||||
}),
|
||||
relative_install_path: "hw",
|
||||
proprietary: true,
|
||||
cppflags: select(soong_config_variable("XIAOMI_TOUCH", "HIGH_TOUCH_POLLING_PATH"), {
|
||||
any @ flag_val: ["-DHTPR_CONTROL_PATH=\"" + flag_val + "\""],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_DISABLER_CONTROL_PATH"), {
|
||||
any @ flag_val: ["-DKD_CONTROL_PATH=\"" + flag_val + "\""],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_SWAPPER_CONTROL_PATH"), {
|
||||
any @ flag_val: ["-DKS_CONTROL_PATH=\"" + flag_val + "\""],
|
||||
default: [],
|
||||
}),
|
||||
srcs: select(soong_config_variable("XIAOMI_TOUCH", "HIGH_TOUCH_POLLING_PATH"), {
|
||||
any: ["HighTouchPollingRate.cpp"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_DISABLER_CONTROL_PATH"), {
|
||||
any: ["KeyDisabler.cpp"],
|
||||
default: [],
|
||||
}) + select(soong_config_variable("XIAOMI_TOUCH", "KEY_SWAPPER_CONTROL_PATH"), {
|
||||
any: ["KeySwapper.cpp"],
|
||||
default: [],
|
||||
}) + ["service.cpp"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"vendor.lineage.touch-V1-ndk",
|
||||
],
|
||||
}
|
||||
46
aidl/touch/HighTouchPollingRate.cpp
Normal file
46
aidl/touch/HighTouchPollingRate.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "vendor.lineage.touch-service.xiaomi"
|
||||
|
||||
#include "HighTouchPollingRate.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
using ::android::base::ReadFileToString;
|
||||
using ::android::base::Trim;
|
||||
using ::android::base::WriteStringToFile;
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
ndk::ScopedAStatus HighTouchPollingRate::getEnabled(bool* _aidl_return) {
|
||||
std::string buf;
|
||||
if (!ReadFileToString(HTPR_CONTROL_PATH, &buf)) {
|
||||
LOG(ERROR) << "Failed to read current HighTouchPollingRate state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
*_aidl_return = Trim(buf) == "1";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HighTouchPollingRate::setEnabled(bool enabled) {
|
||||
if (!WriteStringToFile(enabled ? "1" : "0", HTPR_CONTROL_PATH)) {
|
||||
LOG(ERROR) << "Failed to write HighTouchPollingRate state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
24
aidl/touch/HighTouchPollingRate.h
Normal file
24
aidl/touch/HighTouchPollingRate.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/vendor/lineage/touch/BnHighTouchPollingRate.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
class HighTouchPollingRate : public BnHighTouchPollingRate {
|
||||
public:
|
||||
ndk::ScopedAStatus getEnabled(bool* _aidl_return) override;
|
||||
ndk::ScopedAStatus setEnabled(bool enabled) override;
|
||||
};
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
46
aidl/touch/KeyDisabler.cpp
Normal file
46
aidl/touch/KeyDisabler.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "vendor.lineage.touch-service.xiaomi"
|
||||
|
||||
#include "KeyDisabler.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
using ::android::base::ReadFileToString;
|
||||
using ::android::base::Trim;
|
||||
using ::android::base::WriteStringToFile;
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
ndk::ScopedAStatus KeyDisabler::getEnabled(bool* _aidl_return) {
|
||||
std::string buf;
|
||||
if (!ReadFileToString(KD_CONTROL_PATH, &buf)) {
|
||||
LOG(ERROR) << "Failed to read current KeyDisabler state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
*_aidl_return = Trim(buf) == "0";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus KeyDisabler::setEnabled(bool enabled) {
|
||||
if (!WriteStringToFile(enabled ? "0" : "1", KD_CONTROL_PATH, true)) {
|
||||
LOG(ERROR) << "Failed to write KeyDisabler state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
24
aidl/touch/KeyDisabler.h
Normal file
24
aidl/touch/KeyDisabler.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/vendor/lineage/touch/BnKeyDisabler.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
class KeyDisabler : public BnKeyDisabler {
|
||||
public:
|
||||
ndk::ScopedAStatus getEnabled(bool* _aidl_return) override;
|
||||
ndk::ScopedAStatus setEnabled(bool enabled) override;
|
||||
};
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
46
aidl/touch/KeySwapper.cpp
Normal file
46
aidl/touch/KeySwapper.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "vendor.lineage.touch-service.xiaomi"
|
||||
|
||||
#include "KeySwapper.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
using ::android::base::ReadFileToString;
|
||||
using ::android::base::Trim;
|
||||
using ::android::base::WriteStringToFile;
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
ndk::ScopedAStatus KeySwapper::getEnabled(bool* _aidl_return) {
|
||||
std::string buf;
|
||||
if (!ReadFileToString(KS_CONTROL_PATH, &buf)) {
|
||||
LOG(ERROR) << "Failed to read current KeySwapper state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
*_aidl_return = Trim(buf) == "1";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus KeySwapper::setEnabled(bool enabled) {
|
||||
if (!WriteStringToFile(enabled ? "1" : "0", KS_CONTROL_PATH, true)) {
|
||||
LOG(ERROR) << "Failed to write KeySwapper state";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
24
aidl/touch/KeySwapper.h
Normal file
24
aidl/touch/KeySwapper.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/vendor/lineage/touch/BnKeySwapper.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace vendor {
|
||||
namespace lineage {
|
||||
namespace touch {
|
||||
|
||||
class KeySwapper : public BnKeySwapper {
|
||||
public:
|
||||
ndk::ScopedAStatus getEnabled(bool* _aidl_return) override;
|
||||
ndk::ScopedAStatus setEnabled(bool enabled) override;
|
||||
};
|
||||
|
||||
} // namespace touch
|
||||
} // namespace lineage
|
||||
} // namespace vendor
|
||||
} // namespace aidl
|
||||
48
aidl/touch/service.cpp
Normal file
48
aidl/touch/service.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The LineageOS Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_TAG "vendor.lineage.touch-service.xiaomi"
|
||||
|
||||
#include "HighTouchPollingRate.h"
|
||||
#include "KeyDisabler.h"
|
||||
#include "KeySwapper.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using aidl::vendor::lineage::touch::HighTouchPollingRate;
|
||||
using aidl::vendor::lineage::touch::KeyDisabler;
|
||||
using aidl::vendor::lineage::touch::KeySwapper;
|
||||
|
||||
int main() {
|
||||
binder_status_t status = STATUS_OK;
|
||||
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
|
||||
#ifdef HTPR_CONTROL_PATH
|
||||
std::shared_ptr<HighTouchPollingRate> htpr = ndk::SharedRefBase::make<HighTouchPollingRate>();
|
||||
const std::string htpr_instance = std::string(HighTouchPollingRate::descriptor) + "/default";
|
||||
status = AServiceManager_addService(htpr->asBinder().get(), htpr_instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK) << "Failed to add service " << htpr_instance << " " << status;
|
||||
#endif
|
||||
|
||||
#ifdef KD_CONTROL_PATH
|
||||
std::shared_ptr<KeyDisabler> kd = ndk::SharedRefBase::make<KeyDisabler>();
|
||||
const std::string kd_instance = std::string(KeyDisabler::descriptor) + "/default";
|
||||
status = AServiceManager_addService(kd->asBinder().get(), kd_instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK) << "Failed to add service " << kd_instance << " " << status;
|
||||
#endif
|
||||
|
||||
#ifdef KS_CONTROL_PATH
|
||||
std::shared_ptr<KeySwapper> ks = ndk::SharedRefBase::make<KeySwapper>();
|
||||
const std::string ks_instance = std::string(KeySwapper::descriptor) + "/default";
|
||||
status = AServiceManager_addService(ks->asBinder().get(), ks_instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK) << "Failed to add service " << ks_instance << " " << status;
|
||||
#endif
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="hidl">
|
||||
<hal format="aidl">
|
||||
<name>vendor.lineage.touch</name>
|
||||
<transport>hwbinder</transport>
|
||||
<version>1.0</version>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>IHighTouchPollingRate</name>
|
||||
<instance>default</instance>
|
||||
10
aidl/touch/vendor.lineage.touch-service.xiaomi-kd.xml
Normal file
10
aidl/touch/vendor.lineage.touch-service.xiaomi-kd.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>vendor.lineage.touch</name>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>IKeyDisabler</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
10
aidl/touch/vendor.lineage.touch-service.xiaomi-ks.xml
Normal file
10
aidl/touch/vendor.lineage.touch-service.xiaomi-ks.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>vendor.lineage.touch</name>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>IKeySwapper</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
4
aidl/touch/vendor.lineage.touch-service.xiaomi.rc
Normal file
4
aidl/touch/vendor.lineage.touch-service.xiaomi.rc
Normal file
@@ -0,0 +1,4 @@
|
||||
service vendor.touch-hal /vendor/bin/hw/vendor.lineage.touch-service.xiaomi
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
@@ -10,7 +10,8 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:label="@string/dolby_title"
|
||||
android:persistent="true">
|
||||
|
||||
@@ -36,6 +37,10 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.CATEGORY_CONTENT_MUSIC" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.sound" />
|
||||
<meta-data android:name="com.android.settings.summary_uri"
|
||||
|
||||
12
dolby/res/drawable/ic_launcher_background.xml
Normal file
12
dolby/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector android:height="108.0dip" android:width="108.0dip" android:viewportWidth="108.0" android:viewportHeight="108.0"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<group android:scaleX="1.3544992" android:scaleY="1.3544992" android:translateX="-23.22" android:translateY="-23.22">
|
||||
<group>
|
||||
<clip-path android:pathData="M57.01,57.01m-54,0a54,54 0,1 1,108 0a54,54 0,1 1,-108 0" />
|
||||
<path android:fillColor="#ffeaedef" android:pathData="M-1.9,-1.9h117.82v117.82h-117.82z" />
|
||||
<path android:fillColor="@drawable/ic_launcher_background__0" android:pathData="M-1.9,115.92l0,-117.82l117.82,0l-117.82,117.82z" />
|
||||
<path android:fillColor="@drawable/ic_launcher_background__1" android:pathData="M-1.9,-1.9h117.82v117.82h-117.82z" android:strokeAlpha="0.2" android:fillAlpha="0.2" />
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
6
dolby/res/drawable/ic_launcher_background__0.xml
Normal file
6
dolby/res/drawable/ic_launcher_background__0.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<gradient android:angle="0.0" android:type="linear" android:startX="57.01" android:startY="56.4" android:endX="57.01" android:endY="-1.58"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<item android:color="#ffffffff" android:offset="0.0" />
|
||||
<item android:color="#fff3f5f6" android:offset="1.0" />
|
||||
</gradient>
|
||||
6
dolby/res/drawable/ic_launcher_background__1.xml
Normal file
6
dolby/res/drawable/ic_launcher_background__1.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<gradient android:angle="0.0" android:type="linear" android:startX="-1.9" android:startY="115.92" android:endX="115.92" android:endY="-1.9"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<item android:color="#ff80d0ce" android:offset="0.0" />
|
||||
<item android:color="#ff9fa8da" android:offset="1.0" />
|
||||
</gradient>
|
||||
8
dolby/res/drawable/ic_launcher_foreground.xml
Normal file
8
dolby/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector android:height="108.0dip" android:width="108.0dip" android:viewportWidth="108.0" android:viewportHeight="108.0"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<group android:scaleX="0.84" android:scaleY="0.84" android:translateX="23.76" android:translateY="23.76">
|
||||
<path android:fillColor="#ff465461" android:pathData="M12,19.13h5a16.87,16.87 0,0 1,0 33.74H12Z" />
|
||||
<path android:fillColor="#ff465461" android:pathData="M60,52.87H55a16.87,16.87 0,0 1,0 -33.74h5Z" />
|
||||
</group>
|
||||
</vector>
|
||||
4
dolby/res/drawable/ic_launcher_mono.xml
Normal file
4
dolby/res/drawable/ic_launcher_mono.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="108dp" android:width="108dp" android:viewportWidth="108" android:viewportHeight="108">
|
||||
<path android:fillColor="#000000" android:pathData="M36.6305484,38 C45.6078241,38.1592687 52.837468,45.7082857 52.837468,54.9974325 C52.837468,64.2865794 45.6078241,71.8355964 36.6307694,71.9948651 L32,72 L32,38 L36.6305484,38 Z M36.999,43.017 L36.999,66.977 L37.1225728,66.9701894 C42.9872179,66.559014 47.6837958,61.5395304 47.8337726,55.3050128 L47.837468,54.9974325 C47.837468,48.6211219 43.0833381,43.4425908 37.1223719,43.0246757 L36.999,43.017 Z M71.3694516,38 C62.3921759,38.1592687 55.162532,45.7082857 55.162532,54.9974325 C55.162532,64.2865794 62.3921759,71.8355964 71.3692306,71.9948651 L76,72 L76,38 L71.3694516,38 Z M71.000532,43.017 L71.000532,66.977 L70.8774272,66.9701894 C65.0127821,66.559014 60.3162042,61.5395304 60.1662274,55.3050128 L60.162532,54.9974325 C60.162532,48.6211219 64.9166619,43.4425908 70.8776281,43.0246757 L71.000532,43.017 Z" android:strokeWidth="1"/>
|
||||
</vector>
|
||||
11
dolby/res/drawable/ic_profile_custom.xml
Executable file
11
dolby/res/drawable/ic_profile_custom.xml
Executable file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="72.0"
|
||||
android:viewportHeight="72.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M45,9L45,27L51,27L51,21L63,21L63,15L51,15L51,9L45,9M9,15L9,21L39,21L39,15L9,15M21,27L21,33L9,33L9,39L21,39L21,45L27,45L27,27L21,27M33,33L33,39L63,39L63,33L33,33M33,45L33,63L39,63L39,57L63,57L63,51L39,51L39,45L33,45M9,51L9,57L27,57L27,51L9,51z"/>
|
||||
</vector>
|
||||
11
dolby/res/drawable/ic_profile_dynamic.xml
Executable file
11
dolby/res/drawable/ic_profile_dynamic.xml
Executable file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="72.0"
|
||||
android:viewportHeight="72.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M21,6L21,39L30,39L30,66C34.0185,62.1036 36.3516,56.7839 39.2006,52C43.3436,45.0435 48.7076,37.7933 51,30L40,30C43.3656,21.916 48.5711,14.4315 51,6L21,6z"/>
|
||||
</vector>
|
||||
11
dolby/res/drawable/ic_profile_movie.xml
Executable file
11
dolby/res/drawable/ic_profile_movie.xml
Executable file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="72.0"
|
||||
android:viewportHeight="72.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.84,13.82C9.62,11.74 12.52,12.02 14.98,11.95C16.97,15.97 19,19.98 21,24C24,24 27,24 30,24C28,20 26,16 24,12C26,12 28,12 30,12C32,16 34,20 36,24C39,24 42,24 45,24C43,20 41,16 39,12C41,12 43,12 45,12C47,16 49,20 51,24C54,24 57,24 60,24C58,20 56,16 54,12C58,12 62,12 66,12C65.99,25.69 66.01,39.38 66,53.07C66.42,56.49 63.62,59.98 60.12,59.96C44.39,60.06 28.66,59.97 12.93,60C9.52,60.43 6.02,57.62 6.04,54.12C5.93,42.75 6.06,31.37 6,19.99C5.95,17.82 6.08,15.36 7.84,13.82Z"/>
|
||||
</vector>
|
||||
11
dolby/res/drawable/ic_profile_music.xml
Executable file
11
dolby/res/drawable/ic_profile_music.xml
Executable file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="72.0"
|
||||
android:viewportHeight="72.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M36,9L36,40C32.245,38.8901 27.6726,38.2912 24.0154,40.179C17.5734,43.5044 15.8784,53.3215 20.4336,58.8912C25.822,65.4796 38.0937,64.1632 41.2577,55.9961C42.655,52.3894 42,47.7931 42,44L42,21L54,21L54,9L36,9z"/>
|
||||
</vector>
|
||||
7
dolby/res/mipmap-anydpi/ic_launcher.xml
Normal file
7
dolby/res/mipmap-anydpi/ic_launcher.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_mono" />
|
||||
</adaptive-icon>
|
||||
@@ -8,16 +8,16 @@
|
||||
<!-- Dolby Atmos -->
|
||||
<string-array name="dolby_profile_entries">
|
||||
<item>@string/dolby_profile_dynamic</item>
|
||||
<item>@string/dolby_profile_video</item>
|
||||
<item>@string/dolby_profile_movie</item>
|
||||
<item>@string/dolby_profile_music</item>
|
||||
<item>@string/dolby_profile_voice</item>
|
||||
<item>@string/dolby_profile_custom</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="dolby_profile_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>8</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="dolby_preset_entries" translatable="false">
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
<string name="dolby_volume_leveler">Volume leveler</string>
|
||||
<string name="dolby_connect_headphones">Connect headphones</string>
|
||||
<string name="dolby_reset_profile">Reset to defaults</string>
|
||||
<string name="dolby_reset_profile_toast">Succesfully reset settings for %1$s profile</string>
|
||||
<string name="dolby_reset_profile_toast">Successfully reset settings for %1$s profile</string>
|
||||
|
||||
<!-- Dolby profiles -->
|
||||
<string name="dolby_profile_dynamic">Dynamic</string>
|
||||
<string name="dolby_profile_video">Movie/Video</string>
|
||||
<string name="dolby_profile_movie">Movie</string>
|
||||
<string name="dolby_profile_music">Music</string>
|
||||
<string name="dolby_profile_voice">Voice</string>
|
||||
<string name="dolby_profile_custom">Custom</string>
|
||||
|
||||
<!-- Dolby equalizer presets -->
|
||||
<string name="dolby_preset_default">Flat (off)</string>
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
android:entryValues="@array/dolby_profile_values"
|
||||
android:defaultValue="0"
|
||||
android:title="@string/dolby_profile_title"
|
||||
android:summary="%s"
|
||||
android:icon="@drawable/ic_dolby" />
|
||||
android:summary="%s" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/dolby_category_settings">
|
||||
|
||||
@@ -17,7 +17,7 @@ class DolbyActivity : CollapsingToolbarBaseActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
fragmentManager.beginTransaction()
|
||||
.replace(com.android.settingslib.collapsingtoolbar.R.id.content_frame, DolbySettingsFragment(), TAG)
|
||||
.commit()
|
||||
.replace(com.android.settingslib.collapsingtoolbar.R.id.content_frame, DolbySettingsFragment(), TAG)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal class DolbyController private constructor(
|
||||
private val context: Context
|
||||
) {
|
||||
private var dolbyEffect = DolbyAudioEffect(EFFECT_PRIORITY, audioSession = 0)
|
||||
private val audioManager = context.getSystemService(AudioManager::class.java)
|
||||
private val audioManager = context.getSystemService(AudioManager::class.java)!!
|
||||
private val handler = Handler(context.mainLooper)
|
||||
|
||||
// Restore current profile on every media session
|
||||
@@ -57,10 +57,10 @@ internal class DolbyController private constructor(
|
||||
field = value
|
||||
dlog(TAG, "setRegisterCallbacks($value)")
|
||||
if (value) {
|
||||
audioManager!!.registerAudioPlaybackCallback(playbackCallback, handler)
|
||||
audioManager.registerAudioPlaybackCallback(playbackCallback, handler)
|
||||
audioManager.registerAudioDeviceCallback(audioDeviceCallback, handler)
|
||||
} else {
|
||||
audioManager!!.unregisterAudioPlaybackCallback(playbackCallback)
|
||||
audioManager.unregisterAudioPlaybackCallback(playbackCallback)
|
||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||
}
|
||||
}
|
||||
@@ -102,13 +102,13 @@ internal class DolbyController private constructor(
|
||||
dsOn = prefs.getBoolean(DolbyConstants.PREF_ENABLE, true)
|
||||
|
||||
context.resources.getStringArray(R.array.dolby_profile_values)
|
||||
.map { it.toInt() }
|
||||
.forEach { profile ->
|
||||
// Reset dolby first to prevent it from loading bad settings
|
||||
dolbyEffect.resetProfileSpecificSettings(profile)
|
||||
// Now restore our profile-specific settings
|
||||
restoreSettings(profile)
|
||||
}
|
||||
.map { it.toInt() }
|
||||
.forEach { profile ->
|
||||
// Reset dolby first to prevent it from loading bad settings
|
||||
dolbyEffect.resetProfileSpecificSettings(profile)
|
||||
// Now restore our profile-specific settings
|
||||
restoreSettings(profile)
|
||||
}
|
||||
|
||||
// Finally restore the current profile.
|
||||
setCurrentProfile()
|
||||
@@ -174,6 +174,13 @@ internal class DolbyController private constructor(
|
||||
profile = prefs.getString(DolbyConstants.PREF_PROFILE, "0" /*dynamic*/)!!.toInt()
|
||||
}
|
||||
|
||||
fun setDsOnAndPersist(dsOn: Boolean) {
|
||||
this.dsOn = dsOn
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit()
|
||||
.putBoolean(DolbyConstants.PREF_ENABLE, dsOn)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun getProfileName(): String? {
|
||||
val profile = dolbyEffect.profile.toString()
|
||||
val profiles = context.resources.getStringArray(R.array.dolby_profile_values)
|
||||
@@ -202,8 +209,8 @@ internal class DolbyController private constructor(
|
||||
dlog(TAG, "setPreset: $value")
|
||||
checkEffect()
|
||||
val gains = value.split(",")
|
||||
.map { it.toInt() }
|
||||
.toIntArray()
|
||||
.map { it.toInt() }
|
||||
.toIntArray()
|
||||
dolbyEffect.setDapParameter(DsParam.GEQ_BAND_GAINS, gains, profile)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class DolbyTileService : TileService() {
|
||||
|
||||
override fun onClick() {
|
||||
val isDsOn = dolbyController.dsOn
|
||||
dolbyController.dsOn = !isDsOn
|
||||
dolbyController.setDsOnAndPersist(!isDsOn) // toggle
|
||||
qsTile.apply {
|
||||
state = if (isDsOn) Tile.STATE_INACTIVE else Tile.STATE_ACTIVE
|
||||
updateTile()
|
||||
|
||||
@@ -58,13 +58,14 @@ class SummaryProvider : ContentProvider() {
|
||||
): Int = 0
|
||||
|
||||
private fun getDolbySummary(): String {
|
||||
val dolbyController = DolbyController.getInstance(context!!)
|
||||
val context = context!!
|
||||
val dolbyController = DolbyController.getInstance(context)
|
||||
if (!dolbyController.dsOn) {
|
||||
return context!!.getString(R.string.dolby_off)
|
||||
return context.getString(R.string.dolby_off)
|
||||
}
|
||||
return dolbyController.getProfileName()?.let {
|
||||
context!!.getString(R.string.dolby_on_with_profile, it)
|
||||
} ?: context!!.getString(R.string.dolby_on)
|
||||
context.getString(R.string.dolby_on_with_profile, it)
|
||||
} ?: context.getString(R.string.dolby_on)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,12 +11,13 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.android.settingslib.spa.framework.theme.settingsBackground
|
||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
|
||||
@Composable
|
||||
fun EqualizerScreen(
|
||||
@@ -28,7 +29,7 @@ fun EqualizerScreen(
|
||||
.fillMaxSize()
|
||||
.padding(SettingsDimension.itemPadding)
|
||||
.then(modifier),
|
||||
color = SettingsTheme.colorScheme.background
|
||||
color = MaterialTheme.colorScheme.settingsBackground
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Top,
|
||||
|
||||
@@ -27,7 +27,7 @@ fun TooltipIconButton(
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
TooltipBox(
|
||||
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
|
||||
tooltip = {
|
||||
Text(text)
|
||||
},
|
||||
|
||||
@@ -40,24 +40,24 @@ class DolbyPreferenceStore(
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) =
|
||||
getSharedPreferences(key).edit()
|
||||
.putBoolean(key, value)
|
||||
.apply()
|
||||
.putBoolean(key, value)
|
||||
.apply()
|
||||
|
||||
override fun getBoolean(key: String, defValue: Boolean) =
|
||||
getSharedPreferences(key).getBoolean(key, defValue)
|
||||
|
||||
override fun putInt(key: String, value: Int) =
|
||||
getSharedPreferences(key).edit()
|
||||
.putInt(key, value)
|
||||
.apply()
|
||||
.putInt(key, value)
|
||||
.apply()
|
||||
|
||||
override fun getInt(key: String, defValue: Int) =
|
||||
getSharedPreferences(key).getInt(key, defValue)
|
||||
|
||||
override fun putString(key: String, value: String?) =
|
||||
getSharedPreferences(key).edit()
|
||||
.putString(key, value)
|
||||
.apply()
|
||||
.putString(key, value)
|
||||
.apply()
|
||||
|
||||
override fun getString(key: String, defValue: String?) =
|
||||
getSharedPreferences(key).getString(key, defValue)
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.media.AudioManager
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener
|
||||
import android.widget.Toast
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
@@ -37,7 +38,7 @@ import co.aospa.dolby.xiaomi.R
|
||||
import com.android.settingslib.widget.MainSwitchPreference
|
||||
|
||||
class DolbySettingsFragment : PreferenceFragment(),
|
||||
OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
|
||||
OnPreferenceChangeListener, OnCheckedChangeListener {
|
||||
|
||||
private val switchBar by lazy {
|
||||
findPreference<MainSwitchPreference>(PREF_ENABLE)!!
|
||||
@@ -74,7 +75,7 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
}
|
||||
|
||||
private val dolbyController by lazy { DolbyController.getInstance(context) }
|
||||
private val audioManager by lazy { context.getSystemService(AudioManager::class.java) }
|
||||
private val audioManager by lazy { context.getSystemService(AudioManager::class.java)!! }
|
||||
private val handler = Handler()
|
||||
|
||||
private var isOnSpeaker = true
|
||||
@@ -111,6 +112,7 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
switchBar.setChecked(dsOn)
|
||||
|
||||
profilePref.onPreferenceChangeListener = this
|
||||
updateProfileIcon(profile)
|
||||
profilePref.setEnabled(dsOn)
|
||||
profilePref.apply {
|
||||
if (entryValues.contains(profile.toString())) {
|
||||
@@ -140,14 +142,14 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
true
|
||||
}
|
||||
|
||||
audioManager!!.registerAudioDeviceCallback(audioDeviceCallback, handler)
|
||||
audioManager.registerAudioDeviceCallback(audioDeviceCallback, handler)
|
||||
updateSpeakerState()
|
||||
updateProfileSpecificPrefs()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
dlog(TAG, "onDestroyView")
|
||||
audioManager!!.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@@ -163,6 +165,7 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
val profile = newValue.toString().toInt()
|
||||
dolbyController.profile = profile
|
||||
(preferenceManager.preferenceDataStore as DolbyPreferenceStore).profile = profile
|
||||
updateProfileIcon(profile)
|
||||
updateProfileSpecificPrefs()
|
||||
}
|
||||
|
||||
@@ -207,7 +210,7 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun updateSpeakerState() {
|
||||
val device = audioManager!!.getDevicesForAttributes(ATTRIBUTES_MEDIA)[0]
|
||||
val device = audioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)[0]
|
||||
isOnSpeaker = (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
|
||||
}
|
||||
|
||||
@@ -228,10 +231,10 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
ieqPref.setEnabled(enable)
|
||||
dialoguePref.setEnabled(enable)
|
||||
volumePref.setEnabled(enable)
|
||||
bassPref.setEnabled(enable)
|
||||
resetPref.setEnabled(enable)
|
||||
hpVirtPref.setEnabled(enable && !isOnSpeaker)
|
||||
stereoPref.setEnabled(enable && !isOnSpeaker)
|
||||
bassPref.setEnabled(enable && !isOnSpeaker)
|
||||
|
||||
if (!enable) return
|
||||
|
||||
@@ -259,11 +262,11 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
|
||||
spkVirtPref.setChecked(dolbyController.getSpeakerVirtEnabled(currentProfile))
|
||||
volumePref.setChecked(dolbyController.getVolumeLevelerEnabled(currentProfile))
|
||||
bassPref.setChecked(dolbyController.getBassEnhancerEnabled(currentProfile))
|
||||
|
||||
// below prefs are not enabled on loudspeaker
|
||||
if (isOnSpeaker) {
|
||||
stereoPref.summary = headphoneRes
|
||||
bassPref.summary = headphoneRes
|
||||
hpVirtPref.summary = headphoneRes
|
||||
return
|
||||
}
|
||||
@@ -278,21 +281,26 @@ class DolbySettingsFragment : PreferenceFragment(),
|
||||
}
|
||||
}
|
||||
|
||||
bassPref.apply {
|
||||
setChecked(dolbyController.getBassEnhancerEnabled(currentProfile))
|
||||
summary = null
|
||||
}
|
||||
|
||||
hpVirtPref.apply {
|
||||
setChecked(dolbyController.getHeadphoneVirtEnabled(currentProfile))
|
||||
summary = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateProfileIcon(profile: Int) {
|
||||
when (profile) {
|
||||
0 -> profilePref.setIcon(R.drawable.ic_profile_dynamic)
|
||||
1 -> profilePref.setIcon(R.drawable.ic_profile_movie)
|
||||
2 -> profilePref.setIcon(R.drawable.ic_profile_music)
|
||||
3 -> profilePref.setIcon(R.drawable.ic_profile_custom)
|
||||
else -> profilePref.setIcon(R.drawable.ic_dolby)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "DolbySettingsFragment"
|
||||
private val ATTRIBUTES_MEDIA = AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.build()
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
31
fingerprint/Android.bp
Normal file
31
fingerprint/Android.bp
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (C) 2022-2024 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
cc_library_static {
|
||||
name: "libudfpshandlerfactory",
|
||||
srcs: ["UdfpsHandler.cpp"],
|
||||
vendor: true,
|
||||
header_libs: ["xiaomifingerprint_headers"],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "xiaomifingerprint_headers",
|
||||
export_include_dirs: ["include"],
|
||||
vendor: true,
|
||||
header_libs: ["libhardware_headers"],
|
||||
export_header_lib_headers: ["libhardware_headers"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libudfps_extension.xiaomi",
|
||||
srcs: ["UdfpsExtension.cpp"],
|
||||
include_dirs: [
|
||||
"frameworks/native/services/surfaceflinger/CompositionEngine/include",
|
||||
],
|
||||
header_libs: [
|
||||
"generated_kernel_headers",
|
||||
],
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The LineageOS Project
|
||||
* Copyright (C) 2022,2025 The LineageOS Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -13,12 +13,14 @@ class UdfpsHandler {
|
||||
public:
|
||||
virtual ~UdfpsHandler() = default;
|
||||
|
||||
virtual void init(fingerprint_device_t* device) = 0;
|
||||
virtual void onFingerDown(uint32_t x, uint32_t y, float minor, float major) = 0;
|
||||
virtual void onFingerUp() = 0;
|
||||
virtual void init(fingerprint_device_t* device) {};
|
||||
virtual void onFingerDown(uint32_t x, uint32_t y, float minor, float major) {};
|
||||
virtual void onFingerUp() {};
|
||||
|
||||
virtual void onAcquired(int32_t result, int32_t vendorCode) = 0;
|
||||
virtual void cancel() = 0;
|
||||
virtual void onAcquired(int32_t result, int32_t vendorCode) {};
|
||||
virtual void onAuthenticationSucceeded() {};
|
||||
virtual void onAuthenticationFailed() {};
|
||||
virtual void cancel() {};
|
||||
};
|
||||
|
||||
struct UdfpsHandlerFactory {
|
||||
@@ -14,7 +14,6 @@ cc_binary {
|
||||
relative_install_path: "hw",
|
||||
srcs: [
|
||||
"BiometricsFingerprint.cpp",
|
||||
"UdfpsHandler.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
|
||||
@@ -31,24 +30,9 @@ cc_binary {
|
||||
"android.hardware.biometrics.fingerprint@2.3",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libudfpshandlerfactory",
|
||||
],
|
||||
|
||||
header_libs: ["xiaomifingerprint_headers"],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "xiaomifingerprint_headers",
|
||||
export_include_dirs: ["include"],
|
||||
vendor: true,
|
||||
header_libs: ["libhardware_headers"],
|
||||
export_header_lib_headers: ["libhardware_headers"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libudfps_extension.xiaomi",
|
||||
srcs: ["UdfpsExtension.cpp"],
|
||||
include_dirs: [
|
||||
"frameworks/native/services/surfaceflinger/CompositionEngine/include",
|
||||
],
|
||||
header_libs: [
|
||||
"generated_kernel_headers",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2022 The LineageOS Project
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
soong_config_module_type {
|
||||
name: "xiaomi_touch_hal_cc_defaults",
|
||||
module_type: "cc_defaults",
|
||||
config_namespace: "XIAOMI_TOUCH",
|
||||
value_variables: ["HIGH_TOUCH_POLLING_PATH"],
|
||||
properties: ["cppflags"],
|
||||
}
|
||||
|
||||
xiaomi_touch_hal_cc_defaults {
|
||||
name: "xiaomi_touch_hal_defaults",
|
||||
soong_config_variables: {
|
||||
HIGH_TOUCH_POLLING_PATH: {
|
||||
cppflags: ["-DHIGH_TOUCH_POLLING_PATH=\"%s\""],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "vendor.lineage.touch@1.0-service.xiaomi",
|
||||
defaults: [
|
||||
"hidl_defaults",
|
||||
"xiaomi_touch_hal_defaults",
|
||||
],
|
||||
vintf_fragments: ["vendor.lineage.touch@1.0-service.xiaomi.xml"],
|
||||
init_rc: ["vendor.lineage.touch@1.0-service.xiaomi.rc"],
|
||||
relative_install_path: "hw",
|
||||
proprietary: true,
|
||||
srcs: [
|
||||
"HighTouchPollingRate.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libhidlbase",
|
||||
"libutils",
|
||||
"vendor.lineage.touch@1.0",
|
||||
],
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user