Дружимо штатну гучний зв'язок 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.  
  3. CP1251 PBAP (http://yadi.sk/d/qrbUVrtuLMRan )
  4.  
 
Дане рішення може також допомогти і власникам інших авто з вбудованою гучним зв'язком, яка не розуміє російську мову.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.