28 Commits

Author SHA1 Message Date
pabloescobar-reborn
0420f3f245 configs: add dolby instance in FM 2025-05-19 04:43:07 +09:00
Dmitry
ea81a2acc2 dolby: add missing selinux policies 2025-05-13 21:26:09 +09:00
Ghosuto
fc013ffdef dolby: Update to use new tooltip position provider API 2025-05-03 19:17:11 +02:00
Bruno Martins
d69c31b038 dolby: Migrate MainSwitchBar and Switch to Material3
This follows Settings style updates for Android U.

Change-Id: Id6d3e7f193b6ef9fa6419d164265062328eb9170
2024-11-23 04:06:25 +05:30
Abhay Singh Gill
f479eef03b dolby: DolbyManager: Add custom profile
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-11-09 01:51:40 +05:30
Abhay Singh Gill
e8ebd395d1 dolby: DolbyManager: Add icons for dolby profiles
Also nuke voice profile and fixup some strings.

Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-11-09 01:51:34 +05:30
Abhay Singh Gill
296d340b6d dolby: DolbyManager: Make bass enhancer available on speakers as well
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-11-06 14:52:00 +05:30
Sarthak Roy
41a93dd519 dolby: DolbyManager: Fix building in Android 15
Change-Id: Ie4e312bce0232c7a55ed2c29c8442f886f5aabd9
2024-11-06 14:52:00 +05:30
Adithya R
750b00415a dolby: DolbyManager: Add intelligent equalizer setting
Move preference-related classes to a new package while we're at it,
to reduce code clutter.
Also fix graphical equlizer

Change-Id: I2430e8ab9b6758503ce1777ec985a3e400b55b8e
2024-11-06 14:52:00 +05:30
Aditya R
a5e3d9c63d dolby: Switch to DolbyManager
Based on existing dirac implementation and observing stock
sound effects app and daxservice.

History -
- Allow bass enhancer to use in speaker also
- Remove deprecated PlainTooltipBox
- Fix build with kotlinc 1.9.0
- Add launcher icon
- Introduce graphical equalizer
- Do not set volume leveler amount
- Restore all settings upon bootup
- Rewrite in Kotlin
- Restore dolby profile on audio changes
- Guard debug logging
- Implement profile-specific Dolby settings
- Remove play/pause hack while toggling Dolby
- Set proper summary for dolby settings
- Always refresh playback if status changed
- Introduce Dolby Atmos

Co-authored-by: Henrique Silva <jhenrique09.mcz@hotmail.com>
Co-authored-by: Pranav Vashi <neobuddy89@gmail.com>
Co-authored-by: Fabian Leutenegger <fabian.leutenegger@bluewin.ch>
Co-authored-by: basamaryan <basam.aryan@gmail.com>
Co-authored-by: Ghosuto <clash.raja10@gmail.com>
2024-11-06 14:52:00 +05:30
Abhay Singh Gill
f3fc9e46e2 dolby: Update from sssi-user 14 67.1.A.2.287 1 release-keys
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-11-06 14:51:56 +05:30
Abhay Singh Gill
939e58c22a dolby: Remove redundant audio codec flag
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-11-03 01:28:02 +05:30
Abhay Singh Gill
4ec5eeda3c dolby: Remove OnePlus specific headphone tunings
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-11 07:08:41 +05:30
Abhay Singh Gill
b2e635a522 dolby: Fixup soong modules config
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-11 07:08:25 +05:30
Abhay Singh Gill
42005cbb91 dolby: Build codec2 required packages
Incase someone ignores the README.

Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-10 19:48:50 +05:30
Abhay Singh Gill
3b0d7fd56d dolby: Update DaxUI
Now settings are restored after a reboot.

Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-09 05:41:56 +05:30
Abhay Singh Gill
01a21f5098 dolby: Nuke libeffectproxy.so
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-09 04:06:34 +05:30
Abhay Singh Gill
4dc3303a4c Reapply "dolby: Link dolby blobs against v33 libstagefright_foundation"
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-09 04:06:13 +05:30
Abhay Singh Gill
3fb780dd60 dolby: Kang libswdap.so from https://github.com/sony-sm8550/proprietary_vendor_sony_extra
Else the effects do not update properly.

Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-08 04:04:49 +05:30
Abhay Singh Gill
4be460186b dolby: Switch to sony dolby from pdx234
Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-08-08 02:32:28 +05:30
Abhay Singh Gill
d56e3b306b dolby: DaxUI: Override MusicFX and AudioFX 2024-03-19 05:58:35 +05:30
Abhay Singh Gill
5c1afecdb5 dolby: DaxUI: Fix clipped dialogue enhancer seekbar thumb 2024-03-19 03:02:51 +05:30
Fabian Leutenegger
8d0cda23b6 dolby: Link dolby blobs against v33 libstagefright_foundation
* fixes crashes and absurdly high CPU usage while using dolby
2024-03-15 16:05:38 +05:30
Abhay Singh Gill
3a6b0ad303 dolby: Remove unused blobs 2024-03-15 14:58:24 +05:30
Abhay Singh Gill
deb7018300 Revert "dolby: Update from OnePlus 8 (OOS-11)"
This reverts commit c527d9b162.
2024-03-15 14:56:55 +05:30
Abhay Singh Gill
c8c233e40d dolby: Add path variable 2024-03-15 14:01:44 +05:30
Abhay Singh Gill
5bd62626da dolby: Update readme 2024-03-15 14:01:41 +05:30
Abhay Singh Gill
f28d0a3718 dolby: DaxUI: Add more switches
For:-
• volume leveler
• surround virtualizer
• bass enhancer

Signed-off-by: Abhay Singh Gill <abhaygill017@gmail.com>
2024-03-15 13:49:23 +05:30
109 changed files with 1574 additions and 1692 deletions

1
.gitignore vendored
View File

@@ -1 +0,0 @@
.vscode/

View File

@@ -14,300 +14,3 @@
soong_namespace {
}
cc_prebuilt_library_shared {
name: "libdapparamstorage",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libdapparamstorage.so"],
shared_libs: ["libcutils", "libutils", "liblog", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libdlbdsservice",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libdlbdsservice.so"],
shared_libs: ["libutils", "libcutils", "libstagefright_foundation-v33", "liblog", "libxml2", "libcrypto", "libdapparamstorage", "libsqlite", "libhidlbase", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libdlbpreg",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libdlbpreg.so"],
shared_libs: ["liblog", "libutils", "libcutils", "libaudioutils", "libstagefright_foundation-v33", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libspatializerparamstorage",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libspatializerparamstorage.so"],
shared_libs: ["libcutils", "libutils", "liblog", "libxml2", "libdapparamstorage", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "vendor.dolby.hardware.dms@2.0-impl",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/vendor.dolby.hardware.dms@2.0-impl.so"],
shared_libs: ["libhidlbase", "libutils", "liblog", "libdapparamstorage", "libdlbdsservice", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "vendor.dolby.hardware.dms@2.0",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/vendor.dolby.hardware.dms@2.0.so"],
shared_libs: ["libhidlbase", "liblog", "libutils", "libcutils", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_binary {
name: "vendor.dolby.hardware.dms@2.0-service",
owner: "xiaomi",
target: {
android_arm64: {
srcs: ["proprietary/vendor/bin/hw/vendor.dolby.hardware.dms@2.0-service"],
shared_libs: ["liblog", "libutils", "libhidlbase", "libdapparamstorage", "libdlbdsservice", "vendor.dolby.hardware.dms@2.0", "vendor.dolby.hardware.dms@2.0-impl", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
strip: {
none: true,
},
prefer: true,
relative_install_path: "hw",
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libcodec2_soft_ac4dec",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libcodec2_soft_ac4dec.so"],
shared_libs: ["libhidlbase", "vendor.dolby.hardware.dms@2.0", "libdeccfg", "libbase", "libcodec2", "libcodec2_vndk", "libutils", "libcodec2_soft_common", "libcutils", "liblog", "libsfplugin_ccodec_utils", "libstagefright_foundation-v33", "libcodec2_store_dolby", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libcodec2_soft_ddpdec",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libcodec2_soft_ddpdec.so"],
shared_libs: ["libhidlbase", "vendor.dolby.hardware.dms@2.0", "libdeccfg", "libbase", "libcodec2", "libcodec2_vndk", "libutils", "libcodec2_soft_common", "libcutils", "liblog", "libsfplugin_ccodec_utils", "libstagefright_foundation-v33", "libcodec2_store_dolby", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libcodec2_store_dolby",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libcodec2_store_dolby.so"],
shared_libs: ["libdmabufheap", "libbase", "liblog", "libcodec2", "libcodec2_vndk", "libutils", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libdeccfg",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/libdeccfg.so"],
shared_libs: ["libhidlbase", "vendor.dolby.hardware.dms@2.0", "libdapparamstorage", "libcutils", "libutils", "liblog", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
prefer: true,
soc_specific: true,
}
cc_prebuilt_binary {
name: "vendor.dolby.media.c2@1.0-service",
owner: "xiaomi",
target: {
android_arm64: {
srcs: ["proprietary/vendor/bin/hw/vendor.dolby.media.c2@1.0-service"],
shared_libs: ["libbase", "liblog", "libcodec2", "libutils", "android.hardware.media.c2@1.0", "android.hardware.media.c2@1.1", "android.hardware.media.c2@1.2", "libcodec2_hidl@1.0", "libcodec2_hidl@1.1", "libcodec2_hidl@1.2", "libcodec2_vndk", "libhidlbase", "libavservices_minijail", "libbinder", "libcodec2_store_dolby", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
strip: {
none: true,
},
prefer: true,
relative_install_path: "hw",
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libdlbvol",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/soundfx/libdlbvol.so"],
shared_libs: ["liblog", "libutils", "libcutils", "libaudioutils", "libstagefright_foundation-v33", "libdlbpreg", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
relative_install_path: "soundfx",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libhwdap",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/soundfx/libhwdap.so"],
shared_libs: ["libspatializerparamstorage", "liblog", "libutils", "libcutils", "libaudioutils", "libdapparamstorage", "libhidlbase", "libdlbpreg", "vendor.dolby.hardware.dms@2.0", "libstagefright_foundation-v33", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
relative_install_path: "soundfx",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libswgamedap",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/soundfx/libswgamedap.so"],
shared_libs: ["libspatializerparamstorage", "liblog", "libutils", "libcutils", "libaudioutils", "libdapparamstorage", "libhidlbase", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
relative_install_path: "soundfx",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libswspatializer",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/soundfx/libswspatializer.so"],
shared_libs: ["liblog", "libutils", "libcutils", "libaudioutils", "libdapparamstorage", "libspatializerparamstorage", "libhidlbase", "libstagefright_foundation-v33", "libdlbpreg", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
relative_install_path: "soundfx",
prefer: true,
soc_specific: true,
}
cc_prebuilt_library_shared {
name: "libswvqe",
owner: "xiaomi",
strip: {
none: true,
},
target: {
android_arm64: {
srcs: ["proprietary/vendor/lib64/soundfx/libswvqe.so"],
shared_libs: ["libspatializerparamstorage", "liblog", "libutils", "libcutils", "libaudioutils", "libdapparamstorage", "libhidlbase", "vendor.dolby.hardware.dms@2.0", "libc++", "libc", "libm", "libdl", ],
},
},
compile_multilib: "64",
relative_install_path: "soundfx",
prefer: true,
soc_specific: true,
}

View File

@@ -6,7 +6,7 @@
//
android_app {
name: "XiaomiDolby",
name: "DolbyManager",
srcs: ["src/**/*.kt"],
resource_dirs: ["res"],
@@ -15,7 +15,7 @@ android_app {
system_ext_specific: true,
privileged: true,
overrides: ["MusicFX"],
overrides: ["MusicFX", "AudioFX"],
static_libs: [
"SettingsLib",
"SpaLib",
@@ -23,5 +23,6 @@ android_app {
"androidx.compose.material3_material3",
"androidx.compose.runtime_runtime",
"androidx.preference_preference",
"com.google.android.material_material",
],
}

View File

@@ -4,7 +4,7 @@
SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.aospa.dolby.xiaomi"
package="co.aospa.dolby"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -13,23 +13,20 @@
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:label="@string/dolby_title"
android:persistent="true"
android:directBootAware="true"
android:defaultToDeviceProtectedStorage="true"
android:theme="@style/Theme.SubSettingsBase.Expressive">
android:persistent="true">
<receiver
android:name=".BootCompletedReceiver"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name=".DolbySettingsActivity"
android:name=".DolbyActivity"
android:label="@string/dolby_title"
android:theme="@style/Theme.SubSettingsBase"
android:exported="true">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
@@ -47,12 +44,13 @@
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.sound" />
<meta-data android:name="com.android.settings.summary_uri"
android:value="content://co.aospa.dolby.xiaomi.summary/dolby" />
android:value="content://co.aospa.dolby.summary/dolby" />
</activity>
<activity
android:name=".geq.EqualizerActivity"
android:label="@string/dolby_preset"
android:theme="@style/Theme.SubSettingsBase"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -73,7 +71,7 @@
<provider
android:name=".SummaryProvider"
android:authorities="co.aospa.dolby.xiaomi.summary">
android:authorities="co.aospa.dolby.summary">
</provider>
</application>

View 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>

View 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>

View 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>

View 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>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingTop="@dimen/settingslib_switchbar_margin"
android:paddingBottom="@dimen/settingslib_switchbar_margin"
android:orientation="vertical">
<LinearLayout
android:id="@+id/frame"
android:minHeight="@dimen/settingslib_min_switch_bar_height"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingStart="@dimen/settingslib_switchbar_padding_left"
android:paddingEnd="@dimen/settingslib_switchbar_padding_right"
android:background="@drawable/settingslib_switch_bar_bg">
<TextView
android:id="@+id/switch_text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginEnd="@dimen/settingslib_switch_title_margin"
android:layout_marginVertical="@dimen/settingslib_switch_title_margin"
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceListItem"
android:hyphenationFrequency="normalFast"
android:lineBreakWordStyle="phrase"
style="@style/MainSwitchText.Settingslib" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:theme="@style/Theme.Material3.DynamicColors.DayNight" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<com.google.android.material.materialswitch.MaterialSwitch
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:theme="@style/Theme.Material3.DynamicColors.DayNight" />

View File

@@ -8,9 +8,8 @@
<!-- 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>
@@ -18,7 +17,6 @@
<item>0</item>
<item>1</item>
<item>2</item>
<item>8</item>
<item>3</item>
</string-array>
@@ -57,11 +55,37 @@
<item>40,24,8,8,8,-4,-16,-12,-8,-32,-56,-24,8,8,8,8,8,8,8,8</item>
</string-array>
<string-array name="dolby_dialogue_entries">
<item>@string/dolby_off</item>
<item>@string/dolby_low</item>
<item>@string/dolby_medium</item>
<item>@string/dolby_high</item>
<item>@string/dolby_max</item>
</string-array>
<string-array name="dolby_dialogue_values">
<item>0</item>
<item>2</item>
<item>6</item>
<item>9</item>
<item>12</item>
</string-array>
<string-array name="dolby_stereo_entries">
<item>@string/dolby_low</item>
<item>@string/dolby_high</item>
</string-array>
<string-array name="dolby_stereo_values">
<item>4</item>
<item>40</item>
</string-array>
<string-array name="dolby_ieq_entries">
<item>@string/dolby_off</item>
<item>@string/dolby_detailed</item>
<item>@string/dolby_balanced</item>
<item>@string/dolby_warm</item>
<item>@string/dolby_detailed</item>
</string-array>
<string-array name="dolby_ieq_values">

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023-25 Paranoid Android
Copyright (C) 2023-24 Paranoid Android
SPDX-License-Identifier: Apache-2.0
-->
<resources>
@@ -19,24 +19,20 @@
<string name="dolby_unknown">Unknown</string>
<string name="dolby_on_with_profile">On (%1$s)</string>
<string name="dolby_category_settings">Settings</string>
<string name="dolby_category_adv_settings">Advanced settings</string>
<string name="dolby_adv_settings_footer">Choose a different profile to show advanced settings.</string>
<string name="dolby_bass_enhancer">Bass enhancer</string>
<string name="dolby_dialogue_enhancer">Dialogue enhancer</string>
<string name="dolby_spk_virtualizer">Speaker surround virtualizer</string>
<string name="dolby_hp_virtualizer">Headphone surround virtualizer</string>
<string name="dolby_spk_virtualizer">Speaker virtualization</string>
<string name="dolby_hp_virtualizer">Headphone virtualization</string>
<string name="dolby_stereo_widening">Stereo widening</string>
<string name="dolby_volume_leveler">Volume leveler</string>
<string name="dolby_connect_headphones">Connect headphones</string>
<string name="dolby_reset_all">Reset profiles</string>
<string name="dolby_reset_all_message">This will reset all profiles to factory defaults.</string>
<string name="dolby_reset_all_toast">Succesfully reset all profiles</string>
<string name="dolby_strength">Strength</string>
<string name="dolby_reset_profile">Reset to defaults</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 -->
@@ -51,7 +47,6 @@
<string name="dolby_preset_country">Country</string>
<string name="dolby_preset_dance">Dance</string>
<string name="dolby_preset_metal">Metal</string>
<string name="dolby_preset_custom">Custom</string>
<!-- Dolby equalizer UI -->
<string name="dolby_geq_slider_label_gain">Gain</string>

View File

@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023-25 Paranoid Android
Copyright (C) 2023-24 Paranoid Android
SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/dolby_title">
<com.android.settingslib.widget.MainSwitchPreference
@@ -15,40 +14,25 @@
<ListPreference
android:key="dolby_profile"
android:dependency="dolby_enable"
android:entries="@array/dolby_profile_entries"
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:key="dolby_category_settings"
android:title="@string/dolby_category_settings"
android:dependency="dolby_enable">
android:title="@string/dolby_category_settings">
<Preference
android:key="dolby_preset"
android:title="@string/dolby_preset">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="co.aospa.dolby.xiaomi"
android:targetClass="co.aospa.dolby.xiaomi.geq.EqualizerActivity" />
android:targetPackage="co.aospa.dolby"
android:targetClass="co.aospa.dolby.geq.EqualizerActivity" />
</Preference>
<SwitchPreferenceCompat
android:key="dolby_bass"
android:title="@string/dolby_bass_enhancer" />
</PreferenceCategory>
<PreferenceCategory
android:key="dolby_category_adv_settings"
android:title="@string/dolby_category_adv_settings"
android:dependency="dolby_enable">
<co.aospa.dolby.xiaomi.preference.DolbyIeqPreference
<co.aospa.dolby.preference.DolbyIeqPreference
android:key="dolby_ieq"
android:entries="@array/dolby_ieq_entries"
android:entryValues="@array/dolby_ieq_values"
@@ -62,33 +46,31 @@
android:key="dolby_virtualizer"
android:title="@string/dolby_hp_virtualizer" />
<SeekBarPreference
android:key="dolby_stereo_widening"
android:title="@string/dolby_strength"
android:dependency="dolby_virtualizer"
android:min="@integer/stereo_widening_min"
android:max="@integer/stereo_widening_max"/>
<ListPreference
android:key="dolby_stereo"
android:entries="@array/dolby_stereo_entries"
android:entryValues="@array/dolby_stereo_values"
android:title="@string/dolby_stereo_widening"
android:dependency="dolby_virtualizer" />
<SwitchPreferenceCompat
android:key="dolby_dialogue_enabled"
<ListPreference
android:key="dolby_dialogue"
android:entries="@array/dolby_dialogue_entries"
android:entryValues="@array/dolby_dialogue_values"
android:title="@string/dolby_dialogue_enhancer" />
<SeekBarPreference
android:key="dolby_dialogue_amount"
android:title="@string/dolby_strength"
android:dependency="dolby_dialogue_enabled"
android:min="@integer/dialogue_enhancer_min"
android:max="@integer/dialogue_enhancer_max"/>
<SwitchPreferenceCompat
android:key="dolby_bass"
android:title="@string/dolby_bass_enhancer" />
<SwitchPreferenceCompat
android:key="dolby_volume"
android:title="@string/dolby_volume_leveler" />
<Preference
android:key="dolby_reset"
android:title="@string/dolby_reset_profile" />
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference
android:key="dolby_adv_settings_footer"
android:title="@string/dolby_adv_settings_footer"
android:selectable="false" />
</PreferenceScreen>

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
private const val TAG = "Dolby-Boot"
class BootCompletedReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "Received intent: ${intent.action}")
if (intent.action != Intent.ACTION_BOOT_COMPLETED) {
return
}
Log.i(TAG, "Boot completed, starting dolby")
DolbyController.getInstance(context).onBootCompleted()
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby
import android.os.Bundle
import co.aospa.dolby.preference.DolbySettingsFragment
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity
private const val TAG = "DolbyActivity"
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()
}
}

View File

@@ -4,11 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
package co.aospa.dolby
import android.media.audiofx.AudioEffect
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.dlog
import co.aospa.dolby.xiaomi.DolbyConstants.DsParam
import co.aospa.dolby.DolbyConstants.Companion.dlog
import co.aospa.dolby.DolbyConstants.DsParam
import java.util.UUID
class DolbyAudioEffect(priority: Int, audioSession: Int) : AudioEffect(

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
package co.aospa.dolby
import android.util.Log
@@ -27,16 +27,15 @@ class DolbyConstants {
}
companion object {
const val TAG = "XiaomiDolby"
const val TAG = "Dolby"
const val PREF_ENABLE = "dolby_enable"
const val PREF_PROFILE = "dolby_profile"
const val PREF_PRESET = "dolby_preset"
const val PREF_IEQ = "dolby_ieq"
const val PREF_HP_VIRTUALIZER = "dolby_virtualizer"
const val PREF_SPK_VIRTUALIZER = "dolby_spk_virtualizer"
const val PREF_STEREO_WIDENING = "dolby_stereo_widening"
const val PREF_DIALOGUE = "dolby_dialogue_enabled"
const val PREF_DIALOGUE_AMOUNT = "dolby_dialogue_amount"
const val PREF_STEREO = "dolby_stereo"
const val PREF_DIALOGUE = "dolby_dialogue"
const val PREF_BASS = "dolby_bass"
const val PREF_VOLUME = "dolby_volume"
const val PREF_RESET = "dolby_reset"
@@ -46,16 +45,15 @@ class DolbyConstants {
PREF_IEQ,
PREF_HP_VIRTUALIZER,
PREF_SPK_VIRTUALIZER,
PREF_STEREO_WIDENING,
PREF_STEREO,
PREF_DIALOGUE,
PREF_DIALOGUE_AMOUNT,
PREF_BASS,
PREF_VOLUME
)
fun dlog(tag: String, msg: String) {
if (Log.isLoggable(TAG, Log.DEBUG) || Log.isLoggable(tag, Log.DEBUG)) {
Log.d("$TAG-$tag", msg)
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(tag, msg)
}
}
}

View File

@@ -1,10 +1,10 @@
/*
* Copyright (C) 2023-25 Paranoid Android
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
package co.aospa.dolby
import android.content.Context
import android.media.AudioDeviceCallback
@@ -15,20 +15,16 @@ import android.media.AudioPlaybackConfiguration
import android.os.Handler
import android.util.Log
import androidx.preference.PreferenceManager
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.dlog
import co.aospa.dolby.xiaomi.DolbyConstants.DsParam
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.DolbyConstants.Companion.dlog
import co.aospa.dolby.DolbyConstants.DsParam
import co.aospa.dolby.R
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)
private val stereoWideningSupported =
context.getResources().getBoolean(R.bool.dolby_stereo_widening_supported)
private val volumeLevelerSupported =
context.getResources().getBoolean(R.bool.dolby_volume_leveler_supported)
// Restore current profile on every media session
private val playbackCallback = object : AudioPlaybackCallback() {
@@ -61,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)
}
}
@@ -95,30 +91,27 @@ internal class DolbyController private constructor(
}
init {
dlog(TAG, "initialized")
}
fun onBootCompleted() {
dlog(TAG, "onBootCompleted")
// Restore our main settings
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
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()
dlog(TAG, "initialized")
}
fun onBootCompleted () {
dlog(TAG, "onBootCompleted()")
// Migrate presets from credential protected storage if needed
maybeMigratePresets()
}
private fun restoreSettings(profile: Int) {
@@ -128,20 +121,6 @@ internal class DolbyController private constructor(
prefs.getString(DolbyConstants.PREF_PRESET, getPreset(profile))!!,
profile
)
setBassEnhancerEnabled(
prefs.getBoolean(DolbyConstants.PREF_BASS, getBassEnhancerEnabled(profile)),
profile
)
setVolumeLevelerEnabled(
// force disable if unsupported, else force enable on dynamic profile
volumeLevelerSupported && (profile == 0 ||
prefs.getBoolean(DolbyConstants.PREF_VOLUME, getVolumeLevelerEnabled(profile))),
profile
)
if (profile == 0) {
// below settings are not applicable for dynamic
return
}
setIeqPreset(
prefs.getString(
DolbyConstants.PREF_IEQ,
@@ -158,45 +137,27 @@ internal class DolbyController private constructor(
profile
)
setStereoWideningAmount(
prefs.getInt(
DolbyConstants.PREF_STEREO_WIDENING,
getStereoWideningAmount(profile)
prefs.getString(
DolbyConstants.PREF_STEREO,
getStereoWideningAmount(profile).toString()
)!!.toInt(),
profile
)
setDialogueEnhancerEnabled(
prefs.getBoolean(
DolbyConstants.PREF_DIALOGUE,
getDialogueEnhancerEnabled(profile)
),
profile
)
setDialogueEnhancerAmount(
prefs.getInt(
DolbyConstants.PREF_DIALOGUE_AMOUNT,
getDialogueEnhancerAmount(profile)
prefs.getString(
DolbyConstants.PREF_DIALOGUE,
getDialogueEnhancerAmount(profile).toString()
)!!.toInt(),
profile
)
}
private fun maybeMigratePresets() {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (prefs.getBoolean(PREF_KEY_PRESETS_MIGRATED, false)) {
return
}
val ceContext = context.createCredentialProtectedStorageContext()
val cePrefs = ceContext.getSharedPreferences(PREF_PRESETS, Context.MODE_PRIVATE)
if (cePrefs.all.isEmpty()) {
dlog(TAG, "no presets to migrate")
return
}
if (context.moveSharedPreferencesFrom(ceContext, PREF_PRESETS)) {
prefs.edit().putBoolean(PREF_KEY_PRESETS_MIGRATED, true).apply()
dlog(TAG, "presets migrated successfully")
} else {
Log.w(TAG, "failed to migrate presets")
}
setBassEnhancerEnabled(
prefs.getBoolean(DolbyConstants.PREF_BASS, getBassEnhancerEnabled(profile)),
profile
)
setVolumeLevelerEnabled(
prefs.getBoolean(DolbyConstants.PREF_VOLUME, getVolumeLevelerEnabled(profile)),
profile
)
}
private fun checkEffect() {
@@ -213,13 +174,6 @@ 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)
@@ -230,27 +184,13 @@ internal class DolbyController private constructor(
)[profileIndex]
}
fun resetProfileSpecificSettings(profile: Int = this.profile) {
dlog(TAG, "resetProfileSpecificSettings($profile)")
fun resetProfileSpecificSettings() {
dlog(TAG, "resetProfileSpecificSettings")
checkEffect()
dolbyEffect.resetProfileSpecificSettings(profile)
dolbyEffect.resetProfileSpecificSettings()
context.deleteSharedPreferences("profile_$profile")
}
fun resetAllProfiles() {
dlog(TAG, "resetAllProfiles")
checkEffect()
// Reset profile-specific settings
context.resources.getStringArray(R.array.dolby_profile_values)
.map { it.toInt() }
.forEach { resetProfileSpecificSettings(it) }
// Set default dynamic profile
profile = 0
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putString(DolbyConstants.PREF_PROFILE, "0")
.apply()
}
fun getPreset(profile: Int = this.profile): String {
val gains = dolbyEffect.getDapParameter(DsParam.GEQ_BAND_GAINS, profile)
return gains.joinToString(separator = ",").also {
@@ -262,20 +202,20 @@ 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)
}
fun getPresetName(): String {
val preset = getPreset()
val presets = context.resources.getStringArray(R.array.dolby_preset_values)
val userPresets = context.getSharedPreferences(PREF_PRESETS, Context.MODE_PRIVATE)
return if (presets.contains(preset)) {
context.resources.getStringArray(R.array.dolby_preset_entries)[presets.indexOf(preset)]
val presetIndex = presets.indexOf(getPreset())
return if (presetIndex == -1) {
"Custom"
} else {
userPresets.all.entries.firstOrNull { it.value == preset }?.key
?: context.getString(R.string.dolby_preset_custom)
context.resources.getStringArray(
R.array.dolby_preset_entries
)[presetIndex]
}
}
@@ -324,40 +264,29 @@ internal class DolbyController private constructor(
}
fun getStereoWideningAmount(profile: Int = this.profile) =
if (!stereoWideningSupported) {
0
} else {
dolbyEffect.getDapParameterInt(DsParam.STEREO_WIDENING_AMOUNT, profile).also {
dlog(TAG, "getStereoWideningAmount: $it")
}
dolbyEffect.getDapParameterInt(DsParam.STEREO_WIDENING_AMOUNT, profile).also {
dlog(TAG, "getStereoWideningAmount: $it")
}
fun setStereoWideningAmount(value: Int, profile: Int = this.profile) {
if (!stereoWideningSupported) return
dlog(TAG, "setStereoWideningAmount: $value")
checkEffect()
dolbyEffect.setDapParameter(DsParam.STEREO_WIDENING_AMOUNT, value, profile)
}
fun getDialogueEnhancerEnabled(profile: Int = this.profile) =
dolbyEffect.getDapParameterBool(DsParam.DIALOGUE_ENHANCER_ENABLE, profile).also {
dlog(TAG, "getDialogueEnhancerEnabled: $it")
}
fun setDialogueEnhancerEnabled(value: Boolean, profile: Int = this.profile) {
dlog(TAG, "setDialogueEnhancerEnabled: $value")
checkEffect()
dolbyEffect.setDapParameter(DsParam.DIALOGUE_ENHANCER_ENABLE, value, profile)
fun getDialogueEnhancerAmount(profile: Int = this.profile): Int {
val enabled = dolbyEffect.getDapParameterBool(DsParam.DIALOGUE_ENHANCER_ENABLE, profile)
val amount = if (enabled) {
dolbyEffect.getDapParameterInt(DsParam.DIALOGUE_ENHANCER_AMOUNT, profile)
} else 0
dlog(TAG, "getDialogueEnhancerAmount: enabled=$enabled amount=$amount")
return amount
}
fun getDialogueEnhancerAmount(profile: Int = this.profile) =
dolbyEffect.getDapParameterInt(DsParam.DIALOGUE_ENHANCER_AMOUNT, profile).also {
dlog(TAG, "getDialogueEnhancerAmount: $it")
}
fun setDialogueEnhancerAmount(value: Int, profile: Int = this.profile) {
dlog(TAG, "setDialogueEnhancerAmount: $value")
checkEffect()
dolbyEffect.setDapParameter(DsParam.DIALOGUE_ENHANCER_ENABLE, (value > 0), profile)
dolbyEffect.setDapParameter(DsParam.DIALOGUE_ENHANCER_AMOUNT, value, profile)
}
@@ -375,8 +304,6 @@ internal class DolbyController private constructor(
companion object {
private const val TAG = "DolbyController"
private const val EFFECT_PRIORITY = 100
private const val PREF_PRESETS = "presets"
private const val PREF_KEY_PRESETS_MIGRATED = "presets_migrated"
@Volatile
private var instance: DolbyController? = null

View File

@@ -4,13 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.preference
package co.aospa.dolby
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceDataStore
import androidx.preference.PreferenceManager
import co.aospa.dolby.xiaomi.DolbyConstants
class DolbyPreferenceStore(
private val context: Context
@@ -40,24 +39,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)

View File

@@ -0,0 +1,266 @@
/*
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby
import android.media.AudioAttributes
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
import android.media.AudioManager
import android.os.Bundle
import android.os.Handler
import android.widget.CompoundButton
import android.widget.Toast
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceChangeListener
import androidx.preference.PreferenceFragment
import androidx.preference.SwitchPreferenceCompat
import co.aospa.dolby.DolbyConstants.Companion.dlog
import co.aospa.dolby.R
import com.android.settingslib.widget.MainSwitchPreference
class DolbySettingsFragment : PreferenceFragment(),
OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
private val switchBar by lazy {
findPreference<MainSwitchPreference>(DolbyConstants.PREF_ENABLE)!!
}
private val profilePref by lazy {
findPreference<ListPreference>(DolbyConstants.PREF_PROFILE)!!
}
private val presetPref by lazy {
findPreference<Preference>(DolbyConstants.PREF_PRESET)!!
}
private val stereoPref by lazy {
findPreference<ListPreference>(DolbyConstants.PREF_STEREO)!!
}
private val dialoguePref by lazy {
findPreference<ListPreference>(DolbyConstants.PREF_DIALOGUE)!!
}
private val bassPref by lazy {
findPreference<SwitchPreferenceCompat>(DolbyConstants.PREF_BASS)!!
}
private val hpVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(DolbyConstants.PREF_HP_VIRTUALIZER)!!
}
private val spkVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(DolbyConstants.PREF_SPK_VIRTUALIZER)!!
}
private val volumePref by lazy {
findPreference<SwitchPreferenceCompat>(DolbyConstants.PREF_VOLUME)!!
}
private val resetPref by lazy {
findPreference<Preference>(DolbyConstants.PREF_RESET)!!
}
private val dolbyController by lazy { DolbyController.getInstance(context) }
private val audioManager by lazy { context.getSystemService(AudioManager::class.java) }
private val handler = Handler()
private var isOnSpeaker = true
set(value) {
if (field == value) return
field = value
dlog(TAG, "setIsOnSpeaker($value)")
updateProfileSpecificPrefs()
}
private val audioDeviceCallback = object : AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesAdded")
updateSpeakerState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesRemoved")
updateSpeakerState()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
dlog(TAG, "onCreatePreferences")
addPreferencesFromResource(R.xml.dolby_settings)
val profile = dolbyController.profile
preferenceManager.preferenceDataStore = DolbyPreferenceStore(context).also {
it.profile = profile
}
val dsOn = dolbyController.dsOn
switchBar.addOnSwitchChangeListener(this)
switchBar.setChecked(dsOn)
profilePref.onPreferenceChangeListener = this
profilePref.setEnabled(dsOn)
profilePref.apply {
if (entryValues.contains(profile.toString())) {
summary = "%s"
value = profile.toString()
} else {
summary = context.getString(R.string.dolby_unknown)
}
}
hpVirtPref.onPreferenceChangeListener = this
spkVirtPref.onPreferenceChangeListener = this
stereoPref.onPreferenceChangeListener = this
dialoguePref.onPreferenceChangeListener = this
bassPref.onPreferenceChangeListener = this
volumePref.onPreferenceChangeListener = this
resetPref.setOnPreferenceClickListener {
dolbyController.resetProfileSpecificSettings()
updateProfileSpecificPrefs()
Toast.makeText(
context,
context.getString(R.string.dolby_reset_profile_toast, profilePref.summary),
Toast.LENGTH_SHORT
).show()
true
}
audioManager!!.registerAudioDeviceCallback(audioDeviceCallback, handler)
updateSpeakerState()
updateProfileSpecificPrefs()
}
override fun onDestroyView() {
dlog(TAG, "onDestroyView")
audioManager!!.unregisterAudioDeviceCallback(audioDeviceCallback)
super.onDestroyView()
}
override fun onResume() {
super.onResume()
updateProfileSpecificPrefs()
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
dlog(TAG, "onPreferenceChange: key=${preference.key} value=$newValue")
when (preference.key) {
DolbyConstants.PREF_PROFILE -> {
val profile = newValue.toString().toInt()
dolbyController.profile = profile
(preferenceManager.preferenceDataStore as DolbyPreferenceStore).profile = profile
updateProfileSpecificPrefs()
}
DolbyConstants.PREF_SPK_VIRTUALIZER -> {
dolbyController.setSpeakerVirtEnabled(newValue as Boolean)
}
DolbyConstants.PREF_HP_VIRTUALIZER -> {
dolbyController.setHeadphoneVirtEnabled(newValue as Boolean)
}
DolbyConstants.PREF_STEREO -> {
dolbyController.setStereoWideningAmount(newValue.toString().toInt())
}
DolbyConstants.PREF_DIALOGUE -> {
dolbyController.setDialogueEnhancerAmount(newValue.toString().toInt())
}
DolbyConstants.PREF_BASS -> {
dolbyController.setBassEnhancerEnabled(newValue as Boolean)
}
DolbyConstants.PREF_VOLUME -> {
dolbyController.setVolumeLevelerEnabled(newValue as Boolean)
}
else -> return false
}
return true
}
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
dlog(TAG, "onCheckedChanged($isChecked)")
dolbyController.dsOn = isChecked
profilePref.setEnabled(isChecked)
updateProfileSpecificPrefs()
}
private fun updateSpeakerState() {
val device = audioManager!!.getDevicesForAttributes(ATTRIBUTES_MEDIA)[0]
isOnSpeaker = (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
}
private fun updateProfileSpecificPrefs() {
val unknownRes = context.getString(R.string.dolby_unknown)
val headphoneRes = context.getString(R.string.dolby_connect_headphones)
val dsOn = dolbyController.dsOn
val currentProfile = dolbyController.profile
dlog(
TAG, "updateProfileSpecificPrefs: dsOn=$dsOn currentProfile=$currentProfile"
+ " isOnSpeaker=$isOnSpeaker"
)
val enable = dsOn && (currentProfile != -1)
presetPref.setEnabled(enable)
spkVirtPref.setEnabled(enable)
dialoguePref.setEnabled(enable)
volumePref.setEnabled(enable)
resetPref.setEnabled(enable)
hpVirtPref.setEnabled(enable && !isOnSpeaker)
stereoPref.setEnabled(enable && !isOnSpeaker)
bassPref.setEnabled(enable)
if (!enable) return
presetPref.summary = dolbyController.getPresetName()
val deValue = dolbyController.getDialogueEnhancerAmount(currentProfile).toString()
dialoguePref.apply {
if (entryValues.contains(deValue)) {
summary = "%s"
value = deValue
} else {
summary = unknownRes
}
}
spkVirtPref.setChecked(dolbyController.getSpeakerVirtEnabled(currentProfile))
volumePref.setChecked(dolbyController.getVolumeLevelerEnabled(currentProfile))
// below prefs are not enabled on loudspeaker
if (isOnSpeaker) {
stereoPref.summary = headphoneRes
bassPref.summary = headphoneRes
hpVirtPref.summary = headphoneRes
return
}
val swValue = dolbyController.getStereoWideningAmount(currentProfile).toString()
stereoPref.apply {
if (entryValues.contains(swValue)) {
summary = "%s"
value = swValue
} else {
summary = unknownRes
}
}
bassPref.apply {
setChecked(dolbyController.getBassEnhancerEnabled(currentProfile))
summary = null
}
hpVirtPref.apply {
setChecked(dolbyController.getHeadphoneVirtEnabled(currentProfile))
summary = null
}
}
companion object {
private const val TAG = "DolbySettingsFragment"
private val ATTRIBUTES_MEDIA = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
}
}

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
package co.aospa.dolby
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
@@ -26,7 +26,7 @@ class DolbyTileService : TileService() {
override fun onClick() {
val isDsOn = dolbyController.dsOn
dolbyController.setDsOnAndPersist(!isDsOn) // toggle
dolbyController.dsOn = !isDsOn
qsTile.apply {
state = if (isDsOn) Tile.STATE_INACTIVE else Tile.STATE_ACTIVE
updateTile()

View File

@@ -5,14 +5,14 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
package co.aospa.dolby
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
import com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY
private const val KEY_DOLBY = "dolby"
@@ -58,14 +58,13 @@ class SummaryProvider : ContentProvider() {
): Int = 0
private fun getDolbySummary(): String {
val context = context!!
val dolbyController = DolbyController.getInstance(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)
}
}

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq
package co.aospa.dolby.geq
import android.os.Bundle
import androidx.activity.ComponentActivity
@@ -16,9 +16,9 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.compose.rememberNavController
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.xiaomi.geq.ui.EqualizerScreen
import co.aospa.dolby.xiaomi.geq.ui.EqualizerViewModel
import co.aospa.dolby.R
import co.aospa.dolby.geq.ui.EqualizerScreen
import co.aospa.dolby.geq.ui.EqualizerViewModel
import com.android.settingslib.spa.framework.compose.localNavController
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.scaffold.SettingsScaffold

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.data
package co.aospa.dolby.geq.data
data class BandGain(
val band: Int,

View File

@@ -4,15 +4,15 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.data
package co.aospa.dolby.geq.data
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_PRESET
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.dlog
import co.aospa.dolby.xiaomi.DolbyController
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.DolbyConstants.Companion.PREF_PRESET
import co.aospa.dolby.DolbyConstants.Companion.dlog
import co.aospa.dolby.DolbyController
import co.aospa.dolby.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow

View File

@@ -4,10 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.data
package co.aospa.dolby.geq.data
data class Preset(
var name: String? = null,
var name: String,
val bandGains: List<BandGain>,
var isUserDefined: Boolean = false,
var isMutated: Boolean = false

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
@@ -25,7 +25,7 @@ import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import co.aospa.dolby.xiaomi.geq.data.BandGain
import co.aospa.dolby.geq.data.BandGain
@Composable
fun BandGainSlider(

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -18,7 +18,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
@Composable
fun BandGainSliderLabels() {

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -16,27 +16,30 @@ 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(
viewModel: EqualizerViewModel,
modifier: Modifier = Modifier
) {
Surface(
modifier = Modifier
.fillMaxSize()
.padding(SettingsDimension.itemPadding)
.then(modifier),
color = MaterialTheme.colorScheme.settingsBackground
) {
Column(
verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxHeight()
SettingsTheme {
Surface(
modifier = Modifier
.fillMaxSize()
.padding(SettingsDimension.itemPadding)
.then(modifier),
color = MaterialTheme.colorScheme.background
) {
PresetSelector(viewModel = viewModel)
EqualizerBands(viewModel = viewModel)
Column(
verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxHeight()
) {
PresetSelector(viewModel = viewModel)
EqualizerBands(viewModel = viewModel)
}
}
}
}

View File

@@ -4,16 +4,16 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import co.aospa.dolby.xiaomi.geq.data.EqualizerRepository
import co.aospa.dolby.xiaomi.geq.data.Preset
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.dlog
import co.aospa.dolby.geq.data.EqualizerRepository
import co.aospa.dolby.geq.data.Preset
import co.aospa.dolby.DolbyConstants.Companion.dlog
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.drop
@@ -27,10 +27,10 @@ class EqualizerViewModel(
private val repository: EqualizerRepository
) : ViewModel() {
private val _presets = MutableStateFlow<List<Preset>>(repository.builtInPresets)
private val _presets = MutableStateFlow(repository.builtInPresets)
val presets = _presets.asStateFlow()
private val _preset = MutableStateFlow<Preset>(repository.defaultPreset)
private val _preset = MutableStateFlow(repository.defaultPreset)
val preset = _preset.asStateFlow()
private var presetRestored = false
@@ -52,7 +52,10 @@ class EqualizerViewModel(
val bandGains = repository.getBandGains()
_preset.value = _presets.value.find {
bandGains == it.bandGains
} ?: Preset(bandGains = bandGains)
} ?: Preset(
name = "Custom",
bandGains = bandGains
)
dlog(TAG, "restored preset: ${_preset.value}")
presetRestored = true
}
@@ -98,8 +101,7 @@ class EqualizerViewModel(
dlog(TAG, "setGain($index, $gain)")
_preset.value = _preset.value.run {
copy(
// if we're modifying predefined preset, set name to null so UI shows "Custom"
name = if (!isUserDefined) null else name,
name = if (!isUserDefined) "Custom" else name,
bandGains = bandGains
.toMutableList()
// create a new object to ensure the flow emits an update.
@@ -115,7 +117,7 @@ class EqualizerViewModel(
// Ensure we don't have another preset with the same name
return if (
_presets.value
.any { it.name!!.equals(name.trim(), ignoreCase = true) }
.any { it.name.equals(name.trim(), ignoreCase = true) }
) {
PresetNameValidationError.NAME_EXISTS
} else if (name.length > 50) {

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@@ -21,7 +21,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
@Composable
fun PresetNameDialog(

View File

@@ -4,11 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
enum class PresetNameValidationError {
NAME_EXISTS,

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
@@ -33,7 +33,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -61,7 +61,7 @@ fun PresetSelector(viewModel: EqualizerViewModel) {
.weight(1f)
) {
TextField(
value = currentPreset.name ?: stringResource(id = R.string.dolby_preset_custom),
value = currentPreset.name,
onValueChange = { },
readOnly = true,
label = {
@@ -86,7 +86,7 @@ fun PresetSelector(viewModel: EqualizerViewModel) {
) {
presets.forEach { preset ->
DropdownMenuItem(
text = { Text(text = preset.name!!) },
text = { Text(text = preset.name) },
onClick = {
viewModel.setPreset(preset)
expanded = false
@@ -147,7 +147,7 @@ fun PresetSelector(viewModel: EqualizerViewModel) {
if (showRenamePresetDialog) {
PresetNameDialog(
title = stringResource(id = R.string.dolby_geq_rename_preset),
presetName = currentPreset.name!!,
presetName = currentPreset.name,
onPresetNameSet = {
return@PresetNameDialog viewModel.renamePreset(
preset = currentPreset,

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.geq.ui
package co.aospa.dolby.geq.ui
import androidx.compose.foundation.layout.size
import androidx.compose.material3.ExperimentalMaterial3Api

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.preference
package co.aospa.dolby.preference
import android.content.Context
import android.util.AttributeSet
@@ -13,7 +13,7 @@ import android.widget.ImageView
import androidx.appcompat.content.res.AppCompatResources
import androidx.preference.ListPreference
import androidx.preference.PreferenceViewHolder
import co.aospa.dolby.xiaomi.R
import co.aospa.dolby.R
// Preference with icon on the right side
class DolbyIeqPreference(
@@ -32,11 +32,14 @@ class DolbyIeqPreference(
iconView.setImageDrawable(icon)
}
private fun getIeqIconResId(): Int =
when (findIndexOfValue(value)) {
1 -> R.drawable.ic_ieq_detailed
2 -> R.drawable.ic_ieq_balanced
3 -> R.drawable.ic_ieq_warm
else -> R.drawable.ic_ieq_off
private fun getIeqIconResId(): Int {
val ieqValue = value?.toIntOrNull() ?: 0
return when (ieqValue) {
0 -> R.drawable.ic_ieq_off
1 -> R.drawable.ic_ieq_balanced
2 -> R.drawable.ic_ieq_warm
3 -> R.drawable.ic_ieq_detailed
else -> 0 // should never hit this!
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2024 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.preference
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceDataStore
import androidx.preference.PreferenceManager
import co.aospa.dolby.DolbyConstants
class DolbyPreferenceStore(
private val context: Context
) : PreferenceDataStore() {
private val defaultSharedPrefs by lazy {
PreferenceManager.getDefaultSharedPreferences(context)
}
private lateinit var profileSharedPrefs: SharedPreferences
var profile = 0
set(value) {
field = value
profileSharedPrefs = context.getSharedPreferences(
"profile_$value",
Context.MODE_PRIVATE
)
}
private fun getSharedPreferences(key: String) =
if (DolbyConstants.PROFILE_SPECIFIC_PREFS.contains(key)) {
profileSharedPrefs
} else {
defaultSharedPrefs
}
override fun putBoolean(key: String, value: Boolean) =
getSharedPreferences(key).edit()
.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()
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()
override fun getString(key: String, defValue: String?) =
getSharedPreferences(key).getString(key, defValue)
}

View File

@@ -0,0 +1,306 @@
/*
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.preference
import android.media.AudioAttributes
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
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
import androidx.preference.Preference.OnPreferenceChangeListener
import androidx.preference.PreferenceFragment
import androidx.preference.SwitchPreferenceCompat
import co.aospa.dolby.DolbyConstants
import co.aospa.dolby.DolbyConstants.Companion.PREF_BASS
import co.aospa.dolby.DolbyConstants.Companion.PREF_DIALOGUE
import co.aospa.dolby.DolbyConstants.Companion.PREF_ENABLE
import co.aospa.dolby.DolbyConstants.Companion.PREF_HP_VIRTUALIZER
import co.aospa.dolby.DolbyConstants.Companion.PREF_IEQ
import co.aospa.dolby.DolbyConstants.Companion.PREF_PRESET
import co.aospa.dolby.DolbyConstants.Companion.PREF_PROFILE
import co.aospa.dolby.DolbyConstants.Companion.PREF_RESET
import co.aospa.dolby.DolbyConstants.Companion.PREF_SPK_VIRTUALIZER
import co.aospa.dolby.DolbyConstants.Companion.PREF_STEREO
import co.aospa.dolby.DolbyConstants.Companion.PREF_VOLUME
import co.aospa.dolby.DolbyConstants.Companion.dlog
import co.aospa.dolby.DolbyController
import co.aospa.dolby.R
import com.android.settingslib.widget.MainSwitchPreference
class DolbySettingsFragment : PreferenceFragment(),
OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
private val switchBar by lazy {
findPreference<MainSwitchPreference>(PREF_ENABLE)!!
}
private val profilePref by lazy {
findPreference<ListPreference>(PREF_PROFILE)!!
}
private val presetPref by lazy {
findPreference<Preference>(PREF_PRESET)!!
}
private val ieqPref by lazy {
findPreference<DolbyIeqPreference>(PREF_IEQ)!!
}
private val stereoPref by lazy {
findPreference<ListPreference>(PREF_STEREO)!!
}
private val dialoguePref by lazy {
findPreference<ListPreference>(PREF_DIALOGUE)!!
}
private val bassPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_BASS)!!
}
private val hpVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_HP_VIRTUALIZER)!!
}
private val spkVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_SPK_VIRTUALIZER)!!
}
private val volumePref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_VOLUME)!!
}
private val resetPref by lazy {
findPreference<Preference>(PREF_RESET)!!
}
private val dolbyController by lazy { DolbyController.getInstance(context) }
private val audioManager by lazy { context.getSystemService(AudioManager::class.java) }
private val handler = Handler()
private var isOnSpeaker = true
set(value) {
if (field == value) return
field = value
dlog(TAG, "setIsOnSpeaker($value)")
updateProfileSpecificPrefs()
}
private val audioDeviceCallback = object : AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesAdded")
updateSpeakerState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesRemoved")
updateSpeakerState()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
dlog(TAG, "onCreatePreferences")
addPreferencesFromResource(R.xml.dolby_settings)
val profile = dolbyController.profile
preferenceManager.preferenceDataStore = DolbyPreferenceStore(context).also {
it.profile = profile
}
val dsOn = dolbyController.dsOn
switchBar.addOnSwitchChangeListener(this)
switchBar.setChecked(dsOn)
profilePref.onPreferenceChangeListener = this
updateProfileIcon(profile)
profilePref.setEnabled(dsOn)
profilePref.apply {
if (entryValues.contains(profile.toString())) {
summary = "%s"
value = profile.toString()
} else {
summary = context.getString(R.string.dolby_unknown)
}
}
hpVirtPref.onPreferenceChangeListener = this
spkVirtPref.onPreferenceChangeListener = this
stereoPref.onPreferenceChangeListener = this
dialoguePref.onPreferenceChangeListener = this
bassPref.onPreferenceChangeListener = this
volumePref.onPreferenceChangeListener = this
ieqPref.onPreferenceChangeListener = this
resetPref.setOnPreferenceClickListener {
dolbyController.resetProfileSpecificSettings()
updateProfileSpecificPrefs()
Toast.makeText(
context,
context.getString(R.string.dolby_reset_profile_toast, profilePref.summary),
Toast.LENGTH_SHORT
).show()
true
}
audioManager!!.registerAudioDeviceCallback(audioDeviceCallback, handler)
updateSpeakerState()
updateProfileSpecificPrefs()
}
override fun onDestroyView() {
dlog(TAG, "onDestroyView")
audioManager!!.unregisterAudioDeviceCallback(audioDeviceCallback)
super.onDestroyView()
}
override fun onResume() {
super.onResume()
updateProfileSpecificPrefs()
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
dlog(TAG, "onPreferenceChange: key=${preference.key} value=$newValue")
when (preference.key) {
PREF_PROFILE -> {
val profile = newValue.toString().toInt()
dolbyController.profile = profile
(preferenceManager.preferenceDataStore as DolbyPreferenceStore).profile = profile
updateProfileIcon(profile)
updateProfileSpecificPrefs()
}
PREF_SPK_VIRTUALIZER -> {
dolbyController.setSpeakerVirtEnabled(newValue as Boolean)
}
PREF_HP_VIRTUALIZER -> {
dolbyController.setHeadphoneVirtEnabled(newValue as Boolean)
}
PREF_STEREO -> {
dolbyController.setStereoWideningAmount(newValue.toString().toInt())
}
PREF_DIALOGUE -> {
dolbyController.setDialogueEnhancerAmount(newValue.toString().toInt())
}
PREF_BASS -> {
dolbyController.setBassEnhancerEnabled(newValue as Boolean)
}
PREF_VOLUME -> {
dolbyController.setVolumeLevelerEnabled(newValue as Boolean)
}
PREF_IEQ -> {
dolbyController.setIeqPreset(newValue.toString().toInt())
}
else -> return false
}
return true
}
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
dlog(TAG, "onCheckedChanged($isChecked)")
dolbyController.dsOn = isChecked
profilePref.setEnabled(isChecked)
updateProfileSpecificPrefs()
}
private fun updateSpeakerState() {
val device = audioManager!!.getDevicesForAttributes(ATTRIBUTES_MEDIA)[0]
isOnSpeaker = (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
}
private fun updateProfileSpecificPrefs() {
val unknownRes = context.getString(R.string.dolby_unknown)
val headphoneRes = context.getString(R.string.dolby_connect_headphones)
val dsOn = dolbyController.dsOn
val currentProfile = dolbyController.profile
dlog(
TAG, "updateProfileSpecificPrefs: dsOn=$dsOn currentProfile=$currentProfile"
+ " isOnSpeaker=$isOnSpeaker"
)
val enable = dsOn && (currentProfile != -1)
presetPref.setEnabled(enable)
spkVirtPref.setEnabled(enable)
ieqPref.setEnabled(enable)
dialoguePref.setEnabled(enable)
volumePref.setEnabled(enable)
bassPref.setEnabled(enable)
resetPref.setEnabled(enable)
hpVirtPref.setEnabled(enable && !isOnSpeaker)
stereoPref.setEnabled(enable && !isOnSpeaker)
if (!enable) return
presetPref.summary = dolbyController.getPresetName()
val ieqValue = dolbyController.getIeqPreset(currentProfile)
ieqPref.apply {
if (entryValues.contains(ieqValue.toString())) {
summary = "%s"
value = ieqValue.toString()
} else {
summary = unknownRes
}
}
val deValue = dolbyController.getDialogueEnhancerAmount(currentProfile).toString()
dialoguePref.apply {
if (entryValues.contains(deValue)) {
summary = "%s"
value = deValue
} else {
summary = unknownRes
}
}
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
hpVirtPref.summary = headphoneRes
return
}
val swValue = dolbyController.getStereoWideningAmount(currentProfile).toString()
stereoPref.apply {
if (entryValues.contains(swValue)) {
summary = "%s"
value = swValue
} else {
summary = unknownRes
}
}
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()
}
}

View File

@@ -1,9 +1,9 @@
AOSPA Dolby
Sony Dolby
==============
Getting Started
---------------
For dolby media codecs to work add this line in your media codecs config (should be in vendor partition) :-
For dolby media codecs to work add this line in your media codecs config (should be in vendor partition) and make sure your device supports c2 codecs. :-
```bash
<Include href="media_codecs_dolby_audio.xml" />
@@ -42,20 +42,4 @@ DEVICE_MANIFEST_FILE +=
The only change done above is changing := symbol to += so that manifest can't be overriden from device tree in BoardConfig makefile.
At the end an example commit to properly implement it in your device tree could be :-
[**1**] https://github.com/Spanish-or-Vanish/android_device_xiaomi_sm8350-common/commit/8ece9a976087ed03f1adb447d0ac2a3f5f1a0d3c
[**2**] https://github.com/Spanish-or-Vanish/android_device_xiaomi_sm8350-common/commit/2bdd047bfb5f23bd02e6d4db601a97c27e1506f9
#### Tip pick anyone for Reference:
https://dumps.tadiphone.dev/dumps/xiaomi/vili/-/blob/missi_phone_global-user-14-UKQ1.231207.002-V816.0.5.0.UKDMIXM-release-keys/aosp-device-tree/proprietary-files.txt#L2072
https://github.com/Spanish-or-Vanish/android_device_xiaomi_sm8350-common/commit/6a8f6aae347f9f864f17f2dfa5d541f83ab5b170
https://github.com/Spanish-or-Vanish/android_device_xiaomi_sm8350-common/commit/5c593cbd2c19d571b7e62ea4bd6b8c864a4e1d9e
# Credits:
* [**HELLBOY017**](https://github.com/HELLBOY017)
* [**adithya2306**](https://github.com/adithya2306)
* [**johnmart19**](https://github.com/johnmart19)
* [**userariii**](https://github.com/userariii)
* [**saku-bruh**](https://github.com/saku-bruh)
* [**ahnet-69 · he/him**](https://github.com/ahnet-69)
https://github.com/Neoteric-OS/device_nothing_Pong/commit/cefa46567c04770e492351e51dd96cfae80e34fb

View File

@@ -1,10 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := RemovePackagesDolby
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_OVERRIDES_PACKAGES += Music MusicFX AudioFX
LOCAL_UNINSTALLABLE_MODULE := true
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := /dev/null
include $(BUILD_PREBUILT)

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Feature for devices with a head tracker sensor. -->
<permissions>
<feature name="android.hardware.sensor.dynamic.head_tracker" />
</permissions>

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
<!-- Copyright 2016 The Android Open Source Project
This program is protected under international and U.S. copyright laws as
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 was modified by Dolby Laboratories, Inc. The portions of the
code that are surrounded by "DOLBY..." are copyrighted and
licensed separately, as follows:
(C) 2018 Dolby Laboratories, Inc.
All rights reserved.
This program is protected under international and U.S. Copyright laws as
an unpublished work. This program is confidential and proprietary to the
copyright owners. Reproduction or disclosure, in whole or in part, or the
production of derivative works therefrom without the express permission of
the copyright owners is prohibited.
Copyright (C) 2020-2021 by Dolby Laboratories,
All rights reserved.
-->
<Included>
@@ -33,16 +49,7 @@
<Limit name="sample-rate" ranges="48000" />
<Limit name="bitrate" range="32000-6144000" />
</Type>
<Attribute name="software-codec" />
</MediaCodec>
<!-- DOLBY_UDC END -->
<!-- DOLBY_AC4 -->
<!-- <MediaCodec name="c2.dolby.ac4.decoder" type="audio/ac4">
<Alias name="OMX.dolby.ac4.decoder" />
<Limit name="channel-count" max="16" />
<Limit name="sample-rate" ranges="48000" />
<Limit name="bitrate" range="16000-2688000" />
</MediaCodec> -->
<!-- DOLBY_AC4 END -->
</Decoders>
</Included>

View File

@@ -0,0 +1,19 @@
<compatibility-matrix version="4.0" type="framework">
<hal format="hidl" optional="true">
<name>vendor.dolby.hardware.dms</name>
<version>2.0</version>
<interface>
<name>IDms</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.media.c2</name>
<version>1.0</version>
<interface>
<name>IComponentStore</name>
<instance>dolby</instance>
<instance>default1</instance>
</interface>
</hal>
</compatibility-matrix>

View File

@@ -0,0 +1,11 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>vendor.dolby.hardware.dms</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>IDms</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View File

@@ -0,0 +1,19 @@
<!--
This program is protected under international and U.S. copyright laws as
an unpublished work. This program is confidential and proprietary to the
copyright owners. Reproduction or disclosure, in whole or in part, or the
production of derivative works therefrom without the express permission of
the copyright owners is prohibited.
Copyright (C) 2020-2021 by Dolby Laboratories,
All rights reserved.
-->
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.media.c2</name>
<transport>hwbinder</transport>
<fqname>@1.0::IComponentStore/default1</fqname>
</hal>
</manifest>

140
dolby.mk
View File

@@ -21,111 +21,63 @@ DOLBY_PATH := hardware/dolby
PRODUCT_SOONG_NAMESPACES += \
$(DOLBY_PATH)
# Enable codec support
AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := true
# Build codec2 packages
PRODUCT_PACKAGES += \
libavservices_minijail.vendor \
libcodec2_hidl@1.2.vendor \
libcodec2_soft_common.vendor
# SEPolicy
BOARD_VENDOR_SEPOLICY_DIRS += $(DOLBY_PATH)/sepolicy/vendor
# HIDL
DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += $(DOLBY_PATH)/configs/vintf/dolby_framework_matrix.xml
DEVICE_MANIFEST_FILE += \
$(DOLBY_PATH)/configs/vintf/vendor.dolby.hardware.dms@2.0-service.xml \
$(DOLBY_PATH)/configs/vintf/vendor.dolby.media.c2@1.0-service.xml
# Configs
PRODUCT_COPY_FILES += \
$(DOLBY_PATH)/configs/dax-default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/dolby/dax-default.xml \
$(DOLBY_PATH)/configs/media_codecs_dolby_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_dolby_audio.xml
$(DOLBY_PATH)/configs/dax/dax-default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/dolby/dax-default.xml \
$(DOLBY_PATH)/configs/media/media_codecs_dolby_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_dolby_audio.xml
# Dolby VNDK libs
PRODUCT_PACKAGES += \
libstagefright_foundation-v33
PRODUCT_PACKAGES += \
libshim_dolby
# Init
PRODUCT_PACKAGES += \
init.dolby.rc
# Overlays
PRODUCT_PACKAGES += \
DolbyFrameworksResCommon
# Dolby Spatial Audio
PRODUCT_COPY_FILES += \
$(DOLBY_PATH)/configs/android.hardware.sensor.dynamic.head_tracker.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.dynamic.head_tracker.xml \
prebuilts/vndk/v33/arm/arch-arm-armv7-a-neon/shared/vndk-core/libstagefright_foundation.so:$(TARGET_COPY_OUT_VENDOR)/lib/libstagefright_foundation-v33.so \
prebuilts/vndk/v33/arm64/arch-arm64-armv8-a/shared/vndk-core/libstagefright_foundation.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libstagefright_foundation-v33.so
# Dolby Spatial Audio: optimize spatializer effect
PRODUCT_PROPERTY_OVERRIDES += \
audio.spatializer.effect.util_clamp_min=300
# Dolby Spatial Audio: declare use of spatial audio
PRODUCT_PROPERTY_OVERRIDES += \
ro.audio.spatializer_enabled=true \
ro.audio.headtracking_enabled=true \
ro.audio.spatializer_transaural_enabled_default=false \
persist.vendor.audio.spatializer.speaker_enabled=true \
# Dolby Spatial Audio Proprietary blobs
PRODUCT_PACKAGES += \
libspatializerparamstorage \
libswspatializer
# Media (C2)
PRODUCT_PACKAGES += \
android.hardware.media.c2@1.0.vendor \
android.hardware.media.c2@1.1.vendor \
android.hardware.media.c2@1.2.vendor \
libcodec2_hidl@1.2.vendor \
libsfplugin_ccodec_utils.vendor \
libcodec2_soft_common.vendor
# Codec2 Props
# Dolby
PRODUCT_VENDOR_PROPERTIES += \
vendor.audio.c2.preferred=true \
debug.c2.use_dmabufheaps=1 \
vendor.qc2audio.suspend.enabled=true \
vendor.qc2audio.per_frame.flac.dec.enabled=true
ro.vendor.dolby.dax.version=DAX3_3.7.0.8_r1
# Dolby Props
PRODUCT_VENDOR_PROPERTIES += \
ro.vendor.dolby.dax.version=DAX3_3.7.0.8_r1 \
vendor.audio.dolby.ds2.hardbypass=false \
vendor.audio.dolby.ds2.enabled=false
# Remove Packages for Dolby Support
# DolbyManager
PRODUCT_PACKAGES += \
RemovePackagesDolby
DolbyManager
# XiaomiDolby
PRODUCT_PACKAGES += \
XiaomiDolby
# Dolby Proprietary blobs
# Proprietary-files
PRODUCT_COPY_FILES += \
$(DOLBY_PATH)/proprietary/vendor/etc/init/vendor.dolby.hardware.dms@2.0-service.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/vendor.dolby.hardware.dms@2.0-service.rc
PRODUCT_PACKAGES += \
libdapparamstorage \
libdlbdsservice \
libdlbpreg \
vendor.dolby.hardware.dms@2.0-impl \
vendor.dolby.hardware.dms@2.0 \
vendor.dolby.hardware.dms@2.0-service
# Codec2 (Dolby)
PRODUCT_COPY_FILES += \
$(DOLBY_PATH)/proprietary/vendor/etc/init/vendor.dolby.media.c2@1.0-service.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/vendor.dolby.media.c2@1.0-service.rc
PRODUCT_PACKAGES += \
libcodec2_soft_ac4dec \
libcodec2_soft_ddpdec \
libcodec2_store_dolby \
libdeccfg \
vendor.dolby.media.c2@1.0-service
# Dolby SoundFX Blobs
PRODUCT_PACKAGES += \
libdlbvol \
libhwdap \
libswgamedap \
libswvqe
$(DOLBY_PATH)/proprietary/vendor/bin/hw/vendor.dolby.hardware.dms@2.0-service:$(TARGET_COPY_OUT_VENDOR)/bin/hw/vendor.dolby.hardware.dms@2.0-service \
$(DOLBY_PATH)/proprietary/vendor/bin/hw/vendor.dolby.media.c2@1.0-service:$(TARGET_COPY_OUT_VENDOR)/bin/hw/vendor.dolby.media.c2@1.0-service \
$(DOLBY_PATH)/proprietary/vendor/etc/init/vendor.dolby.hardware.dms@2.0-service.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/vendor.dolby.hardware.dms@2.0-service.rc \
$(DOLBY_PATH)/proprietary/vendor/etc/init/vendor.dolby.media.c2@1.0-service.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/vendor.dolby.media.c2@1.0-service.rc \
$(DOLBY_PATH)/proprietary/vendor/lib/libdapparamstorage.so:$(TARGET_COPY_OUT_VENDOR)/lib/libdapparamstorage.so \
$(DOLBY_PATH)/proprietary/vendor/lib/libdlbpreg.so:$(TARGET_COPY_OUT_VENDOR)/lib/libdlbpreg.so \
$(DOLBY_PATH)/proprietary/vendor/lib/soundfx/libdlbvol.so:$(TARGET_COPY_OUT_VENDOR)/lib/soundfx/libdlbvol.so \
$(DOLBY_PATH)/proprietary/vendor/lib/soundfx/libswdap.so:$(TARGET_COPY_OUT_VENDOR)/lib/soundfx/libswdap.so \
$(DOLBY_PATH)/proprietary/vendor/lib/soundfx/libswgamedap.so:$(TARGET_COPY_OUT_VENDOR)/lib/soundfx/libswgamedap.so \
$(DOLBY_PATH)/proprietary/vendor/lib/soundfx/libswvqe.so:$(TARGET_COPY_OUT_VENDOR)/lib/soundfx/libswvqe.so \
$(DOLBY_PATH)/proprietary/vendor/lib/vendor.dolby.hardware.dms@2.0.so:$(TARGET_COPY_OUT_VENDOR)/lib/vendor.dolby.hardware.dms@2.0.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libcodec2_soft_ac4dec.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libcodec2_soft_ac4dec.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libcodec2_soft_ddpdec.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libcodec2_soft_ddpdec.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libcodec2_soft_dolby.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libcodec2_soft_dolby.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libcodec2_store_dolby.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libcodec2_store_dolby.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libdapparamstorage.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libdapparamstorage.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libdeccfg.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libdeccfg.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libdlbdsservice.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libdlbdsservice.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/libdlbpreg.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libdlbpreg.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/soundfx/libdlbvol.so:$(TARGET_COPY_OUT_VENDOR)/lib64/soundfx/libdlbvol.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/soundfx/libswdap.so:$(TARGET_COPY_OUT_VENDOR)/lib64/soundfx/libswdap.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/soundfx/libswgamedap.so:$(TARGET_COPY_OUT_VENDOR)/lib64/soundfx/libswgamedap.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/soundfx/libswvqe.so:$(TARGET_COPY_OUT_VENDOR)/lib64/soundfx/libswvqe.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/vendor.dolby.hardware.dms@2.0-impl.so:$(TARGET_COPY_OUT_VENDOR)/lib64/vendor.dolby.hardware.dms@2.0-impl.so \
$(DOLBY_PATH)/proprietary/vendor/lib64/vendor.dolby.hardware.dms@2.0.so:$(TARGET_COPY_OUT_VENDOR)/lib64/vendor.dolby.hardware.dms@2.0.so

View File

@@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M653,752L565,840L480,755L568,667Q564,656 562,644Q560,632 560,620Q560,562 601,521Q642,480 700,480Q718,480 735,484.5Q752,489 767,497L672,592L728,648L823,554Q831,569 835.5,585.5Q840,602 840,620Q840,678 799,719Q758,760 700,760Q687,760 675.5,758Q664,756 653,752ZM831,400L748,400Q722,312 649,256Q576,200 480,200Q363,200 281.5,281.5Q200,363 200,480Q200,552 232.5,612Q265,672 320,710L320,600L400,600L400,840L160,840L160,760L254,760Q192,710 156,637.5Q120,565 120,480Q120,405 148.5,339.5Q177,274 225.5,225.5Q274,177 339.5,148.5Q405,120 480,120Q609,120 706.5,199.5Q804,279 831,400Z"/>
</vector>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023-25 Paranoid Android
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- Whether stereo widening levels are supported -->
<bool name="dolby_stereo_widening_supported">true</bool>
<!-- Whether volume leveler is supported -->
<bool name="dolby_volume_leveler_supported">true</bool>
</resources>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2025 Paranoid Android
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- Stereo widening amount -->
<integer name="stereo_widening_min">4</integer>
<integer name="stereo_widening_max">64</integer>
<!-- Dialogue enhancer amount -->
<integer name="dialogue_enhancer_min">1</integer>
<integer name="dialogue_enhancer_max">12</integer>
</resources>

View File

@@ -1,31 +0,0 @@
/*
* Copyright (C) 2023-24 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
private const val TAG = "XiaomiDolby-Boot"
class BootCompletedReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "Received intent: ${intent.action}")
when (intent.action) {
Intent.ACTION_LOCKED_BOOT_COMPLETED -> {
// we perform everything in the initializer
DolbyController.getInstance(context)
}
Intent.ACTION_BOOT_COMPLETED -> {
DolbyController.getInstance(context).onBootCompleted()
}
else -> Log.e(TAG, "unhandled intent action")
}
}
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2023-25 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi
import android.app.AlertDialog
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import co.aospa.dolby.xiaomi.preference.DolbySettingsFragment
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity
class DolbySettingsActivity : CollapsingToolbarBaseActivity() {
private lateinit var dolbyController: DolbyController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager
.beginTransaction()
.replace(
com.android.settingslib.collapsingtoolbar.R.id.content_frame,
DolbySettingsFragment(),
TAG
)
.commit()
dolbyController = DolbyController.getInstance(this)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menu
.add(Menu.NONE, MENU_RESET, Menu.NONE, R.string.dolby_reset_all)
.setIcon(R.drawable.reset_wrench_24px)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean =
when (item.itemId) {
MENU_RESET -> {
confirmReset()
true
}
else -> super.onOptionsItemSelected(item)
}
private fun confirmReset() {
AlertDialog.Builder(this)
.setTitle(R.string.dolby_reset_all)
.setMessage(R.string.dolby_reset_all_message)
.setPositiveButton(android.R.string.yes) { _, _ ->
dolbyController.resetAllProfiles()
recreate()
Toast.makeText(this, getString(R.string.dolby_reset_all_toast), Toast.LENGTH_SHORT)
.show()
}
.setNegativeButton(android.R.string.no, null)
.show()
}
companion object {
private const val TAG = "DolbySettingsActivity"
private const val MENU_RESET = 1001
}
}

View File

@@ -1,289 +0,0 @@
/*
* Copyright (C) 2023-25 Paranoid Android
*
* SPDX-License-Identifier: Apache-2.0
*/
package co.aospa.dolby.xiaomi.preference
import android.media.AudioAttributes
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
import android.media.AudioManager
import android.os.Bundle
import android.os.Handler
import android.widget.Toast
import androidx.core.os.postDelayed
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceChangeListener
import androidx.preference.PreferenceCategory
import androidx.preference.SeekBarPreference
import androidx.preference.SwitchPreferenceCompat
import co.aospa.dolby.xiaomi.DolbyConstants
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_BASS
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_DIALOGUE
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_DIALOGUE_AMOUNT
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_ENABLE
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_HP_VIRTUALIZER
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_IEQ
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_PRESET
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_PROFILE
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_RESET
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_SPK_VIRTUALIZER
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_STEREO_WIDENING
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.PREF_VOLUME
import co.aospa.dolby.xiaomi.DolbyConstants.Companion.dlog
import co.aospa.dolby.xiaomi.DolbyController
import co.aospa.dolby.xiaomi.R
import com.android.settingslib.widget.MainSwitchPreference
import com.android.settingslib.widget.SettingsBasePreferenceFragment
class DolbySettingsFragment : SettingsBasePreferenceFragment(),
OnPreferenceChangeListener {
private val switchBar by lazy {
findPreference<MainSwitchPreference>(PREF_ENABLE)!!
}
private val profilePref by lazy {
findPreference<ListPreference>(PREF_PROFILE)!!
}
private val presetPref by lazy {
findPreference<Preference>(PREF_PRESET)!!
}
private val ieqPref by lazy {
findPreference<DolbyIeqPreference>(PREF_IEQ)!!
}
private val dialoguePref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_DIALOGUE)!!
}
private val dialogueAmountPref by lazy {
findPreference<SeekBarPreference>(PREF_DIALOGUE_AMOUNT)!!
}
private val bassPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_BASS)!!
}
private val hpVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_HP_VIRTUALIZER)!!
}
private val spkVirtPref by lazy {
findPreference<SwitchPreferenceCompat>(PREF_SPK_VIRTUALIZER)!!
}
private val settingsCategory by lazy {
findPreference<PreferenceCategory>("dolby_category_settings")!!
}
private val advSettingsCategory by lazy {
findPreference<PreferenceCategory>("dolby_category_adv_settings")!!
}
private val advSettingsFooter by lazy {
findPreference<Preference>("dolby_adv_settings_footer")!!
}
private var volumePref: SwitchPreferenceCompat? = null
private var stereoPref: SeekBarPreference? = null
private val dolbyController by lazy { DolbyController.getInstance(requireContext()) }
private val audioManager by lazy { requireContext().getSystemService(AudioManager::class.java)!! }
private val handler = Handler()
private var isOnSpeaker = true
set(value) {
if (field == value) return
field = value
dlog(TAG, "setIsOnSpeaker($value)")
updateProfileSpecificPrefs()
}
private val audioDeviceCallback = object : AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesAdded")
updateSpeakerState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<AudioDeviceInfo>) {
dlog(TAG, "onAudioDevicesRemoved")
updateSpeakerState()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
dlog(TAG, "onCreatePreferences")
setPreferencesFromResource(R.xml.dolby_settings, rootKey)
stereoPref = findPreference<SeekBarPreference>(PREF_STEREO_WIDENING)!!
if (!resources.getBoolean(R.bool.dolby_stereo_widening_supported)) {
settingsCategory.removePreference(stereoPref!!)
stereoPref = null
}
volumePref = findPreference<SwitchPreferenceCompat>(PREF_VOLUME)!!
if (!resources.getBoolean(R.bool.dolby_volume_leveler_supported)) {
advSettingsCategory.removePreference(volumePref!!)
volumePref = null
}
preferenceManager.preferenceDataStore = DolbyPreferenceStore(requireContext()).also {
it.profile = dolbyController.profile
}
val dsOn = dolbyController.dsOn
switchBar.onPreferenceChangeListener = this
switchBar.setChecked(dsOn)
profilePref.onPreferenceChangeListener = this
hpVirtPref.onPreferenceChangeListener = this
spkVirtPref.onPreferenceChangeListener = this
stereoPref?.apply {
onPreferenceChangeListener = this@DolbySettingsFragment
min = context.resources.getInteger(R.integer.stereo_widening_min)
max = context.resources.getInteger(R.integer.stereo_widening_max)
}
dialoguePref.onPreferenceChangeListener = this
dialogueAmountPref.apply {
onPreferenceChangeListener = this@DolbySettingsFragment
min = context.resources.getInteger(R.integer.dialogue_enhancer_min)
max = context.resources.getInteger(R.integer.dialogue_enhancer_max)
}
bassPref.onPreferenceChangeListener = this
volumePref?.onPreferenceChangeListener = this
ieqPref.onPreferenceChangeListener = this
audioManager.registerAudioDeviceCallback(audioDeviceCallback, handler)
updateSpeakerState()
updateProfileSpecificPrefsImmediate()
}
override fun onDestroyView() {
dlog(TAG, "onDestroyView")
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
handler.removeCallbacksAndMessages(null)
super.onDestroyView()
}
override fun onResume() {
super.onResume()
updateProfileSpecificPrefsImmediate()
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
dlog(TAG, "onPreferenceChange: key=${preference.key} value=$newValue")
when (preference.key) {
PREF_ENABLE -> {
val isChecked = newValue as Boolean
dlog(TAG, "PREF_ENABLE -> $isChecked")
dolbyController.dsOn = isChecked
updateProfileSpecificPrefs()
}
PREF_PROFILE -> {
val profile = newValue.toString().toInt()
dolbyController.profile = profile
updateProfileSpecificPrefs()
}
PREF_SPK_VIRTUALIZER -> {
dolbyController.setSpeakerVirtEnabled(newValue as Boolean)
}
PREF_HP_VIRTUALIZER -> {
dolbyController.setHeadphoneVirtEnabled(newValue as Boolean)
}
PREF_STEREO_WIDENING -> {
dolbyController.setStereoWideningAmount(newValue as Int)
}
PREF_DIALOGUE -> {
dolbyController.setDialogueEnhancerEnabled(newValue as Boolean)
}
PREF_DIALOGUE_AMOUNT -> {
dolbyController.setDialogueEnhancerAmount(newValue as Int)
}
PREF_BASS -> {
dolbyController.setBassEnhancerEnabled(newValue as Boolean)
}
PREF_VOLUME -> {
dolbyController.setVolumeLevelerEnabled(newValue as Boolean)
}
PREF_IEQ -> {
dolbyController.setIeqPreset(newValue.toString().toInt())
}
else -> return false
}
return true
}
private fun updateSpeakerState() {
val device = audioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)[0]
isOnSpeaker = (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
}
private fun updateProfileSpecificPrefs() {
handler.postDelayed(100) { updateProfileSpecificPrefsImmediate() }
}
private fun updateProfileSpecificPrefsImmediate() {
if (context == null) return
if (!dolbyController.dsOn) {
dlog(TAG, "updateProfileSpecificPrefs: Dolby is off")
advSettingsCategory.isVisible = false
return
}
val unknownRes = getString(R.string.dolby_unknown)
val headphoneRes = getString(R.string.dolby_connect_headphones)
val currentProfile = dolbyController.profile
val isDynamicProfile = currentProfile == 0
(preferenceManager.preferenceDataStore as DolbyPreferenceStore).profile = currentProfile
dlog(TAG, "updateProfileSpecificPrefs: currentProfile=$currentProfile")
profilePref.apply {
if (entryValues.contains(currentProfile.toString())) {
summary = "%s"
value = currentProfile.toString()
} else {
summary = unknownRes
dlog(TAG, "current profile $currentProfile unknown")
}
}
// hide advanced settings on dynamic profile
advSettingsCategory.isVisible = !isDynamicProfile
advSettingsFooter.isVisible = isDynamicProfile
presetPref.summary = dolbyController.getPresetName()
bassPref.isChecked = dolbyController.getBassEnhancerEnabled(currentProfile)
// below prefs are not visible on dynamic profile
if (isDynamicProfile) return
val ieqValue = dolbyController.getIeqPreset(currentProfile)
ieqPref.apply {
if (entryValues.contains(ieqValue.toString())) {
summary = "%s"
value = ieqValue.toString()
} else {
summary = unknownRes
dlog(TAG, "ieq value $ieqValue unknown")
}
}
dialoguePref.isChecked = dolbyController.getDialogueEnhancerEnabled(currentProfile)
dialogueAmountPref.value = dolbyController.getDialogueEnhancerAmount(currentProfile)
spkVirtPref.isChecked = dolbyController.getSpeakerVirtEnabled(currentProfile)
volumePref?.isChecked = dolbyController.getVolumeLevelerEnabled(currentProfile)
hpVirtPref.isChecked = dolbyController.getHeadphoneVirtEnabled(currentProfile)
stereoPref?.value = dolbyController.getStereoWideningAmount(currentProfile)
}
companion object {
private const val TAG = "DolbySettingsFragment"
private val ATTRIBUTES_MEDIA = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
}
}

View File

@@ -1,17 +0,0 @@
//
// Copyright (C) 2023 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
cc_library_shared {
name: "libshim_dolby",
srcs: ["libshim_dolby.cpp"],
compile_multilib: "64",
shared_libs: [
"liblog",
"libdl",
"libc",
],
vendor: true,
}

View File

@@ -1,27 +0,0 @@
//
// SPDX-FileCopyrightText: The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
#include <log/log.h>
#include <dlfcn.h>
extern "C" void _ZNK7android7RefBase9incStrongEPKv(void* thisptr, const void* id) {
if (!thisptr) {
ALOGE("DolbyShim: incStrong called on nullptr!");
return;
}
typedef void (*RealFunc)(void*, const void*);
static RealFunc real = (RealFunc)dlsym(RTLD_NEXT, "_ZNK7android7RefBase9incStrongEPKv");
if (real) real(thisptr, id);
}
extern "C" void _ZNK7android7RefBase9decStrongEPKv(void* thisptr, const void* id) {
if (!thisptr) {
ALOGE("DolbyShim: decStrong called on nullptr!");
return;
}
typedef void (*RealFunc)(void*, const void*);
static RealFunc real = (RealFunc)dlsym(RTLD_NEXT, "_ZNK7android7RefBase9decStrongEPKv");
if (real) real(thisptr, id);
}

View File

@@ -1,4 +0,0 @@
runtime_resource_overlay {
name: "DolbyFrameworksResCommon",
product_specific: true,
}

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.overlay.dolby">
<overlay
android:isStatic="true"
android:priority="300"
android:targetPackage="android" />
</manifest>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-License-Identifier: Apache-2.0
-->
<resources>
<!-- The default value for whether head tracking for
spatial audio is enabled for a newly connected audio device -->
<bool name="config_spatial_audio_head_tracking_enabled_default">true</bool>
</resources>

Binary file not shown.

BIN
proprietary/vendor/lib/libdlbpreg.so vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +0,0 @@
prebuilt_etc {
name: "init.dolby.rc",
src: "init.dolby.rc",
sub_dir: "init",
soc_specific: true
}

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