Хотите увидеть нечто любопытное? Вот, как устранили проблему «антеннагейта» на iPhone в 2010 году. 20 байт.

iOS 4.0: 8d ff ff ff 91 ff ff ff 95 ff ff ff 99 ff ff ff 9d ff ff ff  iOS 4.0.1: 86 ff ff ff 98 ff ff ff 9e ff ff ff a7 ff ff ff b0 ff ff ff
iOS 4.0: 8d ff ff ff 91 ff ff ff 95 ff ff ff 99 ff ff ff 9d ff ff ff iOS 4.0.1: 86 ff ff ff 98 ff ff ff 9e ff ff ff a7 ff ff ff b0 ff ff ff

Контекст: в 2010 году, когда выпустили iPhone 4, пользователи заметили, что если взять телефон определённым образом, то количество полосок сигнала сети падает с 5 до примерно 2. Спустя насколько недель компания опубликовала письмо, в котором свалила вину за это на неправильную формулу: https://www.apple.com/newsroom/2010/07/02Letter-from-Apple-Regarding-iPhone-4/

Upon investigation, we were stunned to find that the formula we use to calculate how many bars of signal strength to display is totally wrong. Our formula, in many instances, mistakenly displays 2 more bars than it should for a given signal strength. For example, we sometimes display 4 bars when we should be displaying as few as 2 bars. Users observing a drop of several bars when they grip their iPhone in a certain way are most likely in an area with very weak signal strength, but they don’t know it because we are erroneously displaying 4 or 5 bars. Their big drop in bars is because their high bars were never real in the first place.
Проведя расследование, мы неожиданно обнаружили, что формула, по которой вычисляется количество полосок силы сигнала, совершенно неправильная. Во многих случаях наша формула ошибочно отображала на две полоски больше, чем на самом деле требовалось. Например, иногда телефон отображал четыре полоски, хотя на самом деле он должен был показывать всего две. Если пользователи наблюдали исчезновение нескольких полосок, когда брали iPhone определённым образом, то это, скорее всего, происходило в местах с очень слабым сигналом, но они не знали этого, потому что телефон ошибочно отображал четыре или пять полосок. Такое резкое снижение количества полосок вызвано тем, что эта индикация изначально была неправильной.

Над этим письмом много смеялись (https://daringfireball.net/2010/07/translation_iphone_4), но никто не изучал различия в формуле между 4.0 и патчем в 4.0.1. В то время я был глупым восьмилетним ребёнком, но теперь уже я глупый взрослый, владеющий дизассемблером.

Я скачал обе прошивки и приступил к расследованию. Во фреймворке CoreTelephony я обнаружил многообещающий двоичный файл: CommCenter. После изучения строк в нём я убедился, что именно там находилась формула расчёта количества полосок.

strings CommCenter | grep -i bars  UseEcn0Bars ecn0 is %d / signal is %d, assuming 5 bars ecn0 is %d / signal is %d, assuming 4 bars ecn0 is %d / signal is %d, we say %d bars telling UI to draw %d bars, %d signal

Расчёт крайне прост. При преобразовании силы сигнала в полоски CommCenter загружает из памяти все пороговые значения и сравнивает их, пока не найдёт подходящий диапазон. То есть проблема не в коде...

; Table lookup loop              loc_3434e: 0003434e         ldr.w      r3, [r2, r4, lsl #2]     ; Load threshold[bar_count] 00034352         cmp        r5, r3                   ; Compare RSSI to threshold 00034354         ble        loc_3435c                ; If RSSI <= threshold, stop 00034356         adds       r4, #0x1                 ; bar_count++ 00034358         cmp        r4, #0x5                 ; Check if reached 5 bars 0003435a         bne        loc_3434e                ; Loop

...а здесь. Это таблица поиска. При преобразовании байтов в децибел-милливатты (дБм) мы получаем -115, -111, -107, -103 и -99 (чем ближе к нулю, тем лучше сигнал). Например, для отображения трёх полосок значение должно быть -107 или больше.

Raw bytes
Five threshold values for signal bars. - 0x8DFFFFFF equals −115 dBm, marking the 1-bar threshold. - 0x91FFFFFF equals −111 dBm, 2-bar threshold. - 0x95FFFFFF equals −107 dBm, 3-bar threshold. - 0x99FFFFFF equals −103 dBm, 4-bar threshold. - 0x9DFFFFFF equals −99 dBm, 5-bar threshold.

Если составить из этих значений график, то можно увидеть, что проблема в том, что значения слишком оптимистичны. Чаще всего индикатор показывает четыре-пять полосок. Но если взять телефон, то из-за столь резкого наклона кривой происходит катастрофическое снижение количества полосок с пяти до двух.

В 4.0.1 компания изменила эти значения, сделав их гораздо более плавными.

Raw 4.0.1 lookup table values
• 0x86FFFFFF equals −122 dBm — 1 bar threshold. • 0x98FFFFFF equals −104 dBm — 2 bars threshold. • 0x9EFFFFFF equals −98 dBm — 3 bars threshold. • 0xA7FFFFFF equals −89 dBm — 4 bars threshold. • 0xB0FFFFFF equals −80 dBm — 5 bars threshold.

Из графика видно, что для снижения с пяти до нуля полосок требуется сильное падение сигнала. Пользователь реже будет видеть пять полосок, но и резко падать их количество тоже будет реже.

4.0 and 4.0.1 signal bar thresholds mapped onto each other. The 4.0 line jumps from 0 to full bars in a fairly short span compared to 4.0.1

Вот и всё. 20 байт.

А, и ещё в 4.0.1 они изменили высоту полосок низкого сигнала, сделав их выше. Забавно.