[Catalyst] Ring volume migration (2/n)
NO_IFTTT=migrate other feature from controller Bug: 373978964 Test: atest SeparateRingVolumePreferenceTest Flag: com.android.settings.flags.catalyst_sound_screen Change-Id: I4aba4c6688e4284fb23570ac999acf7b4039854d
This commit is contained in:
@@ -18,7 +18,14 @@ package com.android.settings.notification
|
|||||||
|
|
||||||
import android.app.INotificationManager
|
import android.app.INotificationManager
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
|
import android.app.NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Context.NOTIFICATION_SERVICE
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION
|
||||||
import android.media.AudioManager.RINGER_MODE_NORMAL
|
import android.media.AudioManager.RINGER_MODE_NORMAL
|
||||||
import android.media.AudioManager.RINGER_MODE_SILENT
|
import android.media.AudioManager.RINGER_MODE_SILENT
|
||||||
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
||||||
@@ -36,6 +43,8 @@ import com.android.settingslib.datastore.NoOpKeyedObservable
|
|||||||
import com.android.settingslib.metadata.PersistentPreference
|
import com.android.settingslib.metadata.PersistentPreference
|
||||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
import com.android.settingslib.metadata.PreferenceIconProvider
|
import com.android.settingslib.metadata.PreferenceIconProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||||
|
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||||
import com.android.settingslib.metadata.PreferenceMetadata
|
import com.android.settingslib.metadata.PreferenceMetadata
|
||||||
import com.android.settingslib.metadata.RangeValue
|
import com.android.settingslib.metadata.RangeValue
|
||||||
import com.android.settingslib.metadata.ReadWritePermit
|
import com.android.settingslib.metadata.ReadWritePermit
|
||||||
@@ -49,19 +58,18 @@ open class SeparateRingVolumePreference :
|
|||||||
RangeValue,
|
RangeValue,
|
||||||
PreferenceAvailabilityProvider,
|
PreferenceAvailabilityProvider,
|
||||||
PreferenceIconProvider,
|
PreferenceIconProvider,
|
||||||
|
PreferenceLifecycleProvider,
|
||||||
PreferenceRestrictionMixin {
|
PreferenceRestrictionMixin {
|
||||||
|
|
||||||
|
private var broadcastReceiver: BroadcastReceiver? = null
|
||||||
|
|
||||||
override val key: String
|
override val key: String
|
||||||
get() = KEY
|
get() = KEY
|
||||||
|
|
||||||
override val title: Int
|
override val title: Int
|
||||||
get() = R.string.separate_ring_volume_option_title
|
get() = R.string.separate_ring_volume_option_title
|
||||||
|
|
||||||
override fun getIcon(context: Context) =
|
override fun getIcon(context: Context) = context.getIconRes()
|
||||||
when {
|
|
||||||
VolumeHelper.isMuted(context, STREAM_RING) -> getMuteIcon(context)
|
|
||||||
else -> R.drawable.ic_ring_volume
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isAvailable(context: Context) = !createAudioHelper(context).isSingleVolume
|
override fun isAvailable(context: Context) = !createAudioHelper(context).isSingleVolume
|
||||||
|
|
||||||
@@ -103,67 +111,77 @@ open class SeparateRingVolumePreference :
|
|||||||
super.bind(preference, metadata)
|
super.bind(preference, metadata)
|
||||||
(preference as VolumeSeekBarPreference).apply {
|
(preference as VolumeSeekBarPreference).apply {
|
||||||
setStream(STREAM_RING)
|
setStream(STREAM_RING)
|
||||||
setMuteIcon(getMuteIcon(preference.context))
|
setMuteIcon(context.getIconRes())
|
||||||
setListener { updateContentDescription(this) }
|
updateContentDescription(context.getContentDescription())
|
||||||
setSuppressionText(getSuppressionText(preference.context))
|
setListener { updateContentDescription(context.getContentDescription()) }
|
||||||
|
setSuppressionText(context.getSuppressionText())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart(context: PreferenceLifecycleContext) {
|
||||||
|
super.onStart(context)
|
||||||
|
val receiver =
|
||||||
|
object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(receiverContext: Context, intent: Intent) {
|
||||||
|
context.notifyPreferenceChange(KEY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.registerReceiver(
|
||||||
|
receiver,
|
||||||
|
IntentFilter().apply {
|
||||||
|
addAction(ACTION_EFFECTS_SUPPRESSOR_CHANGED)
|
||||||
|
addAction(INTERNAL_RINGER_MODE_CHANGED_ACTION)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
broadcastReceiver = receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop(context: PreferenceLifecycleContext) {
|
||||||
|
super.onStop(context)
|
||||||
|
broadcastReceiver?.let { context.unregisterReceiver(it) }
|
||||||
|
}
|
||||||
|
|
||||||
open fun createAudioHelper(context: Context) = AudioHelper(context)
|
open fun createAudioHelper(context: Context) = AudioHelper(context)
|
||||||
|
|
||||||
private fun updateContentDescription(preference: VolumeSeekBarPreference) {
|
|
||||||
val context = preference.context
|
|
||||||
val ringerMode = getEffectiveRingerMode(context)
|
|
||||||
when (ringerMode) {
|
|
||||||
RINGER_MODE_VIBRATE ->
|
|
||||||
preference.updateContentDescription(
|
|
||||||
context.getString(R.string.ringer_content_description_vibrate_mode)
|
|
||||||
)
|
|
||||||
RINGER_MODE_SILENT ->
|
|
||||||
preference.updateContentDescription(
|
|
||||||
context.getString(R.string.ringer_content_description_silent_mode)
|
|
||||||
)
|
|
||||||
else -> preference.updateContentDescription(preference.title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMuteIcon(context: Context): Int {
|
|
||||||
val ringerMode = getEffectiveRingerMode(context)
|
|
||||||
return when (ringerMode) {
|
|
||||||
RINGER_MODE_NORMAL -> R.drawable.ic_ring_volume
|
|
||||||
RINGER_MODE_VIBRATE -> R.drawable.ic_volume_ringer_vibrate
|
|
||||||
else -> R.drawable.ic_ring_volume_off
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getEffectiveRingerMode(context: Context): Int {
|
|
||||||
val hasVibrator = context.getSystemService(Vibrator::class.java)?.hasVibrator() ?: false
|
|
||||||
val ringerMode = createAudioHelper(context).ringerModeInternal
|
|
||||||
return when {
|
|
||||||
!hasVibrator && ringerMode == RINGER_MODE_VIBRATE -> RINGER_MODE_SILENT
|
|
||||||
else -> ringerMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSuppressionText(context: Context): String? {
|
|
||||||
val suppressor = NotificationManager.from(context).getEffectsSuppressor()
|
|
||||||
val notificationManager =
|
|
||||||
INotificationManager.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE)
|
|
||||||
)
|
|
||||||
val hints = notificationManager.hintsFromListenerNoToken
|
|
||||||
return when {
|
|
||||||
hintsMatch(hints) -> SuppressorHelper.getSuppressionText(context, suppressor)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hintsMatch(hints: Int) =
|
|
||||||
(hints and HINT_HOST_DISABLE_CALL_EFFECTS) != 0 ||
|
|
||||||
(hints and HINT_HOST_DISABLE_EFFECTS) != 0
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY = "separate_ring_volume"
|
const val KEY = "separate_ring_volume"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.getContentDescription() =
|
||||||
|
when (getEffectiveRingerMode()) {
|
||||||
|
RINGER_MODE_VIBRATE -> getString(R.string.ringer_content_description_vibrate_mode)
|
||||||
|
RINGER_MODE_SILENT -> getString(R.string.ringer_content_description_silent_mode)
|
||||||
|
else -> getString(R.string.separate_ring_volume_option_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.getIconRes() =
|
||||||
|
when (getEffectiveRingerMode()) {
|
||||||
|
RINGER_MODE_NORMAL -> R.drawable.ic_ring_volume
|
||||||
|
RINGER_MODE_VIBRATE -> R.drawable.ic_volume_ringer_vibrate
|
||||||
|
else -> R.drawable.ic_ring_volume_off
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.getEffectiveRingerMode(): Int {
|
||||||
|
val hasVibrator = getSystemService(Vibrator::class.java)?.hasVibrator() ?: false
|
||||||
|
val ringerMode =
|
||||||
|
getSystemService(AudioManager::class.java)?.getRingerModeInternal() ?: RINGER_MODE_NORMAL
|
||||||
|
return when {
|
||||||
|
!hasVibrator && ringerMode == RINGER_MODE_VIBRATE -> RINGER_MODE_SILENT
|
||||||
|
else -> ringerMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.getSuppressionText(): String? {
|
||||||
|
val suppressor = NotificationManager.from(this).getEffectsSuppressor()
|
||||||
|
val hints =
|
||||||
|
INotificationManager.Stub.asInterface(ServiceManager.getService(NOTIFICATION_SERVICE))
|
||||||
|
?.hintsFromListenerNoToken ?: 0
|
||||||
|
return when {
|
||||||
|
(hints and HINT_HOST_DISABLE_CALL_EFFECTS) != 0 ||
|
||||||
|
(hints and HINT_HOST_DISABLE_EFFECTS) != 0 ->
|
||||||
|
SuppressorHelper.getSuppressionText(this, suppressor)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
// LINT.ThenChange(SeparateRingVolumePreferenceController.java)
|
// LINT.ThenChange(SeparateRingVolumePreferenceController.java)
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.notification
|
package com.android.settings.notification
|
||||||
|
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
|
import android.media.AudioManager
|
||||||
import android.media.AudioManager.RINGER_MODE_NORMAL
|
import android.media.AudioManager.RINGER_MODE_NORMAL
|
||||||
import android.media.AudioManager.RINGER_MODE_SILENT
|
import android.media.AudioManager.RINGER_MODE_SILENT
|
||||||
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
||||||
@@ -36,14 +37,15 @@ import org.mockito.kotlin.stub
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class SeparateRingVolumePreferenceTest {
|
class SeparateRingVolumePreferenceTest {
|
||||||
private var audioHelper = mock<AudioHelper>()
|
private var audioHelper = mock<AudioHelper>()
|
||||||
|
private var audioManager = mock<AudioManager>()
|
||||||
private var vibrator: Vibrator? = null
|
private var vibrator: Vibrator? = null
|
||||||
private var ringVolumePreference = SeparateRingVolumePreference()
|
private var ringVolumePreference = SeparateRingVolumePreference()
|
||||||
|
|
||||||
private val context =
|
private val context =
|
||||||
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||||
override fun getSystemService(name: String): Any? =
|
override fun getSystemService(name: String): Any? =
|
||||||
when {
|
when (name) {
|
||||||
name == getSystemServiceName(Vibrator::class.java) -> vibrator
|
getSystemServiceName(Vibrator::class.java) -> vibrator
|
||||||
|
getSystemServiceName(AudioManager::class.java) -> audioManager
|
||||||
else -> super.getSystemService(name)
|
else -> super.getSystemService(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,78 +75,76 @@ class SeparateRingVolumePreferenceTest {
|
|||||||
@Test
|
@Test
|
||||||
fun getEffectiveRingerMode_noVibratorAndVibrateMode_shouldReturnSilentMode() {
|
fun getEffectiveRingerMode_noVibratorAndVibrateMode_shouldReturnSilentMode() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn false }
|
vibrator = mock { on { hasVibrator() } doReturn false }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
assertThat(context.getEffectiveRingerMode()).isEqualTo(RINGER_MODE_SILENT)
|
||||||
.isEqualTo(RINGER_MODE_SILENT)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getEffectiveRingerMode_hasVibratorAndVibrateMode_shouldReturnVibrateMode() {
|
fun getEffectiveRingerMode_hasVibratorAndVibrateMode_shouldReturnVibrateMode() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn true }
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
assertThat(context.getEffectiveRingerMode()).isEqualTo(RINGER_MODE_VIBRATE)
|
||||||
.isEqualTo(RINGER_MODE_VIBRATE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getEffectiveRingerMode_hasVibratorAndNormalMode_shouldReturnNormalMode() {
|
fun getEffectiveRingerMode_hasVibratorAndNormalMode_shouldReturnNormalMode() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn true }
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_NORMAL }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_NORMAL }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
assertThat(context.getEffectiveRingerMode()).isEqualTo(RINGER_MODE_NORMAL)
|
||||||
.isEqualTo(RINGER_MODE_NORMAL)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getMuteIcon_normalMode_shouldReturnRingVolumeIcon() {
|
fun getIconRes_normalMode_shouldReturnRingVolumeIcon() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn true }
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_NORMAL }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_NORMAL }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getMuteIcon(context)).isEqualTo(R.drawable.ic_ring_volume)
|
assertThat(context.getIconRes()).isEqualTo(R.drawable.ic_ring_volume)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getMuteIcon_vibrateMode_shouldReturnVibrateIcon() {
|
fun getMuteIcon_vibrateMode_shouldReturnVibrateIcon() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn true }
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getMuteIcon(context))
|
assertThat(context.getIconRes()).isEqualTo(R.drawable.ic_volume_ringer_vibrate)
|
||||||
.isEqualTo(R.drawable.ic_volume_ringer_vibrate)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getMuteIcon_silentMode_shouldReturnSilentIcon() {
|
fun getMuteIcon_silentMode_shouldReturnSilentIcon() {
|
||||||
vibrator = mock { on { hasVibrator() } doReturn false }
|
vibrator = mock { on { hasVibrator() } doReturn false }
|
||||||
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
ringVolumePreference =
|
|
||||||
spy(ringVolumePreference).stub {
|
assertThat(context.getIconRes()).isEqualTo(R.drawable.ic_ring_volume_off)
|
||||||
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(ringVolumePreference.getMuteIcon(context))
|
@Test
|
||||||
.isEqualTo(R.drawable.ic_ring_volume_off)
|
fun getContentDescription_normalMode_shouldReturnTitleDescription() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_NORMAL }
|
||||||
|
|
||||||
|
assertThat(context.getContentDescription())
|
||||||
|
.isEqualTo(context.getString(R.string.separate_ring_volume_option_title))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getContentDescription_vibrateMode_shouldReturnVibrateModeDescription() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
|
||||||
|
assertThat(context.getContentDescription())
|
||||||
|
.isEqualTo(context.getString(R.string.ringer_content_description_vibrate_mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getContentDescription_silentMode_shouldReturnSilentModeDescription() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn false }
|
||||||
|
audioManager = mock { on { getRingerModeInternal() } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
|
||||||
|
assertThat(context.getContentDescription())
|
||||||
|
.isEqualTo(context.getString(R.string.ringer_content_description_silent_mode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// LINT.ThenChange(SeparateRingVolumePreferenceControllerTest.java)
|
// LINT.ThenChange(SeparateRingVolumePreferenceControllerTest.java)
|
||||||
|
Reference in New Issue
Block a user