Дружим штатную громкую связь Volvo с русскими буквами

от автора

Доброго времени суток!
Несколько месяцев назад появился у меня чудесный автомобиль Volvo V50 родом из Бельгии. Бортовой компьютер и магнитолу успешно перепрошили на русский язык у официального дилера, а вот с отображением русских имен из записной книжки телефона при использовании штатной громкой связи вышла беда: все кириллические символы показывались в виде подчеркиваний. Я пользуюсь Samsung Galaxy S3 прошитым CyanogenMod 11, поэтому возникла идея подправить стандартный Bluetooth.apk для обеспечения возможности видеть имя звонящего.

Небольшое исследование показало, что в основном автомобили используют два вида профилей для получения записей телефонной книги:

  • PBAP — Phone Book Access Profile
  • HFP — Handsfree Profile

Первый является более навороченным и передает данные в формате vCard, который включает в себя практически все данные о контакте: имя, фамилию, организацию, адрес электронной почты и так далее.
Второй отправляет только имя, телефон и идентификатор записной книжки.

Путем анализа логов системы выяснилось, что мой автомобиль использует HFP с общением посредством AT-команд. За данный профиль отвечает следующий файл /packages/apps/Bluetooth/src/com/android/bluetooth/hfp/AtPhonebook.java
После недолгих поисков находим функцию int processCpbrCommand(BluetoothDevice device), в конце которой происходит формирование строки ответа на команду:

record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + name + "\""; record = record + "\r\n\r\n"; atCommandResponse = record; log("processCpbrCommand - atCommandResponse = "+atCommandResponse); mStateMachine.atResponseStringNative(atCommandResponse, getByteAddress(device)); 

Именно здесь и было бы неплохо исправить передаваемое имя. В моем случае было решено транслитерировать его. Для этих целей в класс AtPhonebook я добавил массив соответствия символов, а также функцию траслитерации:

private static final String[] charTable = new String[65536];     static { 	charTable['А'] = "A"; 	charTable['Б'] = "B"; 	charTable['В'] = "V"; 	charTable['Г'] = "G"; 	charTable['Д'] = "D"; 	charTable['Е'] = "E"; 	charTable['Ё'] = "E"; 	charTable['Ж'] = "ZH"; 	charTable['З'] = "Z"; 	charTable['И'] = "I"; 	charTable['Й'] = "I"; 	charTable['К'] = "K"; 	charTable['Л'] = "L"; 	charTable['М'] = "M"; 	charTable['Н'] = "N"; 	charTable['О'] = "O"; 	charTable['П'] = "P"; 	charTable['Р'] = "R"; 	charTable['С'] = "S"; 	charTable['Т'] = "T"; 	charTable['У'] = "U"; 	charTable['Ф'] = "F"; 	charTable['Х'] = "H"; 	charTable['Ц'] = "C"; 	charTable['Ч'] = "CH"; 	charTable['Ш'] = "SH"; 	charTable['Щ'] = "SH"; 	charTable['Ъ'] = "'"; 	charTable['Ы'] = "Y"; 	charTable['Ь'] = "'"; 	charTable['Э'] = "E"; 	charTable['Ю'] = "U"; 	charTable['Я'] = "YA";  	for (int i = 0; i < charTable.length; i++) { 	    char idx = (char) i; 	    char lower = new String(new char[] {idx}).toLowerCase().charAt(0); 	    if (charTable[i] != null) { 		charTable[lower] = charTable[i].toLowerCase(); 	    } 	} }  public static String toTranslit(String text) { 	char charBuffer[] = text.toCharArray(); 	StringBuilder sb = new StringBuilder(text.length()); 	for (char symbol : charBuffer) { 	    String replace = charTable[symbol]; 	    sb.append(replace == null ? symbol : replace); 	} 	return sb.toString(); } 

После этого нужно вызвать функцию при передаче команды:

record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + toTranslit(name) + "\""; record = record + "\r\n\r\n"; 

Теперь остается лишь скомпилировать приложение Bluetooth и вставить в архив с прошивкой CM.
Тесты после перепрошивки показали полную работоспособность решения. Теперь все имена из записной книжки отображаются транслитом.

В процессе поиска готового решения выяснилось, что проблемы бывают и с профилем PBAP, опять же с автомобилями Volvo, например XC60.
Модуль громкой связи в данном авто использует кодировку CP1251, тогда как стандартное приложение Bluetooth телефона на Android передает данные по профилю PBAP с указанием кодировки UTF-8, что выражается в отображении данных символами подчеркивания.

Для решения данной проблемы можно изменить конструктор класса BluetoothPbapVcardComposer (/packages/apps/Bluetooth/src/com/android/bluetooth/pbap/BluetoothPbapVcardComposer.java)

public BluetoothPbapVcardComposer(final Context context, final int vcardType,     long filter, final boolean careHandlerErrors) {     super(context, vcardType, "CP1251", careHandlerErrors);     mVCardType = vcardType;     mCharset = "CP1251";     mFilter = filter; } 

Здесь можно явно задать кодировку для суперкласса.
В принципе можно попробовать провернуть трюк с транслитерацией и здесь, копать нужно в сторону формирования vCard (функция buildVCard)
К сожалению XC60 или другой машины, использующей PBAP, у меня пока нет, поэтому проверить не смог.

Прикладываю пару вариантов пересобранного Bluetooth.apk

  1. Транслит HFP (http://yadi.sk/d/QlGKIPfXLMNXx)
  2. CP1251 PBAP (http://yadi.sk/d/qrbUVrtuLMRan)

Данное решение может также помочь и обладателям других авто со встроенной громкой связью, не понимающей русский язык.

ссылка на оригинал статьи http://habrahabr.ru/post/217381/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *