Android: невозможно открыть файл устройства в реализации JNI

Я взял код FM-радио Code Aurora и объединил его с кодовой базой Android Gingerbread.

Платформа приложения FM пытается получить доступ к устройству FM-радио ( /dev/radio ) с помощью JNI, который реализован в файле с именем android_hardware_fm.cpp . В этом файле есть функция, которая пытается получить дескриптор файла для узла устройства, используя open() в режиме чтения/записи. Однако вызов завершается с ошибкой с кодом -13: Отказано в доступе.

Я также сделал небольшой исполняемый файл C, который пытается открыть файл /dev/radio (в режиме RDWR), печатает его fd и закрывает его. Он запускается из /system/bin в целевой системе и отображает действительный fd.

Кстати, реализация JNI является частью основной библиотеки Android. Он находится в frameworks/base/core/jni и компилируется как часть libandroid_runtime.so.

Есть идеи/решения? Заранее спасибо.


person trans1st0r    schedule 07.05.2012    source источник
comment
4 года спустя у меня действительно похожая проблема: stackoverflow.com/questions/37486349 я даже запускал свой исполняемый файл с тем же UID как приложение и это работает, и, конечно же, все, что в ответе ниже. Вы когда-нибудь находили решение?   -  person jkoreska    schedule 27.05.2016
comment
@jkoreska я думаю, что использовал обходной путь. см. мой комментарий в ответе ниже.   -  person trans1st0r    schedule 27.05.2016


Ответы (1)


Очевидно, у вас нет прав на открытие устройства из пользовательского пространства. Во втором случае, когда вы запускаете исполняемый файл с терминала, у вас есть разрешения, вероятно, потому, что вы сделали su перед запуском исполняемого файла.

Для вашей проблемы здесь можно сделать две вещи.

1) Измените разрешения узла с терминала.

Этапы:

  • Откройте терминал (adb shell)

  • Сделайте su (для этого ваше устройство должно быть рутировано)

  • Сделайте chmod 777 /dev/radio в терминале

Как только это будет сделано, ваш радиоузел получит соответствующие разрешения для пользователя на чтение и запись. Итак, теперь вы можете сделать open() вызов, и он будет работать.

2) Программно вы можете добиться этого (при условии, что ваше устройство рутировано и на вашем устройстве работает su), вызвав следующую функцию — changePerm(). Это небольшая функция, которую я написал, которая изменит разрешения узлов устройства или, скорее, любого системного файла, к которому нет доступа пользователя. Если у вас есть разрешения, вы можете открыть его из пользовательского пространства. После этого вызов open() будет работать правильно.

void changePerm()
{
    Process chperm;
    try {
        chperm=Runtime.getRuntime().exec("su");


   DataOutputStream os = 
          new DataOutputStream(chperm.getOutputStream());
        os.writeBytes("chmod 777 /dev/radio\n");
        os.flush();

        os.writeBytes("exit\n");
        os.flush();

          chperm.waitFor();

} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}

Я проверил это для других узлов. Так что это также должно работать и для радио. Дайте мне знать, если вы столкнетесь с какими-либо трудностями. Спасибо

person mk..    schedule 08.05.2012
comment
Один, использующий оболочку adb, имеет права root по умолчанию. Что я сделал после вашего предложения, так это поместил команду chmod 777 /dev/radio0 в init.rc ... Однако это временное исправление. - person trans1st0r; 08.05.2012
comment
чтобы изменения в init.rc вступили в силу нужно перекомпилировать андроид и прошить его - person mk..; 08.05.2012
comment
О, в этом случае, если у вас есть права root по умолчанию, su может отсутствовать на вашем устройстве. Тогда только 1-й метод (без su применим) - person mk..; 08.05.2012