adolfintel / OpenPods

The Free and Open Source app for monitoring your AirPods on Android
https://fdossena.com/?p=openPods/index.frag
GNU General Public License v3.0
932 stars 161 forks source link

Ear detection #109

Open steam3d opened 3 years ago

steam3d commented 3 years ago

I am not sure but i think it is wrong.

inEarL = (inEarStatus & (flip ? 0b00001000 : 0b00000010)) != 0;
inEarR = (inEarStatus & (flip ? 0b00000010 : 0b00001000)) != 0;

I tested on AirPods Gen 2 and AirPods Pro and not always status right.

0101 0011 [Real state L in ear] 
isFlipped = true;
inEarL = false;
inEarR = true;
0011 0011  [Real state L in ear] 
isFlipped = false;
inEarL = true;
inEarR = false;

I also try to find a pattern, but so far unsuccessfully

Electric1447 commented 3 years ago

Maybe the pattern for gen 2 and pro is different??

Electric1447 commented 3 years ago

I'll test that, I also have a gen 2

steam3d commented 3 years ago

I got this from Gen2. Looks like that AirPods also send some other states sometimes.

Added: The AirPods send one of two values when you open the case 54 or 74. Maybe this value indicates which of the headphones is the main.

steam3d commented 3 years ago

I am not sure but maybe some of these bits also contain information about AirPod placement (In case or out).

Did you try to get BLE packets when case has 0% battery and AirPods do not charge?

I also counted what packages come more often. Some packets i think also contain information about change some settings. (for example, when AirPods change primary mic or something else). I can't understand why in some values your solution cannot correctly identify the left or right earphone is inserted.

image

Packets from AirPods Gen 2.

It seems 0 bit from the value used in the isFlipped function meaning whether the case is open or not

steam3d commented 3 years ago

i went further i copy the original ble packets from AirPods Gen 2. Created a fake AirPods from my raspberry pi and started to send data to my iPhone. iPhone accepted raspberry pi like AiPods. Interesting that for iPhone does not matter what command, battery lvl or charge status you send. iPhone always show the same parameters like in original packet. It means that iPhone use only encrypted payload. I still do not understand why the AirPods are sent their status and charge level in 10% increments. Maybe the right and left earphone transmits this data between them.

av21389 commented 3 years ago

Is there an apk that includes ear detection?

casasfernando commented 3 years ago

i went further i copy the original ble packets from AirPods Gen 2. Created a fake AirPods from my raspberry pi and started to send data to my iPhone. iPhone accepted raspberry pi like AiPods. Interesting that for iPhone does not matter what command, battery lvl or charge status you send. iPhone always show the same parameters like in original packet. It means that iPhone use only encrypted payload. I still do not understand why the AirPods are sent their status and charge level in 10% increments. Maybe the right and left earphone transmits this data between them.

@steam3d sorry to deviate the discussion a little bit but since you are experimenting with a Pi I wanted to ask you. Which Pi are you using 3B, 3B+, 4? Are you using the onboard BT adapter? And also, are you able to "see" the Pods beacons from the Pi?

I'm willing to develop a similar application for the Linux desktop but so far, even with the Pods paired to the Pi (they work just fine for music playback), if I do a ble scan, I'm not able to see any sort of ble packets coming from the Pods BT address. So I'm a bit lost at the moment since without the beacons to extract the information I will not get too far.

Thanks

steam3d commented 3 years ago

@casasfernando Hi. I use raspberry pi zero w (All raspberries seem to support bluetooth low energy). You need to read about ble. BLE bluetooth mac address and Classic bluetooth mac are different things.

casasfernando commented 3 years ago

@steam3d thanks a lot for the additional information I will look into those differences as I'm just new to this. I was afraid of wasting my time because the Pi was not able to see the beacons but I will dig a bit more and see if I get any further. Probably just scan again with hcitool and send the output to a file for further analisis with hcidump.

Thanks!

steam3d commented 3 years ago

Ear deteaction for AirPods max wrong. I am still trying to find regularity @Electric1447

Electric1447 commented 3 years ago

Very good! Keep me updated :)

steam3d commented 3 years ago

My thought is that AirPods, PowerBeats which have 3 devices (Right, Left, Case) and AirPods Max, PowerBeats which have 1 device (only headphone) uses one data format, but they interpret it differently. Getting ear detection right is possible but get accurate side of AirPod (which is Right or Left) no possible. For AirPods easy to get right or left side of current airpod, but on max it will switch between right and left.

There are two thoughts about it, or Apple just ignore Left and Right side because AirPods max has only headphone themself or Apple make special algorithm for each type of headphones based on their devices

MikeSim1 commented 2 years ago

Came to report this bug and found this issue... On my first gen Airpods, the indicator is on the opposite air pod every time. E.g. I put my left airpod in, the right indicates it is in ear, although charging indicators update properly.

Perhaps an alternative solution, or way to improve the current method, would be to check if the airpod is charging first, and if it isn't charging, check if it is in ear? I'll admit I'm not well educated on how the airpods detection stuff works, but I do both BLE and Android development, so maybe I can help further.

xiaoyaomeng commented 2 years ago

The same problem happened on my Airpod pro. I would like to ask where can I check this Apple's Bluetooth data protocol. Is it convenient to send it to me?

xiaoyaomeng commented 2 years ago

My thought is that AirPods, PowerBeats which have 3 devices (Right, Left, Case) and AirPods Max, PowerBeats which have 1 device (only headphone) uses one data format, but they interpret it differently. Getting ear detection right is possible but get accurate side of AirPod (which is Right or Left) no possible. For AirPods easy to get right or left side of current airpod, but on max it will switch between right and left.

There are two thoughts about it, or Apple just ignore Left and Right side because AirPods max has only headphone themself or Apple make special algorithm for each type of headphones based on their devices

I think it is still a code problem, because you can go to AndroPods (Google play store), it can run normally

fischejo commented 1 year ago

Sorry, for waking up this old thread, but actually it was the ignitation spark for my project. I started to gather all information and research material about the proximity protocol and continued with some own findings, which are documented here: https://github.com/fischejo/airpods-notify/blob/master/doc/proximity_protocol.md Maybe it helps you to implement an accurate ear detection.

Electric1447 commented 1 year ago

Sorry, for waking up this old thread, but actually it was the ignitation spark for my project. I started to gather all information and research material about the proximity protocol and continued with some own findings, which are documented here: https://github.com/fischejo/airpods-notify/blob/master/doc/proximity_protocol.md Maybe it helps you to implement an accurate ear detection.

This is great, thanks!

ursusursus commented 1 year ago

Anybody have an idea how is apple getting actual battery life? (Not just increment of 10s)

steam3d commented 1 year ago

Of course, they used AAP service or something like this to configure AirPods. Nothing complicated, but only Apple know which data to send.

I do not have Mac OS device to sniff Bluetooth traffic, so I know only theoretically.

ursusursus commented 1 year ago

@steam3d "which data to send"? is the precise battery not in the ble packet be read?

steam3d commented 1 year ago

@ursusursus The BLE packet contains encrypted data. When you charge your AirPods you can see that when AirPods battery level changes the encrypted data also changes. So my guess that encrypted part contains MAC hash and extra information.

AirPods does not have BLE Battery Gatt based on my test. If you dig into reverse engineering you will find that AirPods controls by service (AAP or hided custom GUID) on L2CAP layer.

I do not have a mac to sniff Bluetooth traffic from AirPods, but I think that iCloud key that used to encrypt data does not required if AirPods already paired because the connection is already secure after pairing headphones to device so maybe it is possible to connect to this service.

In common words it's possible but it required a lot of work.

ursusursus commented 1 year ago

So the unencrypted stuff, i.e. the 12-13 index for battery level, is them being nice with community, and it's actually not read by iphone/mac?

adolfintel commented 1 year ago

It's been almost 4 years since I did the original work on this app, but I remember that encrypted data not changing with battery level. I think iOS either "guesses" the percentage based on an estimated charge/discharge rate (I remember seeing wild fluctuations in the percentage during my initial testing so this could definitely be the case) or it communicates the information in some other way over the main bluetooth connection that I wasn't able to even detect.

steam3d commented 1 year ago

iPhone uses this information. But if you send for example Left: 10%, Right 25%, Case 90% but different encrypted data each time you will get different result on iPhone.

Public battery level somehow linked with encrypted data. I made experiment using raspberry Pi but I could not find any dependencies.

@adolfintel I can repeat experiment with raspberry Pi to get a fresh data, but I am not sure it will help us.

steam3d commented 1 year ago

If anyone has access to Apple Documentation as developer you can get usable information about Bluetooth and recommendation from Apple to vendors how to create IOT devices that use some of principals of AirPods and Find My protocol.

fischejo commented 1 year ago

According to this paper MagicPairing: Apple’s Take on Securing Bluetooth Peripherals, the last 0x10 bytes of the paired message (same protocol has a paired and pairing message with different byte length.) constitutes to the "Magic Pairing" field. Following is described in chapter 4.3:

4.3 MagicPairing AirPods Advertisements In addition to the pairing mechanism provided by MagicPairing, it also offers the capability to decrypt BLE advertisements sent by the AirPods. These advertisements have been shown to be linkable to AirPods in general [ 20]. Advertisements notify other Apple devices of the presence of the AirPods and encode battery state information. When an iOS device receives advertisements for a pair of AirPods that belong to the same Apple ID as the iOS device, a pop-up shows an AirPod image, the name of the AirPods, and the current battery state. The encrypted part constitutes the MagicPairing data. A new key is introduced, which is called MagicPairing EncryptionKey.

This might explain the hash-like nature of the bytes.