mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 02:36:12 -04:00
Add autopause and autoplay
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package eu.darken.capod.common
|
||||
|
||||
import android.media.AudioManager
|
||||
import android.os.SystemClock
|
||||
import android.view.KeyEvent
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import kotlinx.coroutines.delay
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MediaControl @Inject constructor(
|
||||
private val audioManager: AudioManager,
|
||||
) {
|
||||
|
||||
val isPlaying: Boolean
|
||||
get() = audioManager.isMusicActive
|
||||
|
||||
suspend fun sendPlay() {
|
||||
log(TAG) { "sendPlay()" }
|
||||
if (audioManager.isMusicActive) {
|
||||
log(TAG) { "Music is already playing, not sending play" }
|
||||
return
|
||||
}
|
||||
sendKey(KeyEvent.KEYCODE_MEDIA_PLAY)
|
||||
}
|
||||
|
||||
suspend fun sendPause() {
|
||||
log(TAG) { "sendPause()" }
|
||||
if (!audioManager.isMusicActive) {
|
||||
log(TAG) { "Music is not playing, not sending pause" }
|
||||
return
|
||||
}
|
||||
sendKey(KeyEvent.KEYCODE_MEDIA_PAUSE)
|
||||
}
|
||||
|
||||
suspend fun sendPlayPause() {
|
||||
log(TAG) { "sendPlayPause()" }
|
||||
if (audioManager.isMusicActive) {
|
||||
sendPause()
|
||||
} else {
|
||||
sendPlay()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendKey(keyCode: Int) {
|
||||
log(TAG) { "Sending up+down KeyEvent: $keyCode" }
|
||||
val eventTime = SystemClock.uptimeMillis()
|
||||
audioManager.dispatchMediaKeyEvent(KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0))
|
||||
delay(100)
|
||||
audioManager.dispatchMediaKeyEvent(KeyEvent(eventTime + 200, eventTime + 200, KeyEvent.ACTION_UP, keyCode, 0))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("MediaControl")
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class BleScanner @Inject constructor(
|
||||
fun scan(
|
||||
filter: Set<ScanFilter> = ProximityPairing.getBleScanFilter(),
|
||||
mode: Int = ScanSettings.SCAN_MODE_LOW_POWER,
|
||||
delay: Long = 1,
|
||||
delay: Long = 100,
|
||||
): Flow<List<ScanResult>> = callbackFlow {
|
||||
val scanner = bluetoothManager.adapter.bluetoothLeScanner
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Application
|
||||
import android.app.NotificationManager
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import androidx.work.WorkManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
@@ -33,4 +34,9 @@ class AndroidModule {
|
||||
@Singleton
|
||||
fun workerManager(context: Context): WorkManager =
|
||||
WorkManager.getInstance(context)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun audioManager(context: Context): AudioManager =
|
||||
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ class GeneralSettings @Inject constructor(
|
||||
false
|
||||
)
|
||||
|
||||
val autoPlay = preferences.createFlowPreference(
|
||||
"core.eardetection.autoplay.enabled",
|
||||
false
|
||||
)
|
||||
|
||||
val showAll = preferences.createFlowPreference(
|
||||
"core.showall.enabled",
|
||||
false
|
||||
@@ -48,6 +53,7 @@ class GeneralSettings @Inject constructor(
|
||||
monitorMode,
|
||||
scannerMode,
|
||||
autoPause,
|
||||
autoPlay,
|
||||
showAll,
|
||||
debugSettings.isDebugModeEnabled,
|
||||
debugSettings.isAutoReportEnabled
|
||||
|
||||
@@ -14,6 +14,7 @@ import eu.darken.capod.common.permissions.Permission
|
||||
import eu.darken.capod.common.permissions.isGrantedOrNotRequired
|
||||
import eu.darken.capod.common.uix.ViewModel3
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
|
||||
import eu.darken.capod.main.ui.overview.cards.pods.BasicSingleApplePodsCardVH
|
||||
import eu.darken.capod.main.ui.overview.cards.pods.DualApplePodsCardVH
|
||||
@@ -50,6 +51,11 @@ class OverviewFragmentVM @Inject constructor(
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
|
||||
val showManualRefresh = generalSettings.monitorMode.flow
|
||||
.map { it == MonitorMode.MANUAL }
|
||||
.asLiveData2()
|
||||
|
||||
private val permissionCheckTrigger = MutableStateFlow(UUID.randomUUID())
|
||||
private val requiredPermissions: Flow<List<Permission>> = permissionCheckTrigger
|
||||
.map {
|
||||
@@ -66,17 +72,16 @@ class OverviewFragmentVM @Inject constructor(
|
||||
private val pods: Flow<List<PodDevice>> = requiredPermissions
|
||||
.flatMapLatest { permissions ->
|
||||
if (permissions.isEmpty()) {
|
||||
combine(podMonitor.pods, generalSettings.showAll.flow) { pods, showAll ->
|
||||
if (showAll) {
|
||||
pods
|
||||
.sortedByDescending { it.rssi }
|
||||
} else {
|
||||
pods
|
||||
.maxByOrNull { it.rssi }
|
||||
?.let { listOf(it) }
|
||||
?: emptyList()
|
||||
generalSettings.showAll.flow
|
||||
.flatMapLatest { showAll ->
|
||||
if (showAll) {
|
||||
podMonitor.devices
|
||||
} else {
|
||||
podMonitor.mainDevice.map { mainDevice ->
|
||||
mainDevice?.let { listOf(it) } ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channelFlow {
|
||||
send(emptyList())
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ class SingleApplePodsCardVH(parent: ViewGroup) :
|
||||
sb.append("\n").append(device.getBatteryLevelHeadset(context))
|
||||
when {
|
||||
device.isHeadsetBeingCharged -> sb.append("\n").append("Charging")
|
||||
device.isHeadsetBeingWorn -> sb.append("\n").append("In ear")
|
||||
device.isHeadphonesBeingWorn -> sb.append("\n").append("In ear")
|
||||
else -> {}
|
||||
}
|
||||
text = sb
|
||||
|
||||
@@ -23,7 +23,7 @@ class PodMonitor @Inject constructor(
|
||||
private val generalSettings: GeneralSettings,
|
||||
) {
|
||||
|
||||
val pods: Flow<List<PodDevice>> = generalSettings.scannerMode.flow
|
||||
val devices: Flow<List<PodDevice>> = generalSettings.scannerMode.flow
|
||||
.flatMapLatest {
|
||||
bleScanner.scan(
|
||||
mode = when (it) {
|
||||
@@ -80,6 +80,13 @@ class PodMonitor @Inject constructor(
|
||||
pods
|
||||
}
|
||||
|
||||
val mainDevice: Flow<PodDevice?>
|
||||
get() = devices.map { devices ->
|
||||
devices.maxByOrNull { it.rssi }?.let {
|
||||
if (it.rssi > -85) it else null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("Monitor", "PodMonitor")
|
||||
}
|
||||
|
||||
@@ -8,12 +8,14 @@ import androidx.work.WorkerParameters
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.hilt.EntryPoints
|
||||
import eu.darken.capod.common.MediaControl
|
||||
import eu.darken.capod.common.debug.Bugs
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.*
|
||||
import eu.darken.capod.common.debug.logging.asLog
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.flow.setupCommonEventHandlers
|
||||
import eu.darken.capod.common.flow.withPrevious
|
||||
import eu.darken.capod.common.permissions.Permission
|
||||
import eu.darken.capod.common.permissions.isGrantedOrNotRequired
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
@@ -21,6 +23,7 @@ import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.monitor.core.MonitorComponent
|
||||
import eu.darken.capod.monitor.core.MonitorCoroutineScope
|
||||
import eu.darken.capod.monitor.ui.MonitorNotifications
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.cancelChildren
|
||||
@@ -36,6 +39,7 @@ class MonitorWorker @AssistedInject constructor(
|
||||
private val monitorNotifications: MonitorNotifications,
|
||||
private val notificationManager: NotificationManager,
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val mediaControl: MediaControl,
|
||||
) : CoroutineWorker(context, params) {
|
||||
|
||||
private val workerScope = MonitorCoroutineScope()
|
||||
@@ -105,18 +109,31 @@ class MonitorWorker @AssistedInject constructor(
|
||||
}
|
||||
.launchIn(workerScope)
|
||||
|
||||
|
||||
val monitorJob = podMonitor.pods
|
||||
val monitorJob = podMonitor.mainDevice
|
||||
.setupCommonEventHandlers(TAG) { "PodMonitor" }
|
||||
.onStart {
|
||||
setForeground(monitorNotifications.getForegroundInfo(null))
|
||||
}
|
||||
.onEach {
|
||||
.onEach { currentDevice ->
|
||||
notificationManager.notify(
|
||||
MonitorNotifications.NOTIFICATION_ID,
|
||||
monitorNotifications.getNotification(it.firstOrNull())
|
||||
monitorNotifications.getNotification(currentDevice)
|
||||
)
|
||||
}
|
||||
.withPrevious()
|
||||
.onEach { (previous, current) ->
|
||||
if (previous is HasEarDetection && current is HasEarDetection) {
|
||||
log(TAG) { "previous=${previous.isBeingWorn}, current=${current.isBeingWorn}" }
|
||||
log(TAG) { "previous-id=${previous.identifier}, current-id=${current.identifier}" }
|
||||
if (previous.identifier == current.identifier && previous.isBeingWorn != current.isBeingWorn) {
|
||||
if (generalSettings.autoPlay.value && !mediaControl.isPlaying) {
|
||||
mediaControl.sendPlay()
|
||||
} else if (generalSettings.autoPause.value && mediaControl.isPlaying) {
|
||||
mediaControl.sendPause()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(workerScope)
|
||||
|
||||
log(TAG, VERBOSE) { "Monitor job is active" }
|
||||
|
||||
@@ -60,7 +60,7 @@ class MonitorNotifications @Inject constructor(
|
||||
|
||||
fun getBuilder(device: PodDevice?): NotificationCompat.Builder {
|
||||
if (device == null) {
|
||||
builder.setContentTitle(context.getString(R.string.device_status_loading_message))
|
||||
builder.setContentTitle(context.getString(R.string.device_none_label))
|
||||
builder.setSmallIcon(R.drawable.ic_device_generic_earbuds)
|
||||
return builder
|
||||
}
|
||||
|
||||
@@ -12,14 +12,4 @@ interface DualPodDevice : PodDevice {
|
||||
val batteryRightPodPercent: Float?
|
||||
|
||||
val batteryCasePercent: Float?
|
||||
|
||||
val isLeftPodInEar: Boolean
|
||||
|
||||
val isRightPodInEar: Boolean
|
||||
|
||||
val isCaseCharging: Boolean
|
||||
|
||||
val isLeftPodCharging: Boolean
|
||||
|
||||
val isRightPodCharging: Boolean
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package eu.darken.capod.pods.core
|
||||
|
||||
interface HasEarDetection : PodDevice {
|
||||
|
||||
val isBeingWorn: Boolean
|
||||
|
||||
}
|
||||
@@ -9,8 +9,9 @@ import eu.darken.capod.common.lowerNibble
|
||||
import eu.darken.capod.common.upperNibble
|
||||
import eu.darken.capod.pods.core.DualPodDevice
|
||||
import eu.darken.capod.pods.core.DualPodDevice.Pod
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
|
||||
interface DualApplePods : ApplePods, DualPodDevice {
|
||||
interface DualApplePods : ApplePods, DualPodDevice, HasEarDetection {
|
||||
|
||||
val microPhonePod: Pod
|
||||
get() = when (rawStatus.isBitSet(5)) {
|
||||
@@ -63,28 +64,31 @@ interface DualApplePods : ApplePods, DualPodDevice {
|
||||
}
|
||||
}
|
||||
|
||||
override val isLeftPodInEar: Boolean
|
||||
val isLeftPodInEar: Boolean
|
||||
get() = when (microPhonePod) {
|
||||
Pod.LEFT -> rawStatus.isBitSet(1)
|
||||
Pod.RIGHT -> rawStatus.isBitSet(3)
|
||||
}
|
||||
|
||||
override val isRightPodInEar: Boolean
|
||||
val isRightPodInEar: Boolean
|
||||
get() = when (microPhonePod) {
|
||||
Pod.LEFT -> rawStatus.isBitSet(3)
|
||||
Pod.RIGHT -> rawStatus.isBitSet(1)
|
||||
}
|
||||
|
||||
override val isCaseCharging: Boolean
|
||||
override val isBeingWorn: Boolean
|
||||
get() = isLeftPodInEar && isRightPodInEar
|
||||
|
||||
val isCaseCharging: Boolean
|
||||
get() = rawCaseBattery.upperNibble.isBitSet(2)
|
||||
|
||||
override val isLeftPodCharging: Boolean
|
||||
val isLeftPodCharging: Boolean
|
||||
get() = when (microPhonePod) {
|
||||
Pod.LEFT -> rawCaseBattery.upperNibble.isBitSet(0)
|
||||
Pod.RIGHT -> rawCaseBattery.upperNibble.isBitSet(1)
|
||||
}
|
||||
|
||||
override val isRightPodCharging: Boolean
|
||||
val isRightPodCharging: Boolean
|
||||
get() = when (microPhonePod) {
|
||||
Pod.LEFT -> rawCaseBattery.upperNibble.isBitSet(1)
|
||||
Pod.RIGHT -> rawCaseBattery.upperNibble.isBitSet(0)
|
||||
|
||||
@@ -4,8 +4,9 @@ import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.isBitSet
|
||||
import eu.darken.capod.common.lowerNibble
|
||||
import eu.darken.capod.common.upperNibble
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
|
||||
interface SingleApplePods : BasicSingleApplePods {
|
||||
interface SingleApplePods : BasicSingleApplePods, HasEarDetection {
|
||||
|
||||
val batteryCasePercent: Float?
|
||||
get() = when (val value = rawCaseBattery.lowerNibble.toInt()) {
|
||||
@@ -18,7 +19,7 @@ interface SingleApplePods : BasicSingleApplePods {
|
||||
}
|
||||
}
|
||||
|
||||
val isHeadsetBeingWorn: Boolean
|
||||
val isHeadphonesBeingWorn: Boolean
|
||||
get() = rawStatus.isBitSet(1)
|
||||
|
||||
val isCaseCharging: Boolean
|
||||
@@ -26,4 +27,7 @@ interface SingleApplePods : BasicSingleApplePods {
|
||||
|
||||
val isHeadsetBeingCharged: Boolean
|
||||
get() = rawCaseBattery.upperNibble.isBitSet(0)
|
||||
|
||||
override val isBeingWorn: Boolean
|
||||
get() = isHeadphonesBeingWorn
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM9.5,16.5v-9l7,4.5L9.5,16.5z" />
|
||||
</vector>
|
||||
@@ -22,17 +22,8 @@
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:listitem="@layout/main_toggle_item"
|
||||
tools:listitem="@layout/overview_pods_apple_dual_item"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/ic_baseline_refresh_24" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/card"
|
||||
style="@style/MyCardView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:context=".main.ui.MainActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/primary_info"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Enable or disable the functionality of this app."
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/toggle_action"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="Enable"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/primary_info" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -2,7 +2,6 @@
|
||||
<string name="app_name">CAPod</string>
|
||||
<string name="app_name_pro">CAPod Pro</string>
|
||||
|
||||
<string name="device_status_loading_message">Loading device status</string>
|
||||
<string name="notification_channel_device_status_label">Device status</string>
|
||||
|
||||
<string name="general_error_label">Error</string>
|
||||
@@ -82,6 +81,7 @@
|
||||
<string name="settings_debug_autoreports_label">Automatic bug reports</string>
|
||||
<string name="settings_debug_autoreports_description">Automatically reports issues, e.g. details on an app crash so I can figure out how to fix it.</string>
|
||||
<string name="device_unknown_label">Unknown device</string>
|
||||
<string name="device_none_label">No device</string>
|
||||
<string name="pods_single_headphones_label">Headphones</string>
|
||||
<string name="settings_debug_mode_label">Debug mode</string>
|
||||
<string name="settings_debug_mode_description">Show additional information to troubleshoot issues.</string>
|
||||
@@ -96,7 +96,9 @@
|
||||
<string name="settings_scanner_mode_balanced_label">Balanced</string>
|
||||
<string name="settings_scanner_mode_lowlatency_label">Low latency</string>
|
||||
<string name="settings_autopause_label">Auto pause</string>
|
||||
<string name="settings_autopause_description">Pause music when removing the device from your ear (if your device supports it).</string>
|
||||
<string name="settings_autopause_description">Pause music when removing the device from your ear (if supported).</string>
|
||||
<string name="settings_showall_label">Show all devices</string>
|
||||
<string name="settings_showall_description">Show other people\'s devices that are near you.</string>
|
||||
<string name="settings_autopplay_label">Auto play</string>
|
||||
<string name="settings_autoplay_description">Start music playback music when wearing the device (if supported).</string>
|
||||
</resources>
|
||||
@@ -13,6 +13,12 @@
|
||||
android:summary="@string/settings_scanner_mode_description"
|
||||
android:title="@string/settings_scanner_mode_label" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:icon="@drawable/ic_baseline_play_circle_24"
|
||||
android:key="core.eardetection.autoplay.enabled"
|
||||
android:summary="@string/settings_autoplay_description"
|
||||
android:title="@string/settings_autopplay_label" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:icon="@drawable/ic_baseline_pause_circle_24"
|
||||
android:key="core.eardetection.autopause.enabled"
|
||||
|
||||
@@ -29,7 +29,7 @@ class SingleApplePodsTest : BaseAirPodsTest() {
|
||||
isCaseCharging shouldBe false
|
||||
isHeadsetBeingCharged shouldBe false
|
||||
|
||||
isHeadsetBeingWorn shouldBe true
|
||||
isHeadphonesBeingWorn shouldBe true
|
||||
batteryCasePercent shouldBe 0.0f
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class AirPodsMaxTest : BaseAirPodsTest() {
|
||||
isCaseCharging shouldBe false
|
||||
isHeadsetBeingCharged shouldBe false
|
||||
|
||||
isHeadsetBeingWorn shouldBe true
|
||||
isHeadphonesBeingWorn shouldBe true
|
||||
batteryCasePercent shouldBe 0.0f
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class AirPodsMaxTest : BaseAirPodsTest() {
|
||||
isCaseCharging shouldBe false
|
||||
isHeadsetBeingCharged shouldBe false
|
||||
|
||||
isHeadsetBeingWorn shouldBe true
|
||||
isHeadphonesBeingWorn shouldBe true
|
||||
batteryCasePercent shouldBe 0.0f
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user