diff options
Diffstat (limited to 'src/com/android/settings')
3 files changed, 220 insertions, 1 deletions
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java index 7fffb765f1..1005d20f52 100644 --- a/src/com/android/settings/notification/SoundSettings.java +++ b/src/com/android/settings/notification/SoundSettings.java @@ -26,16 +26,22 @@ import android.os.UserHandle; import android.preference.SeekBarVolumizer; import android.provider.SearchIndexableResource; import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.text.TextUtils; +import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.RingtonePreference; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.sound.HandsFreeProfileOutputPreferenceController; +import com.android.settings.sound.MediaOutputPreferenceController; import com.android.settings.widget.PreferenceCategoryController; +import com.android.settings.widget.UpdatableListPreferenceDialogFragment; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.core.lifecycle.Lifecycle; import java.util.ArrayList; @@ -68,6 +74,9 @@ public class SoundSettings extends DashboardFragment { }; private RingtonePreference mRequestPreference; + private UpdatableListPreferenceDialogFragment mDialogFragment; + private String mMediaOutputControllerKey; + private String mHfpOutputControllerKey; @Override public int getMetricsCategory() { @@ -82,6 +91,11 @@ public class SoundSettings extends DashboardFragment { if (!TextUtils.isEmpty(selectedPreference)) { mRequestPreference = (RingtonePreference) findPreference(selectedPreference); } + + UpdatableListPreferenceDialogFragment dialogFragment = + (UpdatableListPreferenceDialogFragment) getFragmentManager() + .findFragmentByTag(TAG); + mDialogFragment = dialogFragment; } } @@ -112,6 +126,23 @@ public class SoundSettings extends DashboardFragment { } @Override + public void onDisplayPreferenceDialog(Preference preference) { + final int metricsCategory; + if (mHfpOutputControllerKey.equals(preference.getKey())) { + metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_HFP_DEVICES; + } else if (mMediaOutputControllerKey.equals(preference.getKey())) { + metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES; + } else { + metricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN; + } + + mDialogFragment = UpdatableListPreferenceDialogFragment. + newInstance(preference.getKey(), metricsCategory); + mDialogFragment.setTargetFragment(this, 0); + mDialogFragment.show(getFragmentManager(), TAG); + } + + @Override protected String getLogTag() { return TAG; } @@ -152,6 +183,14 @@ public class SoundSettings extends DashboardFragment { volumeControllers.add(use(NotificationVolumePreferenceController.class)); volumeControllers.add(use(CallVolumePreferenceController.class)); + use(MediaOutputPreferenceController.class).setCallback(listPreference -> + onPreferenceDataChanged(listPreference)); + mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey(); + use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference -> + onPreferenceDataChanged(listPreference)); + mHfpOutputControllerKey = + use(HandsFreeProfileOutputPreferenceController.class).getPreferenceKey(); + for (VolumeSeekBarPreferenceController controller : volumeControllers) { controller.setCallback(mVolumeCallback); getLifecycle().addObserver(controller); @@ -287,4 +326,10 @@ public class SoundSettings extends DashboardFragment { workSoundController.enableWorkSync(); } } -} + + private void onPreferenceDataChanged(ListPreference preference) { + if (mDialogFragment != null) { + mDialogFragment.onListPreferenceUpdated(preference); + } + } +}
\ No newline at end of file diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index dde2b3012e..6d9d3a46ed 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -78,6 +78,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont protected final LocalBluetoothProfileManager mProfileManager; protected int mSelectedIndex; protected Preference mPreference; + protected AudioSwitchCallback mAudioSwitchPreferenceCallback; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; private final LocalBluetoothManager mLocalBluetoothManager; @@ -85,6 +86,10 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont private final WiredHeadsetBroadcastReceiver mReceiver; private final Handler mHandler; + public interface AudioSwitchCallback { + void onPreferenceDataChanged(ListPreference preference); + } + public AudioSwitchPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); @@ -207,6 +212,10 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { } + public void setCallback(AudioSwitchCallback callback) { + mAudioSwitchPreferenceCallback = callback; + } + protected boolean isStreamFromOutputDevice(int streamType, int device) { return (device & mAudioManager.getDevicesForStream(streamType)) != 0; } @@ -335,6 +344,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont listPreference.setEntryValues(mediaValues); listPreference.setValueIndex(mSelectedIndex); listPreference.setSummary(mediaOutputs[mSelectedIndex]); + mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference); } private int getConnectedDeviceIndex(String hardwareAddress) { diff --git a/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java b/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java new file mode 100644 index 0000000000..93697781d9 --- /dev/null +++ b/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java @@ -0,0 +1,164 @@ +/* + * Copyright 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.settings.widget; + +import android.app.AlertDialog; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.support.annotation.VisibleForTesting; +import android.support.v14.preference.PreferenceDialogFragment; +import android.support.v7.preference.ListPreference; +import android.widget.ArrayAdapter; +import com.android.settingslib.core.instrumentation.Instrumentable; + +import java.util.ArrayList; + +/** + * {@link PreferenceDialogFragment} that updates the available options + * when {@code onListPreferenceUpdated} is called." + */ +public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragment implements + Instrumentable { + + private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index"; + private static final String SAVE_STATE_ENTRIES = + "UpdatableListPreferenceDialogFragment.entries"; + private static final String SAVE_STATE_ENTRY_VALUES = + "UpdatableListPreferenceDialogFragment.entryValues"; + private static final String METRICS_CATEGORY_KEY = "metrics_category_key"; + private ArrayAdapter mAdapter; + private int mClickedDialogEntryIndex; + private ArrayList<CharSequence> mEntries; + private CharSequence[] mEntryValues; + private int mMetricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN; + + public static UpdatableListPreferenceDialogFragment newInstance( + String key, int metricsCategory) { + UpdatableListPreferenceDialogFragment fragment = + new UpdatableListPreferenceDialogFragment(); + Bundle args = new Bundle(1); + args.putString(ARG_KEY, key); + args.putInt(METRICS_CATEGORY_KEY, metricsCategory); + fragment.setArguments(args); + return fragment; + } + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final Bundle bundle = getArguments(); + mMetricsCategory = + bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN); + if (savedInstanceState == null) { + mEntries = new ArrayList<>(); + setPreferenceData(getListPreference()); + } else { + mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0); + mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES); + mEntryValues = + savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex); + outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries); + outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues); + } + + @Override + public void onDialogClosed(boolean positiveResult) { + final ListPreference preference = getListPreference(); + if (positiveResult && mClickedDialogEntryIndex >= 0) { + final String value = mEntryValues[mClickedDialogEntryIndex].toString(); + if (preference.callChangeListener(value)) { + preference.setValue(value); + } + } + } + + @VisibleForTesting + void setAdapter(ArrayAdapter adapter) { + mAdapter = adapter; + } + + @VisibleForTesting + void setEntries(ArrayList<CharSequence> entries) { + mEntries = entries; + } + + @VisibleForTesting + ArrayAdapter getAdapter() { + return mAdapter; + } + + @VisibleForTesting + void setMetricsCategory(Bundle bundle) { + mMetricsCategory = + bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + super.onPrepareDialogBuilder(builder); + final TypedArray a = getContext().obtainStyledAttributes( + null, + com.android.internal.R.styleable.AlertDialog, + com.android.internal.R.attr.alertDialogStyle, 0); + + mAdapter = new ArrayAdapter<>( + getContext(), + a.getResourceId( + com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout, + com.android.internal.R.layout.select_dialog_singlechoice), + mEntries); + + builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex, + (dialog, which) -> { + mClickedDialogEntryIndex = which; + onClick(dialog, -1); + dialog.dismiss(); + }); + builder.setPositiveButton(null, null); + a.recycle(); + } + + @Override + public int getMetricsCategory() { + return mMetricsCategory; + } + + private ListPreference getListPreference() { + return (ListPreference) getPreference(); + } + + private void setPreferenceData(ListPreference preference) { + mEntries.clear(); + mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue()); + for (CharSequence entry : preference.getEntries()) { + mEntries.add(entry); + } + mEntryValues = preference.getEntryValues(); + } + + public void onListPreferenceUpdated(ListPreference preference) { + if (mAdapter != null) { + setPreferenceData(preference); + mAdapter.notifyDataSetChanged(); + } + } +} |