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
This commit is contained in:
Doris Ling
2016-11-30 17:33:50 -08:00
parent 7aad8a97a4
commit 1b3ec04748
19 changed files with 1448 additions and 193 deletions

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -20,21 +20,16 @@ import android.annotation.UserIdInt;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.AudioSystem; import android.media.AudioSystem;
import android.media.Ringtone; import android.media.Ringtone;
@@ -47,10 +42,7 @@ import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.os.Vibrator;
import android.preference.SeekBarVolumizer; import android.preference.SeekBarVolumizer;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.provider.SearchIndexableResource; import android.provider.SearchIndexableResource;
import android.provider.Settings; import android.provider.Settings;
import android.support.v7.preference.Preference; 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.R;
import com.android.settings.RingtonePreference; import com.android.settings.RingtonePreference;
import com.android.settings.DefaultRingtonePreference; import com.android.settings.DefaultRingtonePreference;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 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.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.drawer.CategoryKey;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
import static android.content.ContentProvider.getUriWithoutUserId; public class SoundSettings extends DashboardFragment
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; implements OnPreferenceChangeListener {
public class SoundSettings extends SettingsPreferenceFragment
implements Indexable, OnPreferenceChangeListener {
private static final String TAG = "SoundSettings"; 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_PHONE_RINGTONE = "ringtone";
private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
private static final String KEY_ALARM_RINGTONE = "alarm_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_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_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
private static final String KEY_WORK_CATEGORY = "sound_work_settings_section"; 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 String SELECTED_PREFERENCE_KEY = "selected_preference";
private static final int REQUEST_CODE = 200; 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 static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds
private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback();
private final H mHandler = new H(); private final H mHandler = new H();
private final SettingsObserver mSettingsObserver = new SettingsObserver(); private final SettingsObserver mSettingsObserver = new SettingsObserver();
private final Receiver mReceiver = new Receiver();
private final ArrayList<VolumeSeekBarPreference> mVolumePrefs = new ArrayList<>();
private Context mContext; private Context mContext;
private boolean mVoiceCapable; private boolean mVoiceCapable;
private Vibrator mVibrator;
private AudioManager mAudioManager;
private VolumeSeekBarPreference mRingOrNotificationPreference;
private Preference mPhoneRingtonePreference; private Preference mPhoneRingtonePreference;
private Preference mNotificationRingtonePreference; private Preference mNotificationRingtonePreference;
private Preference mAlarmRingtonePreference; private Preference mAlarmRingtonePreference;
private TwoStatePreference mVibrateWhenRinging; private TwoStatePreference mVibrateWhenRinging;
private ComponentName mSuppressor;
private int mRingerMode = -1;
private PreferenceGroup mWorkPreferenceCategory; private PreferenceGroup mWorkPreferenceCategory;
private TwoStatePreference mWorkUsePersonalSounds; private TwoStatePreference mWorkUsePersonalSounds;
@@ -161,36 +130,6 @@ public class SoundSettings extends SettingsPreferenceFragment
mUserManager = UserManager.get(getContext()); mUserManager = UserManager.get(getContext());
mVoiceCapable = Utils.isVoiceCapable(mContext); 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. // Enable link to CMAS app settings depending on the value in config.xml.
boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean( boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
com.android.internal.R.bool.config_cellBroadcastAppLinks); com.android.internal.R.bool.config_cellBroadcastAppLinks);
@@ -211,8 +150,6 @@ public class SoundSettings extends SettingsPreferenceFragment
} }
initRingtones(); initRingtones();
initVibrateWhenRinging(); initVibrateWhenRinging();
updateRingerMode();
updateEffectsSuppressor();
if (savedInstanceState != null) { if (savedInstanceState != null) {
String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null); String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null);
@@ -227,26 +164,7 @@ public class SoundSettings extends SettingsPreferenceFragment
super.onResume(); super.onResume();
lookupRingtoneNames(); lookupRingtoneNames();
mSettingsObserver.register(true); 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( RestrictedPreference broadcastSettingsPref = (RestrictedPreference) findPreference(
KEY_CELL_BROADCAST_SETTINGS); KEY_CELL_BROADCAST_SETTINGS);
if (broadcastSettingsPref != null) { if (broadcastSettingsPref != null) {
@@ -272,12 +190,8 @@ public class SoundSettings extends SettingsPreferenceFragment
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
for (VolumeSeekBarPreference volumePref : mVolumePrefs) {
volumePref.onActivityPause();
}
mVolumeCallback.stopSample(); mVolumeCallback.stopSample();
mSettingsObserver.register(false); mSettingsObserver.register(false);
mReceiver.register(false);
} }
@Override @Override
@@ -291,6 +205,36 @@ public class SoundSettings extends SettingsPreferenceFragment
return super.onPreferenceTreeClick(preference); return super.onPreferenceTreeClick(preference);
} }
@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 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mRequestPreference != null) { if (mRequestPreference != null) {
@@ -336,68 +280,7 @@ public class SoundSettings extends SettingsPreferenceFragment
// === Volumes === // === Volumes ===
private VolumeSeekBarPreference initVolumePreference(String key, int stream, int muteIcon) { final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback {
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 {
private SeekBarVolumizer mCurrent; private SeekBarVolumizer mCurrent;
@Override @Override
@@ -568,12 +451,6 @@ public class SoundSettings extends SettingsPreferenceFragment
case STOP_SAMPLE: case STOP_SAMPLE:
mVolumeCallback.stopSample(); mVolumeCallback.stopSample();
break; break;
case UPDATE_EFFECTS_SUPPRESSOR:
updateEffectsSuppressor();
break;
case UPDATE_RINGER_MODE:
updateRingerMode();
break;
case UPDATE_ALARM_RINGTONE: case UPDATE_ALARM_RINGTONE:
mAlarmRingtonePreference.setSummary((CharSequence) msg.obj); mAlarmRingtonePreference.setSummary((CharSequence) msg.obj);
break; 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 === // === Summary ===
private static class SummaryProvider extends BroadcastReceiver private static class SummaryProvider extends BroadcastReceiver
@@ -684,12 +534,13 @@ public class SoundSettings extends SettingsPreferenceFragment
public List<String> getNonIndexableKeys(Context context) { public List<String> getNonIndexableKeys(Context context) {
final ArrayList<String> rt = new ArrayList<String>(); final ArrayList<String> rt = new ArrayList<String>();
if (Utils.isVoiceCapable(context)) { new NotificationVolumePreferenceController(
rt.add(KEY_NOTIFICATION_VOLUME); context, null /* Callback */, null /* Lifecycle */).updateNonIndexableKeys(rt);
} else { new RingVolumePreferenceController(
rt.add(KEY_RING_VOLUME); context, null /* Callback */, null /* Lifecycle */).updateNonIndexableKeys(rt);
new CastPreferenceController(context).updateNonIndexableKeys(rt);
if (!Utils.isVoiceCapable(context)) {
rt.add(KEY_PHONE_RINGTONE); rt.add(KEY_PHONE_RINGTONE);
rt.add(KEY_WIFI_DISPLAY);
rt.add(KEY_VIBRATE_WHEN_RINGING); rt.add(KEY_VIBRATE_WHEN_RINGING);
} }

View File

@@ -146,8 +146,10 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
@Override @Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
super.onProgressChanged(seekBar, progress, fromTouch); super.onProgressChanged(seekBar, progress, fromTouch);
if (mCallback != null) {
mCallback.onStreamValueChanged(mStream, progress); mCallback.onStreamValueChanged(mStream, progress);
} }
}
private void updateIconView() { private void updateIconView() {
if (mIconView == null) return; if (mIconView == null) return;

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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();
}
}