Skip to content

Commit 1a2f513

Browse files
committed
android: parse device info
1 parent ee9de99 commit 1a2f513

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed

android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,11 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
926926
)
927927
}
928928

929-
override fun onDeviceMetadataReceived(deviceMetadata: ByteArray) {
930-
929+
override fun onDeviceInformationReceived(deviceInformation: AACPManager.Companion.AirPodsInformation) {
930+
Log.d(
931+
"AirPodsParser",
932+
"Device Information: name: ${deviceInformation.name}, modelNumber: ${deviceInformation.modelNumber}, manufacturer: ${deviceInformation.manufacturer}, serialNumber: ${deviceInformation.serialNumber}, version1: ${deviceInformation.version1}, version2: ${deviceInformation.version2}, hardwareRevision: ${deviceInformation.hardwareRevision}, updaterIdentifier: ${deviceInformation.updaterIdentifier}, leftSerialNumber: ${deviceInformation.leftSerialNumber}, rightSerialNumber: ${deviceInformation.rightSerialNumber}, version3: ${deviceInformation.version3}"
933+
)
931934
}
932935

933936
@SuppressLint("NewApi")

android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class AACPManager {
4242
const val CONTROL_COMMAND: Byte = 0x09
4343
const val EAR_DETECTION: Byte = 0x06
4444
const val CONVERSATION_AWARENESS: Byte = 0x4B
45-
const val DEVICE_METADATA: Byte = 0x1D
45+
const val INFORMATION: Byte = 0x1D
4646
const val RENAME: Byte = 0x1E
4747
const val HEADTRACKING: Byte = 0x17
4848
const val PROXIMITY_KEYS_REQ: Byte = 0x30
@@ -181,6 +181,20 @@ class AACPManager {
181181
val info2: Byte,
182182
var type: String?
183183
)
184+
185+
data class AirPodsInformation(
186+
val name: String,
187+
val modelNumber: String,
188+
val manufacturer: String,
189+
val serialNumber: String,
190+
val version1: String,
191+
val version2: String,
192+
val hardwareRevision: String,
193+
val updaterIdentifier: String,
194+
val leftSerialNumber: String,
195+
val rightSerialNumber: String,
196+
val version3: String
197+
)
184198
}
185199

186200
var controlCommandStatusList: MutableList<ControlCommandStatus> =
@@ -239,7 +253,7 @@ class AACPManager {
239253
fun onEarDetectionReceived(earDetection: ByteArray)
240254
fun onConversationAwarenessReceived(conversationAwareness: ByteArray)
241255
fun onControlCommandReceived(controlCommand: ByteArray)
242-
fun onDeviceMetadataReceived(deviceMetadata: ByteArray)
256+
fun onDeviceInformationReceived(deviceInformation: AirPodsInformation)
243257
fun onHeadTrackingReceived(headTracking: ByteArray)
244258
fun onUnknownPacketReceived(packet: ByteArray)
245259
fun onProximityKeysReceived(proximityKeys: ByteArray)
@@ -481,10 +495,6 @@ class AACPManager {
481495
callback?.onConversationAwarenessReceived(packet)
482496
}
483497

484-
Opcodes.DEVICE_METADATA -> {
485-
callback?.onDeviceMetadataReceived(packet)
486-
}
487-
488498
Opcodes.HEADTRACKING -> {
489499
if (packet.size < 70) {
490500
Log.w(
@@ -584,8 +594,14 @@ class AACPManager {
584594
eqData = FloatArray(8) { i -> eq1.get(i) }
585595
Log.d(TAG, "EQ Data set to: ${eqData.toList()}, eqOnPhone: $eqOnPhone, eqOnMedia: $eqOnMedia")
586596
}
587-
597+
598+
Opcodes.INFORMATION -> {
599+
Log.e(TAG, "Parsing Information Packet")
600+
val information = parseInformationPacket(packet)
601+
callback?.onDeviceInformationReceived(information)
602+
}
588603
else -> {
604+
Log.d(TAG, "Unknown opcode received: ${opcode.toHexString()}")
589605
callback?.onUnknownPacketReceived(packet)
590606
}
591607
}
@@ -1218,4 +1234,39 @@ class AACPManager {
12181234
connectedDevices = listOf()
12191235
audioSource = null
12201236
}
1237+
1238+
fun parseInformationPacket(packet: ByteArray): AirPodsInformation {
1239+
val data = packet.sliceArray(6 until packet.size)
1240+
1241+
var index = 0
1242+
while (index < data.size && data[index] != 0x00.toByte()) index++
1243+
1244+
val strings = mutableListOf<String>()
1245+
while (index < data.size) {
1246+
// skip 0x00 bytes
1247+
while (index < data.size && data[index] == 0x00.toByte()) index++
1248+
if (index >= data.size) break
1249+
val start = index
1250+
// find next 0x00 byte
1251+
while (index < data.size && data[index] != 0x00.toByte()) index++
1252+
val str = data.sliceArray(start until index).decodeToString()
1253+
strings.add(str)
1254+
}
1255+
1256+
strings.removeAt(0) // I'm too lazy to adjust, just removing the first empty string
1257+
1258+
return AirPodsInformation(
1259+
name = strings.getOrNull(0) ?: "",
1260+
modelNumber = strings.getOrNull(1) ?: "",
1261+
manufacturer = strings.getOrNull(2) ?: "",
1262+
serialNumber = strings.getOrNull(3) ?: "",
1263+
version1 = strings.getOrNull(4) ?: "",
1264+
version2 = strings.getOrNull(5) ?: "",
1265+
hardwareRevision = strings.getOrNull(6) ?: "",
1266+
updaterIdentifier = strings.getOrNull(7) ?: "",
1267+
leftSerialNumber = strings.getOrNull(8) ?: "",
1268+
rightSerialNumber = strings.getOrNull(9) ?: "",
1269+
version3 = strings.getOrNull(10) ?: "",
1270+
)
1271+
}
12211272
}

0 commit comments

Comments
 (0)