Количество мобильных устройств, использующих операционную систему Android, быстро растет, но ее потенциал выходит далеко за пределы рынка мобильных решений. Простая архитектура и расширяемость платформы позволяют задействовать ее в телевизионных приставках, информационных киосках, видеодисплеях, терминалах сбора данных и других устройствах.
Есть много причин использовать в них именно Android: доступность лицензии (плата за нее не предусмотрена), стабильность платформы, открытый исходный код, легко адаптируемый к потребностям пользователя, плюс поддержка Google (что предпочтительно для некоторых людей).
Свободный доступ к исходному коду ОС дает огромные возможности, чтобы приспособить ее к требованиям конкретного устройства. Однако надо заметить, что, как и у других open-source-проектов, документация сводится к исходному коду и порой приходится обращаться к сообществу за ответом на возникшие вопросы, чтобы решить ту или иную проблему.
Большая часть документации по Android ориентирована на разработчиков прикладного ПО, использующих Android SDK на базе Java. Именно здесь идет сейчас главная работа, цель которой — предложить больше приложений для новых устройств. Крупные компании с известным брендом могут получить прямую поддержку от Google. Но если вы не относитесь к этим избранным, то при создании новых компонентов на “родном” коде или новой платформе вам придется самим справляться с проблемами.
Открытый исходный код помогает решать технические вопросы, но нужны указания по отладке, не представленные в текущей документации по Android. В данной статье описано, как сконфигурировать среду разработки и отладить низкоуровневый код.
Конфигурирование платформы
Для разработки на “родном” коде нужна та же среда, что и для приложений Android, но с некоторыми незначительными дополнениями. Следуйте инструкциям, размещенным на вебсайте проекта, для установки Eclipse и Android SDK.
Теперь у вас есть все компоненты, необходимые для разработки на Java для Android. Для разработки и отладки “родного” кода нужны расширения C/C++ Development Tooling (CDT). Получите их через Eclipse, используя диалоговое окно Software Updates в меню Help. Щелкните на опции Available. Разверните дерево Ganymede Update Site, а также C and C++ Development и отметьте флажок C and C++ Development на верхнем уровне. Кроме того, загрузите исходный код Android с вебсайта проекта и выполните сборку.
Установка отладчика “родного” кода
В среде Eclipse нужно задать использование удаленного получателя кода C/C++. Для каждой службы или приложения, использующих “родной” код, который вы хотите отлаживать, нужно выполнить следующие 12 шагов:
Шаг 1. Создайте проект C/C++ для приложения или службы, содержащих “родной” код, который нужно отладить. Для плагина CDT в Eclipse необходим проект, чтобы можно было выполнить отладку. В большинстве случаев платформенный код не будет собран в Eclipse и, следовательно, для него не будет предварительно созданного Eclipse-проекта. Кроме того, еще надо создать “пустой” проект и указать для него соответствующий исходный код. Выберите в Eclipse меню File, а затем New C or C++ Project.
Шаг 2. Задайте имя проекта и снимите флажок Use default location.
Шаг 3. Щелкните на кнопке Browse, найдите и выберите каталог верхнего уровня для вашего “родного” кода и щелкните OK. Если сборка “родного” кода выполнена с помощью команды makefiles, то можно выбрать Makefile empty project.
Шаг 4. Щелкните Finish.
Шаг 5. В главном окне Eclipse выберите проект C/C++, который вы только что создали, на панели Navigator или Package Explorer.
Шаг 6. В меню Run выберите Debug Configurations. В диалоговом окне выберите C/C++ Local Application в левой панели и щелкните на значке New launch configuration слева вверху. В правой панели дайте название новой конфигурации и выберите проект, который вы создали ранее.
Шаг 7. В окне C/C++ Application найдите исполнимый образ, где будет выполняться “родной” код. В случае приложений Android найдите исполнимый образ для app_process в дереве сборки исходного кода Android.
Шаг 8. Выберите вкладку Debugger в правой панели. В ниспадающем списке Debugger выберите gdbserver Debugger.
Шаг 9. В разделе GDB Debugger найдите arm-eabi-gdb в каталоге prebuilt в дереве исходного кода Android.
Шаг 10. Снимите флажок рядом с опцией Stop on startup at.
Шаг 11. Если вы знаете путь к каким-либо внешним совместно используемым библиотекам (“родным”), которые задействует отлаживаемый код, то щелкните на вкладке Shared Libraries и добавьте нужные каталоги.
Шаг 12. На вкладке Connection измените тип связи на TCP. Щелкните на кнопке Apply.
После того как задана конфигурация, вы можете подключиться к заданию и пройти в пошаговом режиме “родной” код. Имейте в виду, что автоматически сделать это в отладчике из Java не удастся. Вам придется вставить ждущий цикл в свой “родной” код, чтобы обеспечить необходимую связь. Прекрасно работает простой бесконечный опрос:
#define DBG_HALT() ({ volatile int i=0; while (i == 0); })
Вставьте DBG_HALT(); в “родной” код, который вы хотите отладить. На текущий момент нет возможности вставить в него жестко заданную точку останова.
Отладка “родного” кода
Отладку “родного” кода на платформе можно осуществить с помощью Eclipse, выполнив следующие девять шагов:
Шаг 1. Запустите получатель. В среде Eclipse запустите отладку приложения (или службы) на Java, содержащего ваш “родной” код. Остановите отладчик в окне Java в точке входа Activity или Service.
Шаг 2. Используя плагин Android в Eclipse (или adb logcat), задайте идентификатор процесса Linux для приложения/службы.
Шаг 3. Сконфигурируйте машину, чтобы портировать код в получатель, выполнив команду:
~> adb forward tcp:10000 tcp:10000
Запустите gdbserver в получателе, привязав его к идентификатору процесса, указанному выше (PID в строке ниже):
~> adb shell /system/bin/gdbserver tcp:10000 — attach PID
Шаг 4. В среде Eclipse перейдите обратно в режим C/C++ или Java, но не отключайте отладчик Java, если хотите провести отладку и со стороны Java.
Шаг 5. Выберите свой проект C/C++, щелкните правой кнопкой мыши и выберите Debug Configurations.
Шаг 6. Выберите созданную ранее конфигурацию отладки C/C++ для Android и щелкните на Debug. Eclipse подсоединится к эмулятору и покажет вид (“перспективу”) Debug с информацией о получателе, а также информацию удаленной отладки Java. Обычно могут появиться предупреждения от gdb о динамических разделах. Игнорируйте их. Вы можете переключаться между сеансами отладки Java и C/C++, как то требуется, однако отладка Java будет недоступна, если остановлена в “родном” коде.
Шаг 7. Выберите получателя C/C++ в “перспективе” Debug и щелкните на Suspend, чтобы остановить процесс в “родном” коде и посмотреть текущий стек вызовов. Изучите каждый поток внутри процесса и найдите, какой из них выполняет DBG_HALT() в вашем коде.
Шаг 8. Посмотрите разборку кода DBG_HALT(), чтобы найти ячейку памяти в стеке, откуда он берет значение “i”. Измените ячейку памяти на 1.
Шаг 9. После изменения ячейки памяти вы не сможете продолжать пошаговый прогон. Чтобы обойти это, задайте точку останова в следующей рабочей строке кода C/C++ после макроса и щелкните на Resume. Вы сразу попадете в эту точку останова и сможете продолжить пошаговое прохождение кода.
Документация по платформе Android и разработке “родного” кода скудна, но доступ к исходному коду и понимание того, как сконфигурировать ваши проекты на “родном” коде для отладки, должны вам помочь.