diff options
author | Doris Ling <dling@google.com> | 2016-11-30 17:33:50 -0800 |
---|---|---|
committer | Doris Ling <dling@google.com> | 2016-12-01 17:24:05 -0800 |
commit | 1b3ec0474875ce754c3f7cd80f762b091d48b627 (patch) | |
tree | f4dac358a756c0fb36de2bf223385ca602929e78 /src/com/android/settings | |
parent | 7aad8a97a4726360bb616f103d0b4051df2617a6 (diff) | |
download | packages_apps_Settings-1b3ec0474875ce754c3f7cd80f762b091d48b627.tar.gz packages_apps_Settings-1b3ec0474875ce754c3f7cd80f762b091d48b627.tar.bz2 packages_apps_Settings-1b3ec0474875ce754c3f7cd80f762b091d48b627.zip |
Update SoundSettings to extend DashboardFragment.
- initial round of refactoring SoundSettings to use DashboardFragment.
- add controller for Cast, Do not disturb, Alarm volume, Media volume,
Ring volume and Notification volume.
Bug: 32276590
Test: make RunSettingsRoboTests
Change-Id: I5c02a344bff5117bfce93d7ccac650fccc82d2b0
Diffstat (limited to 'src/com/android/settings')
11 files changed, 713 insertions, 194 deletions
diff --git a/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java new file mode 100644 index 0000000000..f513882018 --- /dev/null +++ b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.accounts.AccountRestrictionHelper; +import com.android.settings.core.PreferenceController; +import com.android.settingslib.RestrictedPreference; + +/** + * Base class for preference controller that handles preference that enforce adjust volume + * restriction + */ +public abstract class AdjustVolumeRestrictedPreferenceController extends PreferenceController { + + private AccountRestrictionHelper mHelper; + + public AdjustVolumeRestrictedPreferenceController(Context context) { + this(context, new AccountRestrictionHelper(context)); + } + + @VisibleForTesting + AdjustVolumeRestrictedPreferenceController(Context context, AccountRestrictionHelper helper) { + super(context); + mHelper = helper; + } + + @Override + public void updateState(Preference preference) { + if (!(preference instanceof RestrictedPreference)) { + return; + } + mHelper.enforceRestrictionOnPreference((RestrictedPreference) preference, + UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId()); + } + +} diff --git a/src/com/android/settings/notification/AlarmVolumePreferenceController.java b/src/com/android/settings/notification/AlarmVolumePreferenceController.java new file mode 100644 index 0000000000..e9c4b57f8b --- /dev/null +++ b/src/com/android/settings/notification/AlarmVolumePreferenceController.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.media.AudioManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.notification.VolumeSeekBarPreference.Callback; + +public class AlarmVolumePreferenceController extends + VolumeSeekBarPreferenceController { + + private static final String KEY_ALARM_VOLUME = "alarm_volume"; + private AudioHelper mHelper; + + public AlarmVolumePreferenceController(Context context, Callback callback, + Lifecycle lifecycle) { + this(context, callback, lifecycle, new AudioHelper(context)); + } + + @VisibleForTesting + AlarmVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle, + AudioHelper helper) { + super(context, callback, lifecycle); + mHelper = helper; + } + + @Override + public boolean isAvailable() { + return !mHelper.isSingleVolume(); + } + + @Override + public String getPreferenceKey() { + return KEY_ALARM_VOLUME; + } + + @Override + public int getAudioStream() { + return AudioManager.STREAM_ALARM; + } + + @Override + public int getMuteIcon() { + return com.android.internal.R.drawable.ic_audio_alarm_mute; + } + +} diff --git a/src/com/android/settings/notification/AudioHelper.java b/src/com/android/settings/notification/AudioHelper.java new file mode 100644 index 0000000000..ea5bc4ace2 --- /dev/null +++ b/src/com/android/settings/notification/AudioHelper.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.media.AudioSystem; + +/** + * Helper class to wrap API for testing + */ +public class AudioHelper { + + private Context mContext; + + public AudioHelper(Context context) { + mContext = context; + } + + public boolean isSingleVolume() { + return AudioSystem.isSingleVolume(mContext); + } + +} diff --git a/src/com/android/settings/notification/CastPreferenceController.java b/src/com/android/settings/notification/CastPreferenceController.java new file mode 100644 index 0000000000..2ec78213ff --- /dev/null +++ b/src/com/android/settings/notification/CastPreferenceController.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.Utils; +import com.android.settings.core.PreferenceController; +import java.util.List; + +public class CastPreferenceController extends PreferenceController { + + private static final String KEY_WIFI_DISPLAY = "wifi_display"; + + public CastPreferenceController(Context context) { + super(context); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_WIFI_DISPLAY; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void updateNonIndexableKeys(List<String> keys) { + if (!Utils.isVoiceCapable(mContext)) { + keys.add(KEY_WIFI_DISPLAY); + } + } + +} diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java new file mode 100644 index 0000000000..fb8dba55ae --- /dev/null +++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.media.AudioManager; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.notification.VolumeSeekBarPreference.Callback; + +public class MediaVolumePreferenceController extends + VolumeSeekBarPreferenceController { + + private static final String KEY_MEDIA_VOLUME = "media_volume"; + + public MediaVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle) { + super(context, callback, lifecycle); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_MEDIA_VOLUME; + } + + @Override + public int getAudioStream() { + return AudioManager.STREAM_MUSIC; + } + + @Override + public int getMuteIcon() { + return com.android.internal.R.drawable.ic_audio_media_mute; + } + +} diff --git a/src/com/android/settings/notification/NotificationVolumePreferenceController.java b/src/com/android/settings/notification/NotificationVolumePreferenceController.java new file mode 100644 index 0000000000..e4759d71ab --- /dev/null +++ b/src/com/android/settings/notification/NotificationVolumePreferenceController.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.media.AudioManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.Utils; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.notification.VolumeSeekBarPreference.Callback; + +public class NotificationVolumePreferenceController extends + RingVolumePreferenceController { + + private static final String KEY_NOTIFICATION_VOLUME = "notification_volume"; + private AudioHelper mHelper; + + public NotificationVolumePreferenceController(Context context, Callback callback, + Lifecycle lifecycle) { + this(context, callback, lifecycle, new AudioHelper(context)); + } + + @VisibleForTesting + NotificationVolumePreferenceController(Context context, + VolumeSeekBarPreference.Callback callback, Lifecycle lifecycle, AudioHelper helper) { + super(context, callback, lifecycle); + mHelper = helper; + } + + + @Override + public boolean isAvailable() { + return !Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume(); + } + + @Override + public String getPreferenceKey() { + return KEY_NOTIFICATION_VOLUME; + } + + @Override + public int getAudioStream() { + return AudioManager.STREAM_NOTIFICATION; + } + + @Override + public int getMuteIcon() { + return com.android.internal.R.drawable.ic_audio_ring_notif_mute; + } + +} diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java new file mode 100644 index 0000000000..2297837680 --- /dev/null +++ b/src/com/android/settings/notification/RingVolumePreferenceController.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Vibrator; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.Utils; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.notification.VolumeSeekBarPreference.Callback; + +import java.util.Objects; + +public class RingVolumePreferenceController extends VolumeSeekBarPreferenceController { + + private static final String TAG = "RingVolumeController"; + private static final String KEY_RING_VOLUME = "ring_volume"; + + private AudioManager mAudioManager; + private Vibrator mVibrator; + private int mRingerMode = -1; + private ComponentName mSuppressor; + private final RingReceiver mReceiver = new RingReceiver(); + private final H mHandler = new H(); + private AudioHelper mHelper; + + public RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle) { + this(context, callback, lifecycle, new AudioHelper(context)); + } + + @VisibleForTesting + RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle, + AudioHelper helper) { + super(context, callback, lifecycle); + mHelper = helper; + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + if (mVibrator != null && !mVibrator.hasVibrator()) { + mVibrator = null; + } + updateRingerMode(); + } + + @Override + public void onResume() { + super.onResume(); + mReceiver.register(true); + updateEffectsSuppressor(); + updatePreferenceIcon(); + } + + @Override + public void onPause() { + super.onPause(); + mReceiver.register(false); + } + + @Override + public String getPreferenceKey() { + return KEY_RING_VOLUME; + } + + @Override + public boolean isAvailable() { + return Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume(); + } + + @Override + public int getAudioStream() { + return AudioManager.STREAM_RING; + } + + @Override + public int getMuteIcon() { + return com.android.internal.R.drawable.ic_audio_ring_notif_mute; + } + + private void updateRingerMode() { + final int ringerMode = mAudioManager.getRingerModeInternal(); + if (mRingerMode == ringerMode) return; + mRingerMode = ringerMode; + updatePreferenceIcon(); + } + + private boolean wasRingerModeVibrate() { + return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT + && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0; + } + + private void updateEffectsSuppressor() { + final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); + if (Objects.equals(suppressor, mSuppressor)) return; + mSuppressor = suppressor; + if (mPreference != null) { + final String text = suppressor != null ? + mContext.getString(com.android.internal.R.string.muted_by, + getSuppressorCaption(suppressor)) : null; + mPreference.setSuppressionText(text); + } + updatePreferenceIcon(); + } + + private void updatePreferenceIcon() { + if (mPreference != null) { + mPreference.showIcon(mSuppressor != null + ? com.android.internal.R.drawable.ic_audio_ring_notif_mute + : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate() + ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate + : com.android.internal.R.drawable.ic_audio_ring_notif); + } + } + + private String getSuppressorCaption(ComponentName suppressor) { + final PackageManager pm = mContext.getPackageManager(); + try { + final ServiceInfo info = pm.getServiceInfo(suppressor, 0); + if (info != null) { + final CharSequence seq = info.loadLabel(pm); + if (seq != null) { + final String str = seq.toString().trim(); + if (str.length() > 0) { + return str; + } + } + } + } catch (Throwable e) { + Log.w(TAG, "Error loading suppressor caption", e); + } + return suppressor.getPackageName(); + } + + private final class H extends Handler { + private static final int UPDATE_EFFECTS_SUPPRESSOR = 1; + private static final int UPDATE_RINGER_MODE = 2; + + private H() { + super(Looper.getMainLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case UPDATE_EFFECTS_SUPPRESSOR: + updateEffectsSuppressor(); + break; + case UPDATE_RINGER_MODE: + updateRingerMode(); + break; + } + } + } + + private class RingReceiver extends BroadcastReceiver { + private boolean mRegistered; + + public void register(boolean register) { + if (mRegistered == register) return; + if (register) { + final IntentFilter filter = new IntentFilter(); + filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); + filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); + mContext.registerReceiver(this, filter); + } else { + mContext.unregisterReceiver(this); + } + mRegistered = register; + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { + mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); + } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { + mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); + } + } + } + +} diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java index 1ec3164243..1adfdd87a5 100644 --- a/src/com/android/settings/notification/SoundSettings.java +++ b/src/com/android/settings/notification/SoundSettings.java @@ -20,21 +20,16 @@ import android.annotation.UserIdInt; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.app.DialogFragment; import android.app.FragmentManager; import android.app.NotificationManager; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; import android.database.ContentObserver; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; import android.media.AudioManager; import android.media.AudioSystem; import android.media.Ringtone; @@ -47,10 +42,7 @@ import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.os.UserManager; -import android.os.Vibrator; import android.preference.SeekBarVolumizer; -import android.provider.MediaStore; -import android.provider.OpenableColumns; import android.provider.SearchIndexableResource; import android.provider.Settings; import android.support.v7.preference.Preference; @@ -64,38 +56,30 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.RingtonePreference; import com.android.settings.DefaultRingtonePreference; -import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; +import com.android.settings.core.PreferenceController; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.SummaryLoader; import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.Indexable; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedPreference; +import com.android.settingslib.drawer.CategoryKey; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; -import static android.content.ContentProvider.getUriWithoutUserId; -import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; - -public class SoundSettings extends SettingsPreferenceFragment - implements Indexable, OnPreferenceChangeListener { +public class SoundSettings extends DashboardFragment + implements OnPreferenceChangeListener { private static final String TAG = "SoundSettings"; - private static final String KEY_MEDIA_VOLUME = "media_volume"; - private static final String KEY_ALARM_VOLUME = "alarm_volume"; - private static final String KEY_RING_VOLUME = "ring_volume"; - private static final String KEY_NOTIFICATION_VOLUME = "notification_volume"; private static final String KEY_PHONE_RINGTONE = "ringtone"; private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; private static final String KEY_ALARM_RINGTONE = "alarm_ringtone"; private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing"; - private static final String KEY_WIFI_DISPLAY = "wifi_display"; - private static final String KEY_ZEN_MODE = "zen_mode"; private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings"; private static final String KEY_WORK_CATEGORY = "sound_work_settings_section"; @@ -107,34 +91,19 @@ public class SoundSettings extends SettingsPreferenceFragment private static final String SELECTED_PREFERENCE_KEY = "selected_preference"; private static final int REQUEST_CODE = 200; - private static final String[] RESTRICTED_KEYS = { - KEY_MEDIA_VOLUME, - KEY_ALARM_VOLUME, - KEY_RING_VOLUME, - KEY_NOTIFICATION_VOLUME, - KEY_ZEN_MODE, - }; - private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); private final H mHandler = new H(); private final SettingsObserver mSettingsObserver = new SettingsObserver(); - private final Receiver mReceiver = new Receiver(); - private final ArrayList<VolumeSeekBarPreference> mVolumePrefs = new ArrayList<>(); private Context mContext; private boolean mVoiceCapable; - private Vibrator mVibrator; - private AudioManager mAudioManager; - private VolumeSeekBarPreference mRingOrNotificationPreference; private Preference mPhoneRingtonePreference; private Preference mNotificationRingtonePreference; private Preference mAlarmRingtonePreference; private TwoStatePreference mVibrateWhenRinging; - private ComponentName mSuppressor; - private int mRingerMode = -1; private PreferenceGroup mWorkPreferenceCategory; private TwoStatePreference mWorkUsePersonalSounds; @@ -161,36 +130,6 @@ public class SoundSettings extends SettingsPreferenceFragment mUserManager = UserManager.get(getContext()); mVoiceCapable = Utils.isVoiceCapable(mContext); - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); - if (mVibrator != null && !mVibrator.hasVibrator()) { - mVibrator = null; - } - - addPreferencesFromResource(R.xml.sound_settings); - - initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC, - com.android.internal.R.drawable.ic_audio_media_mute); - initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM, - com.android.internal.R.drawable.ic_audio_alarm_mute); - if (mVoiceCapable) { - mRingOrNotificationPreference = - initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING, - com.android.internal.R.drawable.ic_audio_ring_notif_mute); - removePreference(KEY_NOTIFICATION_VOLUME); - } else { - mRingOrNotificationPreference = - initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION, - com.android.internal.R.drawable.ic_audio_ring_notif_mute); - removePreference(KEY_RING_VOLUME); - } - - if (!shouldShowRingtoneSettings()) { - removePreference(KEY_RING_VOLUME); - removePreference(KEY_NOTIFICATION_VOLUME); - removePreference(KEY_ALARM_VOLUME); - } - // Enable link to CMAS app settings depending on the value in config.xml. boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean( com.android.internal.R.bool.config_cellBroadcastAppLinks); @@ -211,8 +150,6 @@ public class SoundSettings extends SettingsPreferenceFragment } initRingtones(); initVibrateWhenRinging(); - updateRingerMode(); - updateEffectsSuppressor(); if (savedInstanceState != null) { String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null); @@ -227,26 +164,7 @@ public class SoundSettings extends SettingsPreferenceFragment super.onResume(); lookupRingtoneNames(); mSettingsObserver.register(true); - mReceiver.register(true); - updateRingOrNotificationPreference(); - updateEffectsSuppressor(); - for (VolumeSeekBarPreference volumePref : mVolumePrefs) { - volumePref.onActivityResume(); - } - - final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext, - UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId()); - final boolean hasBaseRestriction = RestrictedLockUtils.hasBaseUserRestriction(mContext, - UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId()); - for (String key : RESTRICTED_KEYS) { - Preference pref = findPreference(key); - if (pref != null) { - pref.setEnabled(!hasBaseRestriction); - } - if (pref instanceof RestrictedPreference && !hasBaseRestriction) { - ((RestrictedPreference) pref).setDisabledByAdmin(admin); - } - } + RestrictedPreference broadcastSettingsPref = (RestrictedPreference) findPreference( KEY_CELL_BROADCAST_SETTINGS); if (broadcastSettingsPref != null) { @@ -272,12 +190,8 @@ public class SoundSettings extends SettingsPreferenceFragment @Override public void onPause() { super.onPause(); - for (VolumeSeekBarPreference volumePref : mVolumePrefs) { - volumePref.onActivityPause(); - } mVolumeCallback.stopSample(); mSettingsObserver.register(false); - mReceiver.register(false); } @Override @@ -292,6 +206,36 @@ public class SoundSettings extends SettingsPreferenceFragment } @Override + protected String getCategoryKey() { + return CategoryKey.CATEGORY_SOUND; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.sound_settings; + } + + @Override + protected List<PreferenceController> getPreferenceControllers(Context context) { + final List<PreferenceController> controllers = new ArrayList<>(); + Lifecycle lifecycle = getLifecycle(); + controllers.add(new CastPreferenceController(context)); + controllers.add(new ZenModePreferenceController(context)); + // === Volumes === + controllers.add(new AlarmVolumePreferenceController(context, mVolumeCallback, lifecycle)); + controllers.add(new MediaVolumePreferenceController(context, mVolumeCallback, lifecycle)); + controllers.add( + new NotificationVolumePreferenceController(context, mVolumeCallback, lifecycle)); + controllers.add(new RingVolumePreferenceController(context, mVolumeCallback, lifecycle)); + return controllers; + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (mRequestPreference != null) { mRequestPreference.onActivityResult(requestCode, resultCode, data); @@ -336,68 +280,7 @@ public class SoundSettings extends SettingsPreferenceFragment // === Volumes === - private VolumeSeekBarPreference initVolumePreference(String key, int stream, int muteIcon) { - final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key); - volumePref.setCallback(mVolumeCallback); - volumePref.setStream(stream); - mVolumePrefs.add(volumePref); - volumePref.setMuteIcon(muteIcon); - return volumePref; - } - - private void updateRingOrNotificationPreference() { - mRingOrNotificationPreference.showIcon(mSuppressor != null - ? com.android.internal.R.drawable.ic_audio_ring_notif_mute - : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate() - ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate - : com.android.internal.R.drawable.ic_audio_ring_notif); - } - - private boolean wasRingerModeVibrate() { - return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT - && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0; - } - - private void updateRingerMode() { - final int ringerMode = mAudioManager.getRingerModeInternal(); - if (mRingerMode == ringerMode) return; - mRingerMode = ringerMode; - updateRingOrNotificationPreference(); - } - - private void updateEffectsSuppressor() { - final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); - if (Objects.equals(suppressor, mSuppressor)) return; - mSuppressor = suppressor; - if (mRingOrNotificationPreference != null) { - final String text = suppressor != null ? - mContext.getString(com.android.internal.R.string.muted_by, - getSuppressorCaption(suppressor)) : null; - mRingOrNotificationPreference.setSuppressionText(text); - } - updateRingOrNotificationPreference(); - } - - private String getSuppressorCaption(ComponentName suppressor) { - final PackageManager pm = mContext.getPackageManager(); - try { - final ServiceInfo info = pm.getServiceInfo(suppressor, 0); - if (info != null) { - final CharSequence seq = info.loadLabel(pm); - if (seq != null) { - final String str = seq.toString().trim(); - if (str.length() > 0) { - return str; - } - } - } - } catch (Throwable e) { - Log.w(TAG, "Error loading suppressor caption", e); - } - return suppressor.getPackageName(); - } - - private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { + final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { private SeekBarVolumizer mCurrent; @Override @@ -568,12 +451,6 @@ public class SoundSettings extends SettingsPreferenceFragment case STOP_SAMPLE: mVolumeCallback.stopSample(); break; - case UPDATE_EFFECTS_SUPPRESSOR: - updateEffectsSuppressor(); - break; - case UPDATE_RINGER_MODE: - updateRingerMode(); - break; case UPDATE_ALARM_RINGTONE: mAlarmRingtonePreference.setSummary((CharSequence) msg.obj); break; @@ -581,33 +458,6 @@ public class SoundSettings extends SettingsPreferenceFragment } } - private class Receiver extends BroadcastReceiver { - private boolean mRegistered; - - public void register(boolean register) { - if (mRegistered == register) return; - if (register) { - final IntentFilter filter = new IntentFilter(); - filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); - filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); - mContext.registerReceiver(this, filter); - } else { - mContext.unregisterReceiver(this); - } - mRegistered = register; - } - - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { - mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); - } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { - mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); - } - } - } - // === Summary === private static class SummaryProvider extends BroadcastReceiver @@ -684,12 +534,13 @@ public class SoundSettings extends SettingsPreferenceFragment public List<String> getNonIndexableKeys(Context context) { final ArrayList<String> rt = new ArrayList<String>(); - if (Utils.isVoiceCapable(context)) { - rt.add(KEY_NOTIFICATION_VOLUME); - } else { - rt.add(KEY_RING_VOLUME); + new NotificationVolumePreferenceController( + context, null /* Callback */, null /* Lifecycle */).updateNonIndexableKeys(rt); + new RingVolumePreferenceController( + context, null /* Callback */, null /* Lifecycle */).updateNonIndexableKeys(rt); + new CastPreferenceController(context).updateNonIndexableKeys(rt); + if (!Utils.isVoiceCapable(context)) { rt.add(KEY_PHONE_RINGTONE); - rt.add(KEY_WIFI_DISPLAY); rt.add(KEY_VIBRATE_WHEN_RINGING); } diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java index 7b02cae408..5ab1d29a26 100644 --- a/src/com/android/settings/notification/VolumeSeekBarPreference.java +++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java @@ -146,7 +146,9 @@ public class VolumeSeekBarPreference extends SeekBarPreference { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { super.onProgressChanged(seekBar, progress, fromTouch); - mCallback.onStreamValueChanged(mStream, progress); + if (mCallback != null) { + mCallback.onStreamValueChanged(mStream, progress); + } } private void updateIconView() { diff --git a/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java new file mode 100644 index 0000000000..adc86b89da --- /dev/null +++ b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; + +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; +import com.android.settings.notification.VolumeSeekBarPreference.Callback; + +/** + * Base class for preference controller that handles VolumeSeekBarPreference + */ +public abstract class VolumeSeekBarPreferenceController extends + AdjustVolumeRestrictedPreferenceController implements LifecycleObserver, OnResume, OnPause { + + protected VolumeSeekBarPreference mPreference; + protected VolumeSeekBarPreference.Callback mVolumePreferenceCallback; + + public VolumeSeekBarPreferenceController(Context context, Callback callback, + Lifecycle lifecycle) { + super(context); + mVolumePreferenceCallback = callback; + if (lifecycle != null) { + lifecycle.addObserver(this); + } + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + if (isAvailable()) { + mPreference = (VolumeSeekBarPreference) screen.findPreference(getPreferenceKey()); + mPreference.setCallback(mVolumePreferenceCallback); + mPreference.setStream(getAudioStream()); + mPreference.setMuteIcon(getMuteIcon()); + } + } + + @Override + public void onResume() { + if (mPreference != null) { + mPreference.onActivityResume(); + } + } + + @Override + public void onPause() { + if (mPreference != null) { + mPreference.onActivityPause(); + } + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + protected abstract int getAudioStream(); + + protected abstract int getMuteIcon(); + +} diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java new file mode 100644 index 0000000000..e554732e6b --- /dev/null +++ b/src/com/android/settings/notification/ZenModePreferenceController.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 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.notification; + +import android.content.Context; +import android.support.v7.preference.Preference; + +public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController { + + private static final String KEY_ZEN_MODE = "zen_mode"; + + public ZenModePreferenceController(Context context) { + super(context); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_ZEN_MODE; + } + + @Override + public boolean isAvailable() { + return true; + } + +} |