android: add media assist options in hearing aid

ui only
This commit is contained in:
Kavish Devar
2025-09-22 10:44:48 +05:30
parent fe69082e11
commit ce229bec6e
6 changed files with 141 additions and 11 deletions

View File

@@ -146,7 +146,16 @@ fun IndependentToggle(name: String, service: AirPodsService? = null, functionNam
.padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = name, modifier = Modifier.weight(1f), fontSize = 16.sp, color = textColor)
Text(
text = name,
modifier = Modifier.weight(1f),
style = TextStyle(
fontSize = 16.sp,
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Normal,
color = textColor
)
)
StyledSwitch(
checked = checked,
onCheckedChange = {

View File

@@ -1055,7 +1055,7 @@ fun AccessibilitySettingsScreen() {
@Composable
fun AccessibilityToggle(text: String, mutableState: MutableState<Boolean>, independent: Boolean = false, description: String? = null) {
fun AccessibilityToggle(text: String, mutableState: MutableState<Boolean>, independent: Boolean = false, description: String? = null, title: String? = null) {
val isDarkTheme = isSystemInDarkTheme()
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
@@ -1065,7 +1065,20 @@ fun AccessibilityToggle(text: String, mutableState: MutableState<Boolean>, indep
Column(
modifier = Modifier
.padding(vertical = 8.dp)
) {
) {
if (title != null) {
Text(
text = title,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Light,
color = textColor.copy(alpha = 0.6f),
fontFamily = FontFamily(Font(R.font.sf_pro))
),
modifier = Modifier.padding(8.dp, bottom = 2.dp)
)
Spacer(modifier = Modifier.height(4.dp))
}
Box (
modifier = Modifier
.background(animatedBackgroundColor, cornerShape)

View File

@@ -221,6 +221,10 @@ fun HearingAidScreen(navController: NavController) {
}
}
val mediaAssistEnabled = remember { mutableStateOf(false) }
val adjustMediaEnabled = remember { mutableStateOf(false) }
val adjustPhoneEnabled = remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
aacpManager?.registerControlCommandListener(AACPManager.Companion.ControlCommandIdentifiers.HEARING_AID, hearingAidListener)
aacpManager?.registerControlCommandListener(AACPManager.Companion.ControlCommandIdentifiers.HEARING_ASSIST_CONFIG, hearingAidListener)
@@ -256,7 +260,8 @@ fun HearingAidScreen(navController: NavController) {
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Light,
color = textColor.copy(alpha = 0.6f)
color = textColor.copy(alpha = 0.6f),
fontFamily = FontFamily(Font(R.font.sf_pro))
),
modifier = Modifier.padding(8.dp, bottom = 2.dp)
)
@@ -336,6 +341,108 @@ fun HearingAidScreen(navController: NavController) {
),
modifier = Modifier.padding(horizontal = 8.dp)
)
Spacer(modifier = Modifier.height(16.dp))
AccessibilityToggle(
text = stringResource(R.string.media_assist),
mutableState = mediaAssistEnabled,
independent = true,
description = stringResource(R.string.media_assist_description),
title = stringResource(R.string.media_assist).uppercase()
)
Spacer(modifier = Modifier.height(8.dp))
Column (
modifier = Modifier
.fillMaxWidth()
.background(backgroundColor, RoundedCornerShape(14.dp))
) {
val isDarkThemeLocal = isSystemInDarkTheme()
var backgroundColorAdjustMedia by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
val animatedBackgroundColorAdjustMedia by animateColorAsState(targetValue = backgroundColorAdjustMedia, animationSpec = tween(durationMillis = 500))
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
.pointerInput(Unit) {
detectTapGestures(
onPress = {
backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9)
tryAwaitRelease()
backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
},
onTap = {
adjustMediaEnabled.value = !adjustMediaEnabled.value
}
)
},
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.adjust_media),
modifier = Modifier.weight(1f),
style = TextStyle(
fontSize = 16.sp,
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Normal,
color = textColor
)
)
StyledSwitch(
checked = adjustMediaEnabled.value,
onCheckedChange = {
adjustMediaEnabled.value = it
},
)
}
HorizontalDivider(
thickness = 1.5.dp,
color = Color(0x40888888),
modifier = Modifier
.padding(start = 12.dp, end = 0.dp)
)
var backgroundColorAdjustPhone by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
val animatedBackgroundColorAdjustPhone by animateColorAsState(targetValue = backgroundColorAdjustPhone, animationSpec = tween(durationMillis = 500))
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
.pointerInput(Unit) {
detectTapGestures(
onPress = {
backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9)
tryAwaitRelease()
backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
},
onTap = {
adjustPhoneEnabled.value = !adjustPhoneEnabled.value
}
)
},
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.adjust_calls),
modifier = Modifier.weight(1f),
style = TextStyle(
fontSize = 16.sp,
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Normal,
color = textColor
)
)
StyledSwitch(
checked = adjustPhoneEnabled.value,
onCheckedChange = {
adjustPhoneEnabled.value = it
},
)
}
}
}
}
}

View File

@@ -1856,7 +1856,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
}
private lateinit var connectionReceiver: BroadcastReceiver
private lateinit var disconnectionReceiver: BroadcastReceiver
private fun resToUri(resId: Int): Uri? {
return try {
@@ -2581,11 +2580,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
} catch (e: Exception) {
e.printStackTrace()
}
try {
unregisterReceiver(disconnectionReceiver)
} catch (e: Exception) {
e.printStackTrace()
}
try {
unregisterReceiver(earReceiver)
} catch (e: Exception) {

View File

@@ -173,7 +173,10 @@ class ATTManager(private val device: BluetoothDevice) {
val inp = input ?: throw IllegalStateException("Not connected")
val buffer = ByteArray(512)
val len = inp.read(buffer)
if (len <= 0) throw IllegalStateException("No data read from ATT socket")
if (len == -1) {
disconnect()
throw IllegalStateException("End of stream reached")
}
val data = buffer.copyOfRange(0, len)
Log.wtf(TAG, "Read ${data.size} bytes from ATT")
Log.d(TAG, "readPDU: ${data.joinToString(" ") { String.format("%02X", it) }}")

View File

@@ -130,4 +130,8 @@
<string name="conversation_boost">Conversation Boost</string>
<string name="conversation_boost_description">Conversation Boost focuses your AirPods Pro on the person talking in front of you, making it easier to hear in a face-to-face conversation.</string>
<string name="hearing_aid_description">AirPods can use the results of a hearing test to make adjustments that improve the clarity of voices and sounds around you. \n\n Hearing Aid is only intended for people with perceived mild to moderate hearing loss.</string>
<string name="media_assist">Media Assist</string>
<string name="media_assist_description">AirPods Pro can use the results of a hearing test to make adjustments that improve the clarity of music, video, and calls.</string>
<string name="adjust_media">Adjust Music and Video</string>
<string name="adjust_calls">Adjust Calls</string>
</resources>