1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.deskclock.settings; 18 19 import android.annotation.TargetApi; 20 import android.app.NotificationManager; 21 import android.content.Context; 22 import android.database.ContentObserver; 23 import android.media.AudioManager; 24 import android.os.Build; 25 import android.provider.Settings; 26 import android.support.v7.preference.Preference; 27 import android.support.v7.preference.PreferenceViewHolder; 28 import android.util.AttributeSet; 29 import android.view.View; 30 import android.widget.ImageView; 31 import android.widget.SeekBar; 32 33 import com.android.deskclock.R; 34 import com.android.deskclock.RingtonePreviewKlaxon; 35 import com.android.deskclock.Utils; 36 import com.android.deskclock.data.DataModel; 37 38 import static android.content.Context.AUDIO_SERVICE; 39 import static android.content.Context.NOTIFICATION_SERVICE; 40 import static android.media.AudioManager.STREAM_ALARM; 41 42 public class AlarmVolumePreference extends Preference { 43 44 private static final long ALARM_PREVIEW_DURATION_MS = 2000; 45 46 private SeekBar mSeekbar; 47 private ImageView mAlarmIcon; 48 private boolean mPreviewPlaying; 49 50 public AlarmVolumePreference(Context context, AttributeSet attrs) { 51 super(context, attrs); 52 } 53 54 @Override 55 public void onBindViewHolder(PreferenceViewHolder holder) { 56 super.onBindViewHolder(holder); 57 58 final Context context = getContext(); 59 final AudioManager audioManager = (AudioManager) context.getSystemService(AUDIO_SERVICE); 60 61 // Disable click feedback for this preference. 62 holder.itemView.setClickable(false); 63 64 mSeekbar = (SeekBar) holder.findViewById(R.id.alarm_volume_slider); 65 mSeekbar.setMax(audioManager.getStreamMaxVolume(STREAM_ALARM)); 66 mSeekbar.setProgress(audioManager.getStreamVolume(STREAM_ALARM)); 67 mAlarmIcon = (ImageView) holder.findViewById(R.id.alarm_icon); 68 onSeekbarChanged(); 69 70 final ContentObserver volumeObserver = new ContentObserver(mSeekbar.getHandler()) { 71 @Override 72 public void onChange(boolean selfChange) { 73 // Volume was changed elsewhere, update our slider. 74 mSeekbar.setProgress(audioManager.getStreamVolume(STREAM_ALARM)); 75 } 76 }; 77 78 mSeekbar.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { 79 @Override 80 public void onViewAttachedToWindow(View v) { 81 context.getContentResolver().registerContentObserver(Settings.System.CONTENT_URI, 82 true, volumeObserver); 83 } 84 85 @Override 86 public void onViewDetachedFromWindow(View v) { 87 context.getContentResolver().unregisterContentObserver(volumeObserver); 88 } 89 }); 90 91 mSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 92 @Override 93 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 94 if (fromUser) { 95 audioManager.setStreamVolume(STREAM_ALARM, progress, 0); 96 } 97 onSeekbarChanged(); 98 } 99 100 @Override 101 public void onStartTrackingTouch(SeekBar seekBar) { 102 } 103 104 @Override 105 public void onStopTrackingTouch(SeekBar seekBar) { 106 if (!mPreviewPlaying && seekBar.getProgress() != 0) { 107 // If we are not currently playing and progress is set to non-zero, start. 108 RingtonePreviewKlaxon.start( 109 context, DataModel.getDataModel().getDefaultAlarmRingtoneUri()); 110 mPreviewPlaying = true; 111 seekBar.postDelayed(new Runnable() { 112 @Override 113 public void run() { 114 RingtonePreviewKlaxon.stop(context); 115 mPreviewPlaying = false; 116 } 117 }, ALARM_PREVIEW_DURATION_MS); 118 } 119 } 120 }); 121 } 122 123 private void onSeekbarChanged() { 124 mSeekbar.setEnabled(doesDoNotDisturbAllowAlarmPlayback()); 125 mAlarmIcon.setImageResource(mSeekbar.getProgress() == 0 ? 126 R.drawable.ic_alarm_off_24dp : R.drawable.ic_alarm_small); 127 } 128 129 private boolean doesDoNotDisturbAllowAlarmPlayback() { 130 return !Utils.isNOrLater() || doesDoNotDisturbAllowAlarmPlaybackNPlus(); 131 } 132 133 @TargetApi(Build.VERSION_CODES.N) 134 private boolean doesDoNotDisturbAllowAlarmPlaybackNPlus() { 135 final NotificationManager notificationManager = (NotificationManager) 136 getContext().getSystemService(NOTIFICATION_SERVICE); 137 return notificationManager.getCurrentInterruptionFilter() != 138 NotificationManager.INTERRUPTION_FILTER_NONE; 139 } 140 }