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 | |
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
19 files changed, 1449 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; + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java new file mode 100644 index 0000000000..76e5a223ae --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java @@ -0,0 +1,115 @@ +/* + * 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.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.accounts.AccountRestrictionHelper; +import com.android.settingslib.RestrictedPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AdjustVolumeRestrictedPreferenceControllerTest { + + @Mock + private AccountRestrictionHelper mAccountHelper; + + private Context mContext; + private AdjustVolumeRestrictedPreferenceControllerTestable mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowApplication shadowContext = ShadowApplication.getInstance(); + mContext = spy(shadowContext.getApplicationContext()); + mController = + new AdjustVolumeRestrictedPreferenceControllerTestable(mContext, mAccountHelper); + } + + @Test + public void updateState_hasBaseRestriction_shouldDisable() { + RestrictedPreference preference = mock(RestrictedPreference.class); + when(mAccountHelper.hasBaseUserRestriction( + eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt())).thenReturn(true); + + mController.updateState(preference); + + assertThat(preference.isEnabled()).isFalse(); + } + + @Test + public void updateState_NoBaseRestriction_shouldCheckRestriction() { + RestrictedPreference preference = spy(new RestrictedPreference(mContext)); + + when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(null); + when(mAccountHelper.hasBaseUserRestriction( + eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt())).thenReturn(false); + doCallRealMethod().when(mAccountHelper).enforceRestrictionOnPreference( + eq(preference), eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt()); + + mController.updateState(preference); + + verify(preference).checkRestrictionAndSetDisabled( + eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt()); + } + + private class AdjustVolumeRestrictedPreferenceControllerTestable extends + AdjustVolumeRestrictedPreferenceController { + AdjustVolumeRestrictedPreferenceControllerTestable(Context context, + AccountRestrictionHelper helper) { + super(context, helper); + } + + @Override + public String getPreferenceKey() { + return null; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public boolean isAvailable() { + return true; + } + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java new file mode 100644 index 0000000000..11370e3dc5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java @@ -0,0 +1,72 @@ +/* + * 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.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AlarmVolumePreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private AudioHelper mHelper; + + private AlarmVolumePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController = new AlarmVolumePreferenceController(mContext, null, null, mHelper); + } + + @Test + public void isAvailable_singleVolume_shouldReturnFalse() { + when(mHelper.isSingleVolume()).thenReturn(true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_notSingleVolume_shouldReturnTrue() { + when(mHelper.isSingleVolume()).thenReturn(false); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void getAudioStream_shouldReturnAlarm() { + assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_ALARM); + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java new file mode 100644 index 0000000000..7f1888ab7e --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java @@ -0,0 +1,84 @@ +/* + * 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.telephony.TelephonyManager; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class CastPreferenceControllerTest { + + @Mock + private TelephonyManager mTelephonyManager; + + private Context mContext; + private CastPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowApplication shadowContext = ShadowApplication.getInstance(); + shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager); + mContext = shadowContext.getApplicationContext(); + mController = new CastPreferenceController(mContext); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void updateNonIndexableKeys_voiceCapable_shouldNotUpdate() { + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + final List<String> keys = new ArrayList<>(); + + mController.updateNonIndexableKeys(keys); + + assertThat(keys).isEmpty(); + } + + @Test + public void updateNonIndexableKeys_voiceIncapable_shouldUpdate() { + when(mTelephonyManager.isVoiceCapable()).thenReturn(false); + final List<String> keys = new ArrayList<>(); + + mController.updateNonIndexableKeys(keys); + + assertThat(keys).isNotEmpty(); + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java new file mode 100644 index 0000000000..9c16937d01 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java @@ -0,0 +1,61 @@ +/* + * 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.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class MediaVolumePreferenceControllerTest { + + @Mock + private Context mContext; + + private MediaVolumePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController = new MediaVolumePreferenceController(mContext, null, null); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void getAudioStream_shouldReturnMusic() { + assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_MUSIC); + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java new file mode 100644 index 0000000000..e0aa88ed62 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java @@ -0,0 +1,93 @@ +/* + * 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 android.os.Vibrator; +import android.telephony.TelephonyManager; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class NotificationVolumePreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private AudioHelper mHelper; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private AudioManager mAudioManager; + @Mock + private Vibrator mVibrator; + + private NotificationVolumePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mContext.getSystemService(Context.VIBRATOR_SERVICE)).thenReturn(mVibrator); + mController = new NotificationVolumePreferenceController(mContext, null, null, mHelper); + } + + @Test + public void isAvailable_singleVolume_shouldReturnFalse() { + when(mHelper.isSingleVolume()).thenReturn(true); + when(mTelephonyManager.isVoiceCapable()).thenReturn(false); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_voiceCapable_shouldReturnFalse() { + when(mHelper.isSingleVolume()).thenReturn(false); + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_notSingleVolume_notVoiceCapable_shouldReturnTrue() { + when(mHelper.isSingleVolume()).thenReturn(false); + when(mTelephonyManager.isVoiceCapable()).thenReturn(false); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void getAudioStream_shouldReturnNotification() { + assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_NOTIFICATION); + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java new file mode 100644 index 0000000000..2d54cef521 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java @@ -0,0 +1,104 @@ +/* + * 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.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.os.Vibrator; +import android.telephony.TelephonyManager; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class RingVolumePreferenceControllerTest { + + @Mock + private AudioHelper mHelper; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private AudioManager mAudioManager; + @Mock + private Vibrator mVibrator; + @Mock + private NotificationManager mNotificationManager; + @Mock + private ComponentName mSuppressor; + + private Context mContext; + private RingVolumePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowApplication shadowContext = ShadowApplication.getInstance(); + shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager); + shadowContext.setSystemService(Context.AUDIO_SERVICE, mAudioManager); + shadowContext.setSystemService(Context.VIBRATOR_SERVICE, mVibrator); + shadowContext.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager); + mContext = shadowContext.getApplicationContext(); + when(mNotificationManager.getEffectsSuppressor()).thenReturn(mSuppressor); + mController = new RingVolumePreferenceController(mContext, null, null, mHelper); + } + + @Test + public void isAvailable_singleVolume_shouldReturnFalse() { + when(mHelper.isSingleVolume()).thenReturn(true); + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_notVoiceCapable_shouldReturnFalse() { + when(mHelper.isSingleVolume()).thenReturn(false); + when(mTelephonyManager.isVoiceCapable()).thenReturn(false); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_notSingleVolume_VoiceCapable_shouldReturnTrue() { + when(mHelper.isSingleVolume()).thenReturn(false); + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void getAudioStream_shouldReturnRing() { + assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_RING); + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java new file mode 100644 index 0000000000..2d0aaebb6a --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java @@ -0,0 +1,153 @@ +/* + * 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.preference.SeekBarVolumizer; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class VolumeSeekBarPreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private PreferenceScreen mScreen; + @Mock + private VolumeSeekBarPreference mPreference; + @Mock + private VolumeSeekBarPreference.Callback mCallback; + + private VolumeSeekBarPreferenceControllerTestable mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mScreen.findPreference(anyString())).thenReturn(mPreference); + mController = + new VolumeSeekBarPreferenceControllerTestable(mContext, mCallback); + } + + @Test + public void displayPreference_available_shouldUpdatePreference() { + mController.displayPreference(mScreen); + + verify(mPreference).setCallback(mCallback); + verify(mPreference).setStream(mController.AUDIO_STREAM); + verify(mPreference).setMuteIcon(mController.MUTE_ICON); + } + + @Test + public void displayPreference_notAvailable_shouldNotUpdatePreference() { + mController = + new VolumeSeekBarPreferenceControllerTestable(mContext, mCallback, false); + + mController.displayPreference(mScreen); + + verify(mPreference, never()).setCallback(any(VolumeSeekBarPreference.Callback.class)); + verify(mPreference, never()).setStream(anyInt()); + verify(mPreference, never()).setMuteIcon(anyInt()); + } + + @Test + public void onResume_shouldResumePreference() { + mController.displayPreference(mScreen); + + mController.onResume(); + + verify(mPreference).onActivityResume(); + } + + @Test + public void onPause_shouldPausePreference() { + mController.displayPreference(mScreen); + + mController.onPause(); + + verify(mPreference).onActivityPause(); + } + + private class VolumeSeekBarPreferenceControllerTestable extends + VolumeSeekBarPreferenceController { + + private final static int AUDIO_STREAM = 1; + private final static int MUTE_ICON = 2; + + private boolean mAvailable; + + VolumeSeekBarPreferenceControllerTestable(Context context, + VolumeSeekBarPreference.Callback callback) { + this(context, callback, true); + } + + VolumeSeekBarPreferenceControllerTestable(Context context, + VolumeSeekBarPreference.Callback callback, boolean available) { + super(context, callback, null); + mAvailable = available; + } + + @Override + public String getPreferenceKey() { + return null; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public boolean isAvailable() { + return mAvailable; + } + + @Override + public int getAudioStream() { + return AUDIO_STREAM; + } + + @Override + public int getMuteIcon() { + return MUTE_ICON; + } + + private void setAvailable(boolean available) { + + } + } + +} diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java new file mode 100644 index 0000000000..7b53a86624 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java @@ -0,0 +1,54 @@ +/* + * 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 com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class ZenModePreferenceControllerTest { + + @Mock + private Context mContext; + + private ZenModePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController = new ZenModePreferenceController(mContext); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + +} |