From ba9728d512bd7ea8f222a79798386fb00d960b29 Mon Sep 17 00:00:00 2001 From: Meticulus Date: Tue, 15 Mar 2022 01:44:03 +0700 Subject: [PATCH] Cherish: Live Volume Steps [2/2] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I1e4ced6a7b7c963419fe1656e25b76f596a61959 Signed-off-by: Jason Edson Signed-off-by: Hưng Phan --- res/values/cherish_arrays.xml | 10 + res/values/cherish_strings.xml | 12 + res/xml/cherish_settings_button.xml | 6 + res/xml/cherish_settings_volume_steps.xml | 62 ++++++ .../fragments/VolumeStepsFragment.java | 206 ++++++++++++++++++ 5 files changed, 296 insertions(+) create mode 100644 res/xml/cherish_settings_volume_steps.xml create mode 100644 src/com/cherish/settings/fragments/VolumeStepsFragment.java diff --git a/res/values/cherish_arrays.xml b/res/values/cherish_arrays.xml index a1615bf..8da8b6f 100644 --- a/res/values/cherish_arrays.xml +++ b/res/values/cherish_arrays.xml @@ -359,5 +359,15 @@ 2 3 + + + + 60 + 45 + 30 + 15 + 7 + 5 + diff --git a/res/values/cherish_strings.xml b/res/values/cherish_strings.xml index 7ee4c3a..a6273fe 100644 --- a/res/values/cherish_strings.xml +++ b/res/values/cherish_strings.xml @@ -452,4 +452,16 @@ Screen off FOD Keep FOD enabled when the screen is off + + Volume steps + Customize volume steps + Volume steps: Alarm + Volume steps: DTMF + Volume steps: Media + Volume steps: Notification + Volume steps: Ringer + Volume steps: System + Volume steps: Voice Call + Reset + diff --git a/res/xml/cherish_settings_button.xml b/res/xml/cherish_settings_button.xml index b1836ae..e14911d 100644 --- a/res/xml/cherish_settings_button.xml +++ b/res/xml/cherish_settings_button.xml @@ -33,6 +33,12 @@ android:summary="@string/volume_rocker_wake_summary" android:title="@string/volume_rocker_wake_title" android:defaultValue="false" /> + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/cherish/settings/fragments/VolumeStepsFragment.java b/src/com/cherish/settings/fragments/VolumeStepsFragment.java new file mode 100644 index 0000000..9d1d501 --- /dev/null +++ b/src/com/cherish/settings/fragments/VolumeStepsFragment.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2015 The Pure Nexus Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cherish.settings.fragments; + +import android.content.Context; +import android.content.SharedPreferences; +import android.media.AudioManager; +import android.os.Bundle; +import android.provider.SearchIndexableResource; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.Preference.OnPreferenceChangeListener; +import androidx.preference.PreferenceScreen; +import androidx.preference.PreferenceFragment; + +import com.android.settings.R; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settingslib.search.SearchIndexable; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@SearchIndexable +public class VolumeStepsFragment extends SettingsPreferenceFragment implements + Preference.OnPreferenceChangeListener { + + private static final String TAG = "VolumeSteps"; + private static final String VOLUME_STEP_DEFAULTS = "volume_step_defaults"; + private static final String FIRST_RUN_KEY = "first_run"; + + // base map of all preference keys and the associated stream + private static final Map volume_map = new HashMap(); + static { + volume_map.put("volume_steps_alarm", new Integer(AudioManager.STREAM_ALARM)); + volume_map.put("volume_steps_dtmf", new Integer(AudioManager.STREAM_DTMF)); + volume_map.put("volume_steps_music", new Integer(AudioManager.STREAM_MUSIC)); + volume_map.put("volume_steps_notification", new Integer(AudioManager.STREAM_NOTIFICATION)); + volume_map.put("volume_steps_ring", new Integer(AudioManager.STREAM_RING)); + volume_map.put("volume_steps_system", new Integer(AudioManager.STREAM_SYSTEM)); + volume_map.put("volume_steps_voice_call", new Integer(AudioManager.STREAM_VOICE_CALL)); + } + + // entries to remove on non-telephony devices + private static final Set telephony_set = new HashSet(); + static { + telephony_set.add("volume_steps_dtmf"); + telephony_set.add("volume_steps_ring"); + telephony_set.add("volume_steps_voice_call"); + } + + // set of available pref keys after device configuration filter + private Set mAvailableKeys = new HashSet(); + private AudioManager mAudioManager; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.cherish_settings_volume_steps); + mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + + final PreferenceScreen prefScreen = getPreferenceScreen(); + mAvailableKeys = volume_map.keySet(); + + // remove invalid audio stream prefs + boolean isPhone = TelephonyManager.getDefault().getCurrentPhoneType() != TelephonyManager.PHONE_TYPE_NONE; + + if (!isPhone) { + // remove telephony keys from available set + mAvailableKeys.removeAll(telephony_set); + for (String key : telephony_set) { + Preference toRemove = prefScreen.findPreference(key); + if (toRemove != null) { + prefScreen.removePreference(toRemove); + } + } + } + + // check prefs for initial run of this fragment + final boolean firstRun = checkForFirstRun(); + + // entries array isn't translatable ugh + final String defEntry = getString(R.string.volume_steps_reset); + + // initialize prefs: set defaults if first run, set listeners and update values + for (String key : mAvailableKeys) { + Preference pref = prefScreen.findPreference(key); + if (pref == null || !(pref instanceof ListPreference)) { + continue; + } + final ListPreference listPref = (ListPreference) pref; + int steps = mAudioManager.getStreamMaxVolume(volume_map.get(key)); + if (firstRun) { + saveDefaultSteps(listPref, steps); + } + final int defSteps = getDefaultSteps(listPref); + CharSequence[] entries = new CharSequence[listPref.getEntries().length + 1]; + CharSequence[] values = new CharSequence[listPref.getEntryValues().length + 1]; + + for (int i = 0; i < entries.length; i++) { + if (i == 0) { + entries[i] = defEntry; + values[i] = String.valueOf(defSteps); + continue; + } + entries[i] = listPref.getEntries()[i - 1]; + values[i] = listPref.getEntryValues()[i - 1]; + } + listPref.setEntries(entries); + listPref.setEntryValues(values); + updateVolumeStepPrefs(listPref, steps); + listPref.setOnPreferenceChangeListener(this); + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object objValue) { + if (preference.hasKey() && mAvailableKeys.contains(preference.getKey())) { + commitVolumeSteps(preference, Integer.parseInt(objValue.toString())); + } + return true; + } + + private SharedPreferences getDefaultStepsPrefs() { + return getActivity().getSharedPreferences(VOLUME_STEP_DEFAULTS, + Context.MODE_PRIVATE); + } + + // test for initial run of this fragment + private boolean checkForFirstRun() { + String isFirstRun = getDefaultStepsPrefs().getString(FIRST_RUN_KEY, null); + if (isFirstRun == null) { + getDefaultStepsPrefs().edit().putString(FIRST_RUN_KEY, "first_run_initialized").commit(); + return true; + } + return false; + } + + private int getDefaultSteps(Preference pref) { + if (pref == null || !(pref instanceof ListPreference)) { + // unlikely + return -1; + } + String key = pref.getKey(); + String value = getDefaultStepsPrefs().getString(key, null); + if (value == null) { + // unlikely + return -1; + } + return Integer.parseInt(value); + } + + // on the initial run, let's store true device defaults in sharedPrefs + private void saveDefaultSteps(Preference volPref, int defaultSteps) { + String key = volPref.getKey(); + getDefaultStepsPrefs().edit().putString(key, String.valueOf(defaultSteps)).commit(); + } + + private void updateVolumeStepPrefs(Preference pref, int steps) { + if (pref == null || !(pref instanceof ListPreference)) { + return; + } + final ListPreference listPref = (ListPreference) pref; + listPref.setSummary(String.valueOf(steps)); + listPref.setValue(String.valueOf(steps)); + } + + private void commitVolumeSteps(Preference pref, int steps) { + Settings.System.putInt(getActivity().getContentResolver(), pref.getKey(), steps); + mAudioManager.setStreamMaxVolume(volume_map.get(pref.getKey()), steps); + updateVolumeStepPrefs(pref, steps); + Log.i(TAG, "Volume steps:" + pref.getKey() + "" + String.valueOf(steps)); + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.CHERISH_SETTINGS; + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.cherish_settings_volume_steps); +}