1 /* 2 * Copyright (C) 2024 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.settingslib.media.data.repository 18 19 import android.media.AudioDeviceAttributes 20 import android.media.Spatializer 21 import kotlin.coroutines.CoroutineContext 22 import kotlinx.coroutines.withContext 23 24 interface SpatializerRepository { 25 26 /** 27 * Returns true when head tracking is available for the [audioDeviceAttributes] and false the 28 * otherwise. 29 */ isHeadTrackingAvailableForDevicenull30 suspend fun isHeadTrackingAvailableForDevice( 31 audioDeviceAttributes: AudioDeviceAttributes 32 ): Boolean 33 34 /** 35 * Returns true when Spatial audio feature is supported for the [audioDeviceAttributes] and 36 * false the otherwise. 37 */ 38 suspend fun isSpatialAudioAvailableForDevice( 39 audioDeviceAttributes: AudioDeviceAttributes 40 ): Boolean 41 42 /** Returns a list [AudioDeviceAttributes] that are compatible with spatial audio. */ 43 suspend fun getSpatialAudioCompatibleDevices(): Collection<AudioDeviceAttributes> 44 45 /** Adds a [audioDeviceAttributes] to [getSpatialAudioCompatibleDevices] list. */ 46 suspend fun addSpatialAudioCompatibleDevice(audioDeviceAttributes: AudioDeviceAttributes) 47 48 /** Removes a [audioDeviceAttributes] from [getSpatialAudioCompatibleDevices] list. */ 49 suspend fun removeSpatialAudioCompatibleDevice(audioDeviceAttributes: AudioDeviceAttributes) 50 51 /** Checks if the head tracking is enabled for the [audioDeviceAttributes]. */ 52 suspend fun isHeadTrackingEnabled(audioDeviceAttributes: AudioDeviceAttributes): Boolean 53 54 /** Sets head tracking [isEnabled] for the [audioDeviceAttributes]. */ 55 suspend fun setHeadTrackingEnabled( 56 audioDeviceAttributes: AudioDeviceAttributes, 57 isEnabled: Boolean, 58 ) 59 } 60 61 class SpatializerRepositoryImpl( 62 private val spatializer: Spatializer, 63 private val backgroundContext: CoroutineContext, 64 ) : SpatializerRepository { 65 66 override suspend fun isHeadTrackingAvailableForDevice( 67 audioDeviceAttributes: AudioDeviceAttributes 68 ): Boolean { 69 return withContext(backgroundContext) { spatializer.hasHeadTracker(audioDeviceAttributes) } 70 } 71 72 override suspend fun isSpatialAudioAvailableForDevice( 73 audioDeviceAttributes: AudioDeviceAttributes 74 ): Boolean { 75 return withContext(backgroundContext) { 76 spatializer.isAvailableForDevice(audioDeviceAttributes) 77 } 78 } 79 80 override suspend fun getSpatialAudioCompatibleDevices(): Collection<AudioDeviceAttributes> = 81 withContext(backgroundContext) { spatializer.compatibleAudioDevices } 82 83 override suspend fun addSpatialAudioCompatibleDevice( 84 audioDeviceAttributes: AudioDeviceAttributes 85 ) { 86 withContext(backgroundContext) { 87 spatializer.addCompatibleAudioDevice(audioDeviceAttributes) 88 } 89 } 90 91 override suspend fun removeSpatialAudioCompatibleDevice( 92 audioDeviceAttributes: AudioDeviceAttributes 93 ) { 94 withContext(backgroundContext) { 95 spatializer.removeCompatibleAudioDevice(audioDeviceAttributes) 96 } 97 } 98 99 override suspend fun isHeadTrackingEnabled( 100 audioDeviceAttributes: AudioDeviceAttributes 101 ): Boolean = 102 withContext(backgroundContext) { spatializer.isHeadTrackerEnabled(audioDeviceAttributes) } 103 104 override suspend fun setHeadTrackingEnabled( 105 audioDeviceAttributes: AudioDeviceAttributes, 106 isEnabled: Boolean, 107 ) { 108 withContext(backgroundContext) { 109 spatializer.setHeadTrackerEnabled(isEnabled, audioDeviceAttributes) 110 } 111 } 112 } 113