blob: dd08eea48b1bd94d82aa76677b0d66c0d402351f [file] [log] [blame]
/*
* Copyright (C) 2020 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.deskclock.settings
import android.annotation.TargetApi
import android.app.NotificationManager
import android.content.Context
import android.content.Context.AUDIO_SERVICE
import android.content.Context.NOTIFICATION_SERVICE
import android.database.ContentObserver
import android.media.AudioManager
import android.media.AudioManager.STREAM_ALARM
import android.os.Build
import android.provider.Settings
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import android.widget.SeekBar
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import com.android.deskclock.R
import com.android.deskclock.RingtonePreviewKlaxon
import com.android.deskclock.Utils
import com.android.deskclock.data.DataModel
class AlarmVolumePreference(context: Context?, attrs: AttributeSet?) : Preference(context!!, attrs) {
private lateinit var mSeekbar: SeekBar
private var mPreviewPlaying = false
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val context: Context = getContext()
val audioManager: AudioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
// Disable click feedback for this preference.
holder.itemView.setClickable(false)
// Minimum volume for alarm is not 0, calculate it.
val maxVolume = audioManager.getStreamMaxVolume(STREAM_ALARM) - getMinVolume(audioManager)
mSeekbar = holder.findViewById(R.id.alarm_volume_slider) as SeekBar
mSeekbar.setMax(maxVolume)
mSeekbar.setProgress(audioManager.getStreamVolume(STREAM_ALARM) -
getMinVolume(audioManager))
(holder.findViewById(R.id.alarm_icon) as ImageView)
.setImageResource(R.drawable.ic_alarm_small)
onSeekbarChanged()
val volumeObserver: ContentObserver = object : ContentObserver(mSeekbar.getHandler()) {
override fun onChange(selfChange: Boolean) {
// Volume was changed elsewhere, update our slider.
mSeekbar.setProgress(audioManager.getStreamVolume(STREAM_ALARM) -
getMinVolume(audioManager))
}
}
mSeekbar.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
context.getContentResolver().registerContentObserver(Settings.System.CONTENT_URI,
true, volumeObserver)
}
override fun onViewDetachedFromWindow(v: View) {
context.getContentResolver().unregisterContentObserver(volumeObserver)
}
})
mSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
val newVolume = progress + getMinVolume(audioManager)
audioManager.setStreamVolume(STREAM_ALARM, newVolume, 0)
}
onSeekbarChanged()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
if (!mPreviewPlaying) {
// If we are not currently playing, start.
RingtonePreviewKlaxon
.start(context, DataModel.dataModel.defaultAlarmRingtoneUri)
mPreviewPlaying = true
seekBar.postDelayed(Runnable {
RingtonePreviewKlaxon.stop(context)
mPreviewPlaying = false
}, ALARM_PREVIEW_DURATION_MS)
}
}
})
}
private fun onSeekbarChanged() {
mSeekbar.setEnabled(doesDoNotDisturbAllowAlarmPlayback())
}
private fun doesDoNotDisturbAllowAlarmPlayback(): Boolean {
return !Utils.isNOrLater || doesDoNotDisturbAllowAlarmPlaybackNPlus()
}
@TargetApi(Build.VERSION_CODES.N)
private fun doesDoNotDisturbAllowAlarmPlaybackNPlus(): Boolean {
val notificationManager =
getContext().getSystemService(NOTIFICATION_SERVICE) as NotificationManager
return notificationManager.getCurrentInterruptionFilter() !=
NotificationManager.INTERRUPTION_FILTER_NONE
}
private fun getMinVolume(audioManager: AudioManager): Int {
return if (Utils.isPOrLater) audioManager.getStreamMinVolume(STREAM_ALARM) else 0
}
companion object {
private const val ALARM_PREVIEW_DURATION_MS: Long = 2000
}
}