summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2018-05-16 22:11:57 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-05-16 22:11:57 +0000
commit89777940b322690110689c7122f639c24ddfa82e (patch)
tree9bfe2facc1231cfdf0ca8a20ce1fe368c67affc4
parent225abb0dfad71e96479a77976c9804c5b5e656f9 (diff)
parenta80f5b947e751fe09db33a0f4f3d4330c29e246d (diff)
downloadTvSettings-89777940b322690110689c7122f639c24ddfa82e.tar.gz
Merge "Improved surround sound settings for ATV." into pi-dev
-rw-r--r--Settings/res/values/arrays.xml12
-rw-r--r--Settings/res/xml/sound.xml23
-rw-r--r--Settings/src/com/android/tv/settings/device/sound/SoundFormatPreferenceController.java141
-rw-r--r--Settings/src/com/android/tv/settings/device/sound/SoundFragment.java120
4 files changed, 265 insertions, 31 deletions
diff --git a/Settings/res/values/arrays.xml b/Settings/res/values/arrays.xml
index 41e4b99dd..810cc1be5 100644
--- a/Settings/res/values/arrays.xml
+++ b/Settings/res/values/arrays.xml
@@ -225,18 +225,18 @@
<item>FFFFFFFF</item>
</string-array>
- <!-- List entries for controlling surround sound passthrough setting [CHAR LIMIT=50] -->
- <string-array name="surround_sound_entries">
- <item>Auto</item>
- <item>Always</item>
- <item>Never</item>
+ <!-- List entries for controlling surround sound passthrough setting -->
+ <string-array name="surround_sound_entries" translatable="false">
+ <item>@string/surround_sound_auto_summary</item>
+ <item>@string/surround_sound_none_summary</item>
+ <item>@string/surround_sound_manual_summary</item>
</string-array>
<!-- Entry values for surround sound preference -->
<string-array name="surround_sound_entry_values" translatable="false">
<item>auto</item>
- <item>always</item>
<item>never</item>
+ <item>manual</item>
</string-array>
<!-- Type of EAP method -->
diff --git a/Settings/res/xml/sound.xml b/Settings/res/xml/sound.xml
index 9b064c38b..b5f7aed4f 100644
--- a/Settings/res/xml/sound.xml
+++ b/Settings/res/xml/sound.xml
@@ -23,12 +23,21 @@
android:persistent="true"
android:title="@string/device_sound_effects"/>
- <ListPreference
- android:key="surround_passthrough"
- android:persistent="true"
- android:entries="@array/surround_sound_entries"
- android:entryValues="@array/surround_sound_entry_values"
- android:title="@string/device_surround_sound"
- android:summary="%s" />
+ <PreferenceCategory
+ android:key="surround_sound_category"
+ android:title="@string/surround_sound_category_title">
+
+ <ListPreference
+ android:key="surround_passthrough"
+ android:persistent="true"
+ android:entries="@array/surround_sound_entries"
+ android:entryValues="@array/surround_sound_entry_values"
+ android:title="@string/surround_sound_select_formats"
+ android:summary="%s"
+ android:dialogMessage="@string/surround_sound_auto_info"/>
+
+ <!-- Switches for each surround sound format programmatically added here. -->
+
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/Settings/src/com/android/tv/settings/device/sound/SoundFormatPreferenceController.java b/Settings/src/com/android/tv/settings/device/sound/SoundFormatPreferenceController.java
new file mode 100644
index 000000000..d36feee24
--- /dev/null
+++ b/Settings/src/com/android/tv/settings/device/sound/SoundFormatPreferenceController.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.tv.settings.device.sound;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * Controller for the surround sound switch preferences.
+ */
+public class SoundFormatPreferenceController extends AbstractPreferenceController {
+
+ private static final String TAG = "SoundFormatController";
+
+ private int mFormatId;
+ private AudioManager mAudioManager;
+ private Map<Integer, Boolean> mReportedFormats;
+
+ public SoundFormatPreferenceController(Context context, int formatId) {
+ super(context);
+ mFormatId = formatId;
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mReportedFormats = mAudioManager.getReportedSurroundFormats();
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return SoundFragment.KEY_SURROUND_SOUND_FORMAT_PREFIX + mFormatId;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference.getKey().equals(getPreferenceKey())) {
+ preference.setEnabled(getFormatPreferencesEnabledState());
+ ((SwitchPreference) preference).setChecked(getFormatPreferenceCheckedState());
+ }
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (preference.getKey().equals(getPreferenceKey())) {
+ setSurroundManualFormatsSetting(((SwitchPreference) preference).isChecked());
+ }
+ return super.handlePreferenceTreeClick(preference);
+ }
+
+ /**
+ * @return checked state of a surround sound format switch based on passthrough setting and
+ * audio manager state for the format.
+ */
+ private boolean getFormatPreferenceCheckedState() {
+ switch (SoundFragment.getSurroundPassthroughSetting(mContext)) {
+ case SoundFragment.VAL_SURROUND_SOUND_NEVER:
+ return false;
+ case SoundFragment.VAL_SURROUND_SOUND_ALWAYS:
+ return true;
+ case SoundFragment.VAL_SURROUND_SOUND_AUTO:
+ return isReportedFormat();
+ case SoundFragment.VAL_SURROUND_SOUND_MANUAL:
+ return getFormatsEnabledInManualMode().contains(mFormatId);
+ default: return false;
+ }
+ }
+
+ /** @return true if the format checkboxes should be enabled, i.e. in manual mode. */
+ private boolean getFormatPreferencesEnabledState() {
+ return SoundFragment.getSurroundPassthroughSetting(mContext)
+ == SoundFragment.VAL_SURROUND_SOUND_MANUAL;
+ }
+
+ /** @return the formats that are enabled in manual mode, from global settings */
+ private HashSet<Integer> getFormatsEnabledInManualMode() {
+ HashSet<Integer> formats = new HashSet<>();
+ String enabledFormats = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
+ if (enabledFormats == null) {
+ // Starting with Android P passthrough setting ALWAYS has been replaced with MANUAL.
+ // In that case all formats will be enabled when in MANUAL mode.
+ formats.addAll(mAudioManager.getSurroundFormats().keySet());
+ } else {
+ try {
+ Arrays.stream(enabledFormats.split(",")).mapToInt(Integer::parseInt)
+ .forEach(formats::add);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS misformatted.", e);
+ }
+ }
+ return formats;
+ }
+
+ /**
+ * Writes enabled/disabled state for a given format to the global settings.
+ */
+ private void setSurroundManualFormatsSetting(boolean enabled) {
+ HashSet<Integer> formats = getFormatsEnabledInManualMode();
+ if (enabled) {
+ formats.add(mFormatId);
+ } else {
+ formats.remove(mFormatId);
+ }
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
+ TextUtils.join(",", formats));
+ }
+
+ /** @return true if the given format is reported by the device. */
+ private boolean isReportedFormat() {
+ return mReportedFormats != null && mReportedFormats.get(mFormatId) != null;
+ }
+}
diff --git a/Settings/src/com/android/tv/settings/device/sound/SoundFragment.java b/Settings/src/com/android/tv/settings/device/sound/SoundFragment.java
index 626fd3819..b929d0235 100644
--- a/Settings/src/com/android/tv/settings/device/sound/SoundFragment.java
+++ b/Settings/src/com/android/tv/settings/device/sound/SoundFragment.java
@@ -18,41 +18,61 @@ package com.android.tv.settings.device.sound;
import android.content.ContentResolver;
import android.content.Context;
+import android.media.AudioFormat;
import android.media.AudioManager;
import android.os.Bundle;
import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.TwoStatePreference;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.tv.settings.PreferenceControllerFragment;
import com.android.tv.settings.R;
-import com.android.tv.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
/**
* The "Sound" screen in TV Settings.
*/
-public class SoundFragment extends SettingsPreferenceFragment implements
+public class SoundFragment extends PreferenceControllerFragment implements
Preference.OnPreferenceChangeListener {
- private static final String KEY_SOUND_EFFECTS = "sound_effects";
- private static final String KEY_SURROUND_PASSTHROUGH = "surround_passthrough";
+ static final String KEY_SOUND_EFFECTS = "sound_effects";
+ static final String KEY_SURROUND_PASSTHROUGH = "surround_passthrough";
+ static final String KEY_SURROUND_SOUND_CATEGORY = "surround_sound_category";
+ static final String KEY_SURROUND_SOUND_FORMAT_PREFIX = "surround_sound_format_";
- private static final String VAL_SURROUND_SOUND_AUTO = "auto";
- private static final String VAL_SURROUND_SOUND_ALWAYS = "always";
- private static final String VAL_SURROUND_SOUND_NEVER = "never";
+ static final String VAL_SURROUND_SOUND_AUTO = "auto";
+ static final String VAL_SURROUND_SOUND_NEVER = "never";
+ static final String VAL_SURROUND_SOUND_ALWAYS = "always";
+ static final String VAL_SURROUND_SOUND_MANUAL = "manual";
private AudioManager mAudioManager;
+ private Map<Integer, Boolean> mFormats;
+ private List<AbstractPreferenceController> mPreferenceControllers;
+ private PreferenceCategory mSurroundSoundCategoryPref;
public static SoundFragment newInstance() {
return new SoundFragment();
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
- super.onCreate(savedInstanceState);
+ public void onAttach(Context context) {
+ mAudioManager = context.getSystemService(AudioManager.class);
+ mFormats = mAudioManager.getSurroundFormats();
+ super.onAttach(context);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.sound;
}
@Override
@@ -64,8 +84,65 @@ public class SoundFragment extends SettingsPreferenceFragment implements
final ListPreference surroundPref =
(ListPreference) findPreference(KEY_SURROUND_PASSTHROUGH);
- surroundPref.setValue(getSurroundPassthroughSetting());
+ surroundPref.setValue(getSurroundPassthroughSetting(getContext()));
surroundPref.setOnPreferenceChangeListener(this);
+
+ mSurroundSoundCategoryPref =
+ (PreferenceCategory) findPreference(KEY_SURROUND_SOUND_CATEGORY);
+ createFormatPreferences();
+ updateFormatPreferencesStates();
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> onCreatePreferenceControllers(Context context) {
+ mPreferenceControllers = new ArrayList<>(mFormats.size());
+ for (Map.Entry<Integer, Boolean> format : mFormats.entrySet()) {
+ mPreferenceControllers.add(new SoundFormatPreferenceController(context,
+ format.getKey() /*formatId*/));
+ }
+ return mPreferenceControllers;
+ }
+
+ /** Creates and adds switches for each surround sound format. */
+ private void createFormatPreferences() {
+ for (Map.Entry<Integer, Boolean> format : mFormats.entrySet()) {
+ int formatId = format.getKey();
+ boolean enabled = format.getValue();
+ SwitchPreference pref = new SwitchPreference(getPreferenceManager().getContext());
+ pref.setTitle(getFormatDisplayName(formatId));
+ pref.setKey(KEY_SURROUND_SOUND_FORMAT_PREFIX + formatId);
+ pref.setChecked(enabled);
+ mSurroundSoundCategoryPref.addPreference(pref);
+ }
+ }
+
+ /**
+ * @return the display name for each surround sound format.
+ */
+ private String getFormatDisplayName(int formatId) {
+ switch (formatId) {
+ case AudioFormat.ENCODING_AC3:
+ return getContext().getResources().getString(R.string.surround_sound_format_ac3);
+ case AudioFormat.ENCODING_E_AC3:
+ return getContext().getResources().getString(R.string.surround_sound_format_e_ac3);
+ case AudioFormat.ENCODING_DTS:
+ return getContext().getResources().getString(R.string.surround_sound_format_dts);
+ case AudioFormat.ENCODING_DTS_HD:
+ return getContext().getResources().getString(R.string.surround_sound_format_dts_hd);
+ default:
+ // Fallback in case new formats have been added that we don't know of.
+ return AudioFormat.toDisplayName(formatId);
+ }
+ }
+
+ private void updateFormatPreferencesStates() {
+ for (AbstractPreferenceController controller : mPreferenceControllers) {
+ Preference preference = mSurroundSoundCategoryPref.findPreference(
+ controller.getPreferenceKey());
+ if (preference != null) {
+ controller.updateState(preference);
+ }
+ }
}
@Override
@@ -85,15 +162,20 @@ public class SoundFragment extends SettingsPreferenceFragment implements
case VAL_SURROUND_SOUND_AUTO:
setSurroundPassthroughSetting(Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
break;
+ case VAL_SURROUND_SOUND_NEVER:
+ setSurroundPassthroughSetting(Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER);
+ break;
case VAL_SURROUND_SOUND_ALWAYS:
setSurroundPassthroughSetting(Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS);
break;
- case VAL_SURROUND_SOUND_NEVER:
- setSurroundPassthroughSetting(Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER);
+ case VAL_SURROUND_SOUND_MANUAL:
+ setSurroundPassthroughSetting(Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL);
break;
default:
- throw new IllegalArgumentException("Unknown surround sound pref value");
+ throw new IllegalArgumentException("Unknown surround sound pref value: "
+ + selection);
}
+ updateFormatPreferencesStates();
return true;
}
return true;
@@ -123,8 +205,8 @@ public class SoundFragment extends SettingsPreferenceFragment implements
Settings.Global.ENCODED_SURROUND_OUTPUT, newVal);
}
- private String getSurroundPassthroughSetting() {
- final int value = Settings.Global.getInt(getContext().getContentResolver(),
+ static String getSurroundPassthroughSetting(Context context) {
+ final int value = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.ENCODED_SURROUND_OUTPUT,
Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
@@ -132,10 +214,12 @@ public class SoundFragment extends SettingsPreferenceFragment implements
case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
default:
return VAL_SURROUND_SOUND_AUTO;
- case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
- return VAL_SURROUND_SOUND_ALWAYS;
case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
return VAL_SURROUND_SOUND_NEVER;
+ // On Android P ALWAYS is replaced by MANUAL.
+ case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
+ case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
+ return VAL_SURROUND_SOUND_MANUAL;
}
}