Pull to refresh

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

Reading time 4 min
Views 10K
Доброго времени суток!
Несколько месяцев назад появился у меня чудесный автомобиль 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)


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

Articles