From b21e660eb1230e0f0a80800498876fb1ed1a56f6 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sat, 16 Aug 2025 13:49:47 +0200 Subject: [PATCH 1/7] Implement VolumeStepsIncrease --- VolumeStepsIncrease/build.gradle.kts | 17 +++++++ .../src/main/AndroidManifest.xml | 34 ++++++++++++++ .../src/main/assets/xposed_init | 1 + .../VolumeStepsIncrease/Common.kt | 24 ++++++++++ .../VolumeStepsIncrease/Hook.kt | 37 +++++++++++++++ .../VolumeStepsIncrease/SettingsActivity.kt | 46 +++++++++++++++++++ .../src/main/res/layout/settings_activity.xml | 14 ++++++ .../src/main/res/values-v21/themes.xml | 4 ++ .../src/main/res/values/arrays.xml | 6 +++ .../src/main/res/values/strings.xml | 5 ++ .../src/main/res/values/themes.xml | 8 ++++ .../src/main/res/xml/root_preferences.xml | 4 ++ modules.gradle.kts | 1 + 13 files changed, 201 insertions(+) create mode 100644 VolumeStepsIncrease/build.gradle.kts create mode 100644 VolumeStepsIncrease/src/main/AndroidManifest.xml create mode 100644 VolumeStepsIncrease/src/main/assets/xposed_init create mode 100644 VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt create mode 100644 VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt create mode 100644 VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt create mode 100644 VolumeStepsIncrease/src/main/res/layout/settings_activity.xml create mode 100644 VolumeStepsIncrease/src/main/res/values-v21/themes.xml create mode 100644 VolumeStepsIncrease/src/main/res/values/arrays.xml create mode 100644 VolumeStepsIncrease/src/main/res/values/strings.xml create mode 100644 VolumeStepsIncrease/src/main/res/values/themes.xml create mode 100644 VolumeStepsIncrease/src/main/res/xml/root_preferences.xml diff --git a/VolumeStepsIncrease/build.gradle.kts b/VolumeStepsIncrease/build.gradle.kts new file mode 100644 index 0000000..352aa6a --- /dev/null +++ b/VolumeStepsIncrease/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + alias(libs.plugins.buildlogic.android.application) + alias(libs.plugins.buildlogic.kotlin.android) +} + +android { + namespace = "com.programminghoch10.VolumeStepsIncrease" + + defaultConfig { + minSdk = 23 + targetSdk = 35 + } +} + +dependencies { + implementation(libs.androidx.preference) +} diff --git a/VolumeStepsIncrease/src/main/AndroidManifest.xml b/VolumeStepsIncrease/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6958021 --- /dev/null +++ b/VolumeStepsIncrease/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + diff --git a/VolumeStepsIncrease/src/main/assets/xposed_init b/VolumeStepsIncrease/src/main/assets/xposed_init new file mode 100644 index 0000000..2d70ba7 --- /dev/null +++ b/VolumeStepsIncrease/src/main/assets/xposed_init @@ -0,0 +1 @@ +com.programminghoch10.VolumeStepsIncrease.Hook diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt new file mode 100644 index 0000000..224c86a --- /dev/null +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt @@ -0,0 +1,24 @@ +package com.programminghoch10.VolumeStepsIncrease + +class Common { + companion object { + val streams = arrayOf( + "ro.config.vc_call_vol_steps", + "ro.config.media_vol_steps", + "ro.config.alarm_vol_steps", + "ro.config.system_vol_steps", + ) + + val defaultStreamValues = mapOf( + // default volumes from AudioService + "ro.config.vc_call_vol_steps" to 5, + "ro.config.media_vol_steps" to 15, + "ro.config.alarm_vol_steps" to 7, + "ro.config.system_vol_steps" to 7, + ).mapValues { it.value * 2 } + + fun getMaxVolumeSteps(): Int { + return defaultStreamValues.values.maxOf { it } * 3 + } + } +} diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt new file mode 100644 index 0000000..9fd0bc5 --- /dev/null +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt @@ -0,0 +1,37 @@ +package com.programminghoch10.VolumeStepsIncrease + +import android.util.Log +import com.programminghoch10.VolumeStepsIncrease.Common.Companion.streams +import de.robv.android.xposed.IXposedHookLoadPackage +import de.robv.android.xposed.XSharedPreferences +import de.robv.android.xposed.XposedHelpers +import de.robv.android.xposed.callbacks.XC_LoadPackage +import de.robv.android.xposed.XC_MethodHook as MethodHook + +class Hook : IXposedHookLoadPackage { + override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) { + if (lpparam.packageName == BuildConfig.APPLICATION_ID) return + + val SystemPropertiesClass = XposedHelpers.findClass("android.os.SystemProperties", lpparam.classLoader) + + XposedHelpers.findAndHookMethod(SystemPropertiesClass, "getInt", String::class.java, Int::class.java, object : MethodHook() { + override fun afterHookedMethod(param: MethodHookParam) { + val key = param.args[0] as String + param.args[1] as Int + val result = param.result as Int + if (!streams.contains(key)) return + val preferences = XSharedPreferences(BuildConfig.APPLICATION_ID, "streams") + if (!preferences.contains(key)) return + param.result = preferences.getInt(key, result) + Log.d("Logger", "beforeHookedMethod: replace $key with ${param.result}") + } + }) + + XposedHelpers.findAndHookMethod(SystemPropertiesClass, "getBoolean", String::class.java, Boolean::class.java, object : MethodHook() { + override fun beforeHookedMethod(param: MethodHookParam) { + val key = param.args[0] as String + if (key == "audio.safemedia.bypass") param.result = true + } + }) + } +} diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt new file mode 100644 index 0000000..3c090cb --- /dev/null +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt @@ -0,0 +1,46 @@ +package com.programminghoch10.VolumeStepsIncrease + +import android.annotation.SuppressLint +import android.os.Bundle +import androidx.fragment.app.FragmentActivity +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SeekBarPreference +import com.programminghoch10.VolumeStepsIncrease.Common.Companion.defaultStreamValues +import com.programminghoch10.VolumeStepsIncrease.Common.Companion.getMaxVolumeSteps +import com.programminghoch10.VolumeStepsIncrease.Common.Companion.streams + +class SettingsActivity : FragmentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.settings_activity) + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment()).commit() + } + actionBar?.setDisplayHomeAsUpEnabled( + supportFragmentManager.backStackEntryCount > 0 + ) + } + + class SettingsFragment : PreferenceFragmentCompat() { + @SuppressLint("WorldReadableFiles") + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.root_preferences, rootKey) + preferenceManager.sharedPreferencesName = "streams" + preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE + + for (stream in streams) { + val defaultValue = defaultStreamValues[stream]!! + val preference = SeekBarPreference(requireContext()) + preference.key = stream + preference.title = stream + preference.min = 1 + preference.max = getMaxVolumeSteps() + preference.setDefaultValue(defaultValue) + preference.showSeekBarValue = true + //preference.summary = "default = ${defaultValue / 2}" + preferenceScreen.addPreference(preference) + } + } + } +} diff --git a/VolumeStepsIncrease/src/main/res/layout/settings_activity.xml b/VolumeStepsIncrease/src/main/res/layout/settings_activity.xml new file mode 100644 index 0000000..620409c --- /dev/null +++ b/VolumeStepsIncrease/src/main/res/layout/settings_activity.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/VolumeStepsIncrease/src/main/res/values-v21/themes.xml b/VolumeStepsIncrease/src/main/res/values-v21/themes.xml new file mode 100644 index 0000000..6ee0359 --- /dev/null +++ b/VolumeStepsIncrease/src/main/res/values-v21/themes.xml @@ -0,0 +1,4 @@ + + + + diff --git a/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml b/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml new file mode 100644 index 0000000..37f6c5a --- /dev/null +++ b/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml @@ -0,0 +1,4 @@ + + + diff --git a/modules.gradle.kts b/modules.gradle.kts index 352f7fa..b1f4cf1 100644 --- a/modules.gradle.kts +++ b/modules.gradle.kts @@ -19,3 +19,4 @@ include(":ResetAllNotificationChannels") include(":RotationControl") include(":SensorMod") include(":UpsideWifi") +include(":VolumeStepsIncrease") From 2360164dadf77a6f8c83662e344a5b51df27d7d0 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:58:50 +0200 Subject: [PATCH 2/7] flatten companion object in VolumeStepsIncrease --- .../VolumeStepsIncrease/Common.kt | 38 +++++++++---------- .../VolumeStepsIncrease/Hook.kt | 2 +- .../VolumeStepsIncrease/SettingsActivity.kt | 6 +-- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt index 224c86a..234b5ce 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt @@ -1,24 +1,22 @@ package com.programminghoch10.VolumeStepsIncrease -class Common { - companion object { - val streams = arrayOf( - "ro.config.vc_call_vol_steps", - "ro.config.media_vol_steps", - "ro.config.alarm_vol_steps", - "ro.config.system_vol_steps", - ) - - val defaultStreamValues = mapOf( - // default volumes from AudioService - "ro.config.vc_call_vol_steps" to 5, - "ro.config.media_vol_steps" to 15, - "ro.config.alarm_vol_steps" to 7, - "ro.config.system_vol_steps" to 7, - ).mapValues { it.value * 2 } - - fun getMaxVolumeSteps(): Int { - return defaultStreamValues.values.maxOf { it } * 3 - } +object Common { + val streams = arrayOf( + "ro.config.vc_call_vol_steps", + "ro.config.media_vol_steps", + "ro.config.alarm_vol_steps", + "ro.config.system_vol_steps", + ) + + val defaultStreamValues = mapOf( + // default volumes from AudioService + "ro.config.vc_call_vol_steps" to 5, + "ro.config.media_vol_steps" to 15, + "ro.config.alarm_vol_steps" to 7, + "ro.config.system_vol_steps" to 7, + ).mapValues { it.value * 2 } + + fun getMaxVolumeSteps(): Int { + return defaultStreamValues.values.maxOf { it } * 3 } } diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt index 9fd0bc5..4347cdc 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt @@ -1,7 +1,7 @@ package com.programminghoch10.VolumeStepsIncrease import android.util.Log -import com.programminghoch10.VolumeStepsIncrease.Common.Companion.streams +import com.programminghoch10.VolumeStepsIncrease.Common.streams import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.XSharedPreferences import de.robv.android.xposed.XposedHelpers diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt index 3c090cb..b9d8dbf 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt @@ -5,9 +5,9 @@ import android.os.Bundle import androidx.fragment.app.FragmentActivity import androidx.preference.PreferenceFragmentCompat import androidx.preference.SeekBarPreference -import com.programminghoch10.VolumeStepsIncrease.Common.Companion.defaultStreamValues -import com.programminghoch10.VolumeStepsIncrease.Common.Companion.getMaxVolumeSteps -import com.programminghoch10.VolumeStepsIncrease.Common.Companion.streams +import com.programminghoch10.VolumeStepsIncrease.Common.defaultStreamValues +import com.programminghoch10.VolumeStepsIncrease.Common.getMaxVolumeSteps +import com.programminghoch10.VolumeStepsIncrease.Common.streams class SettingsActivity : FragmentActivity() { From 69806211d7a053579435dcb55a3507904159b0d0 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:59:35 +0200 Subject: [PATCH 3/7] remove appinfo settings access for VolumeStepsIncrease * the module has to be enabled for this to work, forcing the user to go through Xposed Manager makes it more likely they enable it first --- VolumeStepsIncrease/src/main/AndroidManifest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/VolumeStepsIncrease/src/main/AndroidManifest.xml b/VolumeStepsIncrease/src/main/AndroidManifest.xml index 6958021..13292ab 100644 --- a/VolumeStepsIncrease/src/main/AndroidManifest.xml +++ b/VolumeStepsIncrease/src/main/AndroidManifest.xml @@ -10,8 +10,6 @@ android:theme="@style/AppTheme" > - - From 74c9b8fc6d99f973a682b20b4f2aa776c6703fc5 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sun, 17 Aug 2025 22:42:04 +0200 Subject: [PATCH 4/7] add metadata for IncreaseVolumeSteps --- README.md | 1 + VolumeStepsIncrease/Readme.md | 3 +++ VolumeStepsIncrease/src/main/AndroidManifest.xml | 4 ++++ VolumeStepsIncrease/src/main/res/values/strings.xml | 1 + .../en-US/full_description.txt | 1 + .../en-US/short_description.txt | 1 + .../com.programminghoch10.VolumeStepsIncrease/en-US/title.txt | 1 + 7 files changed, 12 insertions(+) create mode 100644 VolumeStepsIncrease/Readme.md create mode 100644 metadata/com.programminghoch10.VolumeStepsIncrease/en-US/full_description.txt create mode 100644 metadata/com.programminghoch10.VolumeStepsIncrease/en-US/short_description.txt create mode 100644 metadata/com.programminghoch10.VolumeStepsIncrease/en-US/title.txt diff --git a/README.md b/README.md index 9bc9877..8867bb8 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ A collection of small Xposed Modules. | [ResetAllNotificationChannels](ResetAllNotificationChannels) | [@binarynoise](https://github.com/binarynoise) | Reset all Notification Channels: vibrations, ringtones, importance etc. | [GitHub](https://github.com/binarynoise/XposedModulets/releases?q=resetAllNotificationChannels) [IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/de.binarynoise.resetAllNotificationChannels) | | [RotationControl](RotationControl) | [@programminghoch10](https://github.com/programminghoch10) | Force rotation for selected packages | [GitHub](https://github.com/binarynoise/XposedModulets/releases?q=RotationControl) [IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/com.programminghoch10.RotationControl) | | [UpsideWifi](UpsideWifi) | [@programminghoch10](https://github.com/programminghoch10) | Turn the WiFi icon upside down | [GitHub](https://github.com/binarynoise/XposedModulets/releases?q=UpsideWifi) | +| [VolumeStepsIncrease](VolumeStepsIncrease) | [@programminghoch10](https://github.com/programminghoch10) | Increase the amount of volume steps | [GitHub](https://github.com/binarynoise/XposedModulets/releases?q=VolumeStepsIncrease) | ## License diff --git a/VolumeStepsIncrease/Readme.md b/VolumeStepsIncrease/Readme.md new file mode 100644 index 0000000..cfe8bb2 --- /dev/null +++ b/VolumeStepsIncrease/Readme.md @@ -0,0 +1,3 @@ +# VolumeStepsIncrease + +Increase the amount of volume steps. diff --git a/VolumeStepsIncrease/src/main/AndroidManifest.xml b/VolumeStepsIncrease/src/main/AndroidManifest.xml index 13292ab..7cf0327 100644 --- a/VolumeStepsIncrease/src/main/AndroidManifest.xml +++ b/VolumeStepsIncrease/src/main/AndroidManifest.xml @@ -19,6 +19,10 @@ android:name="xposedmodule" android:value="true" /> + VolumeStepsIncrease Volume Steps Configuration + Increase the amount of volume steps. diff --git a/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/full_description.txt b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/full_description.txt new file mode 100644 index 0000000..4977cfb --- /dev/null +++ b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/full_description.txt @@ -0,0 +1 @@ +Increase the amount of volume steps. diff --git a/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/short_description.txt b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/short_description.txt new file mode 100644 index 0000000..4977cfb --- /dev/null +++ b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/short_description.txt @@ -0,0 +1 @@ +Increase the amount of volume steps. diff --git a/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/title.txt b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/title.txt new file mode 100644 index 0000000..ac5f80f --- /dev/null +++ b/metadata/com.programminghoch10.VolumeStepsIncrease/en-US/title.txt @@ -0,0 +1 @@ +VolumeStepsIncrease \ No newline at end of file From 2d669b58d5eff9334c94a6ef142cd6a6f6f80420 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:22:55 +0200 Subject: [PATCH 5/7] improve VolumeStepsIncrease * settings activity * hooking AudioService --- VolumeStepsIncrease/build.gradle.kts | 2 +- .../VolumeStepsIncrease/Common.kt | 58 +++++++++--- .../VolumeStepsIncrease/Hook.kt | 23 ++++- .../VolumeStepsIncrease/SettingsActivity.kt | 55 ++++++++--- .../VolumeStepsIncrease/StockValues.kt | 94 +++++++++++++++++++ .../src/main/res/values/strings.xml | 1 + .../src/main/res/xml/root_preferences.xml | 6 +- 7 files changed, 205 insertions(+), 34 deletions(-) create mode 100644 VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/StockValues.kt diff --git a/VolumeStepsIncrease/build.gradle.kts b/VolumeStepsIncrease/build.gradle.kts index 352aa6a..48b1ab2 100644 --- a/VolumeStepsIncrease/build.gradle.kts +++ b/VolumeStepsIncrease/build.gradle.kts @@ -13,5 +13,5 @@ android { } dependencies { - implementation(libs.androidx.preference) + implementation(libs.androidx.preference.ktx) } diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt index 234b5ce..ddb8552 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt @@ -1,22 +1,52 @@ package com.programminghoch10.VolumeStepsIncrease +import com.programminghoch10.VolumeStepsIncrease.StockValues.MAX_STREAM_VOLUME +import com.programminghoch10.VolumeStepsIncrease.StockValues.MIN_STREAM_VOLUME +import com.programminghoch10.VolumeStepsIncrease.StockValues.STREAM_ALARM +import com.programminghoch10.VolumeStepsIncrease.StockValues.STREAM_MUSIC +import com.programminghoch10.VolumeStepsIncrease.StockValues.STREAM_SYSTEM +import com.programminghoch10.VolumeStepsIncrease.StockValues.STREAM_VOICE_CALL + object Common { - val streams = arrayOf( - "ro.config.vc_call_vol_steps", - "ro.config.media_vol_steps", - "ro.config.alarm_vol_steps", - "ro.config.system_vol_steps", + val SHARED_PREFERENCES_NAME = "streams" + + val STREAMS = StockValues::class.java.declaredFields.filter { it.name.startsWith("STREAM_") }.associate { it.name to it.getInt(null) } + + val STREAM_NAMES = STREAMS.keys + + val systemPropertyToStream = mapOf( + "ro.config.vc_call_vol_steps" to STREAM_VOICE_CALL, + "ro.config.media_vol_steps" to STREAM_MUSIC, + "ro.config.alarm_vol_steps" to STREAM_ALARM, + "ro.config.system_vol_steps" to STREAM_SYSTEM, ) - val defaultStreamValues = mapOf( - // default volumes from AudioService - "ro.config.vc_call_vol_steps" to 5, - "ro.config.media_vol_steps" to 15, - "ro.config.alarm_vol_steps" to 7, - "ro.config.system_vol_steps" to 7, - ).mapValues { it.value * 2 } + val moduleDefaultVolumeSteps = mapOf( + STREAM_MUSIC to MAX_STREAM_VOLUME[STREAM_MUSIC] * 2, + STREAM_VOICE_CALL to MAX_STREAM_VOLUME[STREAM_VOICE_CALL] * 2, + ) + + fun getSystemMaxVolumeSteps(stream: Int): Int { + return MAX_STREAM_VOLUME[stream] + } + + fun getModuleDefaultVolumeSteps(stream: Int): Int { + return moduleDefaultVolumeSteps[stream] ?: getSystemMaxVolumeSteps(stream) + } + + fun getModuleMaxVolumeSteps(stream: Int): Int { + return getSystemMaxVolumeSteps(stream) * 3 + } + + fun getSystemMinVolumeSteps(stream: Int): Int { + return MIN_STREAM_VOLUME[stream] + } + + fun getModuleMinVolumeSteps(stream: Int): Int { + return getSystemMinVolumeSteps((stream)) + } - fun getMaxVolumeSteps(): Int { - return defaultStreamValues.values.maxOf { it } * 3 + fun getPreferenceKey(stream: Int): String { + return "STREAM_${stream}" } } diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt index 4347cdc..de64cfc 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Hook.kt @@ -1,9 +1,13 @@ package com.programminghoch10.VolumeStepsIncrease import android.util.Log -import com.programminghoch10.VolumeStepsIncrease.Common.streams +import com.programminghoch10.VolumeStepsIncrease.Common.SHARED_PREFERENCES_NAME +import com.programminghoch10.VolumeStepsIncrease.Common.STREAMS +import com.programminghoch10.VolumeStepsIncrease.Common.getPreferenceKey +import com.programminghoch10.VolumeStepsIncrease.Common.systemPropertyToStream import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.XSharedPreferences +import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import de.robv.android.xposed.XC_MethodHook as MethodHook @@ -19,9 +23,9 @@ class Hook : IXposedHookLoadPackage { val key = param.args[0] as String param.args[1] as Int val result = param.result as Int - if (!streams.contains(key)) return - val preferences = XSharedPreferences(BuildConfig.APPLICATION_ID, "streams") - if (!preferences.contains(key)) return + val streamInt = systemPropertyToStream[key] ?: return + val preferences = XSharedPreferences(BuildConfig.APPLICATION_ID, SHARED_PREFERENCES_NAME) + if (!preferences.contains(getPreferenceKey(streamInt))) return param.result = preferences.getInt(key, result) Log.d("Logger", "beforeHookedMethod: replace $key with ${param.result}") } @@ -33,5 +37,16 @@ class Hook : IXposedHookLoadPackage { if (key == "audio.safemedia.bypass") param.result = true } }) + + val AudioServiceClass = XposedHelpers.findClass("com.android.server.audio.AudioService", lpparam.classLoader) + XposedBridge.hookAllConstructors(AudioServiceClass, object : MethodHook() { + override fun afterHookedMethod(param: MethodHookParam) { + val MAX_STREAM_VOLUME = XposedHelpers.getObjectField(param.thisObject, "MAX_STREAM_VOLUME") as Array + val preferences = XSharedPreferences(BuildConfig.APPLICATION_ID, SHARED_PREFERENCES_NAME) + STREAMS.filter { preferences.contains(getPreferenceKey(it.value)) } + .map { it.value to preferences.getInt(getPreferenceKey(it.value), MAX_STREAM_VOLUME[it.value]) } + .forEach { MAX_STREAM_VOLUME[it.first] = it.second } + } + }) } } diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt index b9d8dbf..33ffc4e 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt @@ -1,13 +1,22 @@ package com.programminghoch10.VolumeStepsIncrease +import kotlin.math.round import android.annotation.SuppressLint import android.os.Bundle import androidx.fragment.app.FragmentActivity +import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceGroup import androidx.preference.SeekBarPreference -import com.programminghoch10.VolumeStepsIncrease.Common.defaultStreamValues -import com.programminghoch10.VolumeStepsIncrease.Common.getMaxVolumeSteps -import com.programminghoch10.VolumeStepsIncrease.Common.streams +import androidx.preference.children +import com.programminghoch10.VolumeStepsIncrease.Common.SHARED_PREFERENCES_NAME +import com.programminghoch10.VolumeStepsIncrease.Common.STREAMS +import com.programminghoch10.VolumeStepsIncrease.Common.STREAM_NAMES +import com.programminghoch10.VolumeStepsIncrease.Common.getModuleDefaultVolumeSteps +import com.programminghoch10.VolumeStepsIncrease.Common.getModuleMaxVolumeSteps +import com.programminghoch10.VolumeStepsIncrease.Common.getModuleMinVolumeSteps +import com.programminghoch10.VolumeStepsIncrease.Common.getPreferenceKey +import com.programminghoch10.VolumeStepsIncrease.Common.getSystemMaxVolumeSteps class SettingsActivity : FragmentActivity() { @@ -26,21 +35,43 @@ class SettingsActivity : FragmentActivity() { @SuppressLint("WorldReadableFiles") override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) - preferenceManager.sharedPreferencesName = "streams" + preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE - for (stream in streams) { - val defaultValue = defaultStreamValues[stream]!! + for (stream in STREAM_NAMES) { + val streamInt = STREAMS[stream]!! val preference = SeekBarPreference(requireContext()) - preference.key = stream - preference.title = stream - preference.min = 1 - preference.max = getMaxVolumeSteps() - preference.setDefaultValue(defaultValue) + preference.key = getPreferenceKey(streamInt) + preference.title = stream.replace("STREAM_", "") + preference.min = getModuleMinVolumeSteps(streamInt) + preference.max = getModuleMaxVolumeSteps(streamInt) + preference.setDefaultValue(getModuleDefaultVolumeSteps(streamInt)) preference.showSeekBarValue = true - //preference.summary = "default = ${defaultValue / 2}" + preference.updatesContinuously = true + preference.setOnPreferenceChangeListener { preference, newValue -> + val factor = (newValue as Int).toDouble() / getSystemMaxVolumeSteps(streamInt) + preference.summary = arrayOf( + "factor=${factor.round(1)}x ", + //"systemMin=${getSystemMinVolumeSteps(streamInt)} ", + "systemMax=${getSystemMaxVolumeSteps(streamInt)} ", + ).joinToString(" ") + true + } preferenceScreen.addPreference(preference) + preference.onPreferenceChangeListener?.onPreferenceChange(preference, preference.value) } + preferenceScreen.setIconSpaceReservedRecursive(false) + } + + fun Preference.setIconSpaceReservedRecursive(iconSpaceReserved: Boolean) { + this.isIconSpaceReserved = iconSpaceReserved + if (this is PreferenceGroup) children.forEach { it.setIconSpaceReservedRecursive(iconSpaceReserved) } + } + + fun Double.round(decimals: Int = 0): Double { + var multiplier = 1.0 + repeat(decimals) { multiplier *= 10 } + return round(this * multiplier) / multiplier } } } diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/StockValues.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/StockValues.kt new file mode 100644 index 0000000..6bbfce1 --- /dev/null +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/StockValues.kt @@ -0,0 +1,94 @@ +package com.programminghoch10.VolumeStepsIncrease + +import android.media.AudioManager +import androidx.annotation.Keep + +@Keep +object StockValues { + + // from com.android.server.media.AudioService + + /** Maximum volume index values for audio streams */ + var MAX_STREAM_VOLUME: IntArray = intArrayOf( + 5, // STREAM_VOICE_CALL + 7, // STREAM_SYSTEM + 7, // STREAM_RING + 15, // STREAM_MUSIC + 7, // STREAM_ALARM + 7, // STREAM_NOTIFICATION + 15, // STREAM_BLUETOOTH_SCO + 7, // STREAM_SYSTEM_ENFORCED + 15, // STREAM_DTMF + 15, // STREAM_TTS + 15, // STREAM_ACCESSIBILITY + 15, // STREAM_ASSISTANT + ) + + /** Minimum volume index values for audio streams */ + var MIN_STREAM_VOLUME: IntArray = intArrayOf( + 1, // STREAM_VOICE_CALL + 0, // STREAM_SYSTEM + 0, // STREAM_RING + 0, // STREAM_MUSIC + 1, // STREAM_ALARM + 0, // STREAM_NOTIFICATION + 0, // STREAM_BLUETOOTH_SCO + 0, // STREAM_SYSTEM_ENFORCED + 0, // STREAM_DTMF + 0, // STREAM_TTS + 1, // STREAM_ACCESSIBILITY + 0, // STREAM_ASSISTANT + ) + + // from android.media.AudioSystem + + const val STREAM_VOICE_CALL: Int = AudioManager.STREAM_VOICE_CALL + + /** @hide Used to identify the volume of audio streams for system sounds + */ + const val STREAM_SYSTEM: Int = AudioManager.STREAM_SYSTEM + + /** @hide Used to identify the volume of audio streams for the phone ring and message alerts + */ + const val STREAM_RING: Int = AudioManager.STREAM_RING + + /** @hide Used to identify the volume of audio streams for music playback + */ + const val STREAM_MUSIC: Int = AudioManager.STREAM_MUSIC + + /** @hide Used to identify the volume of audio streams for alarms + */ + const val STREAM_ALARM: Int = AudioManager.STREAM_ALARM + + /** @hide Used to identify the volume of audio streams for notifications + */ + const val STREAM_NOTIFICATION: Int = AudioManager.STREAM_NOTIFICATION + + /** @hide + * Used to identify the volume of audio streams for phone calls when connected on bluetooth + */ + @Deprecated("use {@link #STREAM_VOICE_CALL} instead ") + const val STREAM_BLUETOOTH_SCO: Int = 6 + + /** @hide Used to identify the volume of audio streams for enforced system sounds in certain + * countries (e.g camera in Japan) + */ + const val STREAM_SYSTEM_ENFORCED: Int = 7 + + /** @hide Used to identify the volume of audio streams for DTMF tones + */ + const val STREAM_DTMF: Int = AudioManager.STREAM_DTMF + + /** @hide Used to identify the volume of audio streams exclusively transmitted through the + * speaker (TTS) of the device + */ + const val STREAM_TTS: Int = 9 + + /** @hide Used to identify the volume of audio streams for accessibility prompts + */ + const val STREAM_ACCESSIBILITY: Int = AudioManager.STREAM_ACCESSIBILITY + + /** @hide Used to identify the volume of audio streams for virtual assistant + */ + const val STREAM_ASSISTANT: Int = 11 +} diff --git a/VolumeStepsIncrease/src/main/res/values/strings.xml b/VolumeStepsIncrease/src/main/res/values/strings.xml index ddde23b..d239e46 100644 --- a/VolumeStepsIncrease/src/main/res/values/strings.xml +++ b/VolumeStepsIncrease/src/main/res/values/strings.xml @@ -3,4 +3,5 @@ VolumeStepsIncrease Volume Steps Configuration Increase the amount of volume steps. + A restart is required to apply the new values! diff --git a/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml b/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml index 37f6c5a..bdbca14 100644 --- a/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml +++ b/VolumeStepsIncrease/src/main/res/xml/root_preferences.xml @@ -1,4 +1,4 @@ - - + + + From 57843ba051065e61459f98d9424308a4e224e958 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:26:12 +0200 Subject: [PATCH 6/7] inline redundant variable --- .../VolumeStepsIncrease/Common.kt | 2 -- .../VolumeStepsIncrease/SettingsActivity.kt | 20 +++++++++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt index ddb8552..b8f37a5 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/Common.kt @@ -12,8 +12,6 @@ object Common { val STREAMS = StockValues::class.java.declaredFields.filter { it.name.startsWith("STREAM_") }.associate { it.name to it.getInt(null) } - val STREAM_NAMES = STREAMS.keys - val systemPropertyToStream = mapOf( "ro.config.vc_call_vol_steps" to STREAM_VOICE_CALL, "ro.config.media_vol_steps" to STREAM_MUSIC, diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt index 33ffc4e..9928322 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt @@ -11,7 +11,6 @@ import androidx.preference.SeekBarPreference import androidx.preference.children import com.programminghoch10.VolumeStepsIncrease.Common.SHARED_PREFERENCES_NAME import com.programminghoch10.VolumeStepsIncrease.Common.STREAMS -import com.programminghoch10.VolumeStepsIncrease.Common.STREAM_NAMES import com.programminghoch10.VolumeStepsIncrease.Common.getModuleDefaultVolumeSteps import com.programminghoch10.VolumeStepsIncrease.Common.getModuleMaxVolumeSteps import com.programminghoch10.VolumeStepsIncrease.Common.getModuleMinVolumeSteps @@ -38,22 +37,21 @@ class SettingsActivity : FragmentActivity() { preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE - for (stream in STREAM_NAMES) { - val streamInt = STREAMS[stream]!! + for (stream in STREAMS) { val preference = SeekBarPreference(requireContext()) - preference.key = getPreferenceKey(streamInt) - preference.title = stream.replace("STREAM_", "") - preference.min = getModuleMinVolumeSteps(streamInt) - preference.max = getModuleMaxVolumeSteps(streamInt) - preference.setDefaultValue(getModuleDefaultVolumeSteps(streamInt)) + preference.key = getPreferenceKey(stream.value) + preference.title = stream.key.replace("STREAM_", "") + preference.min = getModuleMinVolumeSteps(stream.value) + preference.max = getModuleMaxVolumeSteps(stream.value) + preference.setDefaultValue(getModuleDefaultVolumeSteps(stream.value)) preference.showSeekBarValue = true preference.updatesContinuously = true preference.setOnPreferenceChangeListener { preference, newValue -> - val factor = (newValue as Int).toDouble() / getSystemMaxVolumeSteps(streamInt) + val factor = (newValue as Int).toDouble() / getSystemMaxVolumeSteps(stream.value) preference.summary = arrayOf( "factor=${factor.round(1)}x ", - //"systemMin=${getSystemMinVolumeSteps(streamInt)} ", - "systemMax=${getSystemMaxVolumeSteps(streamInt)} ", + //"systemMin=${getSystemMinVolumeSteps(stream.value)} ", + "systemMax=${getSystemMaxVolumeSteps(stream.value)} ", ).joinToString(" ") true } From ce0316cb051704cf058d331ae3d6d19f49988200 Mon Sep 17 00:00:00 2001 From: programminghoch10 <16062290+programminghoch10@users.noreply.github.com> Date: Thu, 28 Aug 2025 14:58:23 +0200 Subject: [PATCH 7/7] set activity properties properly --- VolumeStepsIncrease/src/main/AndroidManifest.xml | 1 + .../VolumeStepsIncrease/SettingsActivity.kt | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/VolumeStepsIncrease/src/main/AndroidManifest.xml b/VolumeStepsIncrease/src/main/AndroidManifest.xml index 7cf0327..b8980a2 100644 --- a/VolumeStepsIncrease/src/main/AndroidManifest.xml +++ b/VolumeStepsIncrease/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ android:exported="true" android:label="@string/title_activity_settings" android:theme="@style/AppTheme" + android:excludeFromRecents="true" > diff --git a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt index 9928322..d683375 100644 --- a/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt +++ b/VolumeStepsIncrease/src/main/java/com/programminghoch10/VolumeStepsIncrease/SettingsActivity.kt @@ -25,9 +25,12 @@ class SettingsActivity : FragmentActivity() { if (savedInstanceState == null) { supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment()).commit() } - actionBar?.setDisplayHomeAsUpEnabled( - supportFragmentManager.backStackEntryCount > 0 - ) + actionBar?.setDisplayHomeAsUpEnabled(true) + } + + override fun onNavigateUp(): Boolean { + finish() + return super.onNavigateUp() } class SettingsFragment : PreferenceFragmentCompat() {