Всем хороши Android-девай­сы, но порой им край­не не хва­тает воз­можнос­тей и ути­лит, име­ющих­ся в нас­толь­ной Linux. Отдель­ные инс­тру­мен­ты, такие как Terminal IDE, час­тично выруча­ют, но некото­рого нуж­ного фун­кци­она­ла в них нет. Как же испра­вить ситу­ацию?
 

Введение

Как всем извес­тно, Android име­ет под собой фун­дамент в виде ядра Linux. Из это­го сле­дует, что в теории на смар­тфо­не мож­но запус­тить все те при­ложе­ния, что дос­тупны на дес­ктоп­ном Linux. На прак­тике же все слож­нее. Пос­коль­ку набор Native-биб­лиотек в Android отли­чает­ся от таково­го на дес­кто­пе (не говоря уже об архи­тек­туре плат­формы), при­ложе­ния тре­бует­ся ком­пилиро­вать ста­тичес­ки. А иног­да еще и пат­чить. Но и в этом слу­чае работос­пособ­ность при­ложе­ния не всег­да гаран­тирова­на.

Что каса­ется модулей ядра, которые могут быть весь­ма полез­ны на смар­тфо­не (под­дер­жка NTFS, нап­ример), то здесь все еще инте­рес­нее. Во мно­гих ядрах от вен­дора отклю­чена фун­кция заг­рузки модулей (начиная с Android 4.3, это фак­тичес­ки тре­бова­ние Google. — Прим. ред.). Поэто­му нам при­дет­ся не толь­ко подоб­рать пра­виль­ную вер­сию ядра для сбор­ки модулей, но и, воз­можно, пересоб­рать само ядро, вклю­чив такую под­дер­жку, или прос­то добавить модуль в сам образ ядра.

Да­лее в статье мы рас­смот­рим, как побороть эти проб­лемы, и поп­робу­ем соб­рать модули Linux-ядра и нес­коль­ко при­ложе­ний.

 

Подготовка

Для сбор­ки модулей (ядра) и при­ложе­ний нам пот­ребу­ется тул­чейн, то есть связ­ка из кросс‑ком­пилято­ра и лин­ковщи­ка, плюс набор стан­дар­тных инс­тру­мен­тов сбор­ки, которые мож­но уста­новить из репози­тория (при­мер для Ubuntu):

$ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev lib32ncurses5-dev x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 git libtool

Те­перь мож­но уста­новить тул­чейн. Их сущес­тву­ет как минимум два — стан­дар­тный гуг­лов­ский NDK и тул­чейн от Linaro, куда силь­нее опти­мизи­рующий код. Раз­лича­ются они еще и набором target-биб­лиотек — если NDK содер­жит те биб­лиоте­ки, которые име­ются в Android и, соот­ветс­твен­но, могут не под­ходить для сбор­ки обыч­ных POSIX-сов­мести­мых при­ложе­ний, то Linaro вклю­чает минималь­ный набор стан­дар­тных POSIX-биб­лиотек под ARM, для исполь­зования которых в гуг­лооси понадо­бит­ся ста­тичес­кая лин­ковка.

Для сбор­ки ядра мы, в целях сов­мести­мос­ти, будем исполь­зовать пер­вый. Заходим на стра­нич­ку https://developer.android.com/tools/sdk/ndk/index.html и, выб­рав нуж­ную вер­сию NDK, ска­чива­ем его. Затем уста­нав­лива­ем на ска­чан­ный файл пра­во исполне­ния и рас­паковы­ваем:

$ chmod u+x android-ndk-r10c-linux-x86_64.bin
$ ./android-ndk-r10c-linux-x86_64.bin

А вот для сбор­ки прог­рамм понадо­бит­ся и тул­чейн от Linaro. Для его получе­ния про­ще все­го зай­ти на forum.xda-developers.com/showthread.php?t=2098133 и выб­рать билд. Лич­но я выб­рал Linaro GCC 4.6.4-2013.05 (пос­коль­ку про­цес­сор у меня не Cortex, то и качал я arm-unknown-linux-gnueabi-linaro_4.6.4-2013.05-build_2013_05_18.tar.bz2). Рас­паковы­ваем и для пущего удобс­тва пере­име­новы­ваем:

$ tar xjvf arm-unknown-linux-gnueabi-linaro_4.6.4-2013.05-build_2013_05_18.tar.bz2
$ mv arm-unknown-linux-gnueabi-linaro_4.6.4-2013.05 linaro-toolchain-4.6

До­бавим путь к тул­чей­ну в ~/.bashrc (и заод­но опре­делим отдель­ные перемен­ные, которые на вре­мя ком­пиляции ядра, воз­можно, и не при­годят­ся, но в даль­нейшем могут ой как понадо­бить­ся):

export PATH=$PATH:${HOME}/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin:${HOME}/linaro-toolchain-4.6/bin
export NDKPATH=${HOME}/android-ndk-r10c
export ANDROID_SYSROOT=${HOME}/android-ndk-r10c/platforms/android-18/arch-arm
export LINARO_SYSROOT=${HOME}/linaro-toolchain-4.6/arm-unknown-linux-gnueabi/sysroot
export ARCH=arm
export CROSS_COMPILE_NDK=arm-linux-androideabi-
export CROSS_COMPILE_LINARO=arm-unknown-linux-gnueabi-
export CROSS_COMPILE=$CROSS_COMPILE_NDK
export CCOMPILE=$CROSS_COMPILE
 

Компиляция модулей и ядра

Для начала опре­делим, под­держи­вает ли сто­ковое ядро модули. Для это­го смот­рим, есть ли на устрой­стве файл /proc/modules. В зависи­мос­ти от это­го мы пой­мем, что делать даль­ше. В слу­чае если модули под­держи­вают­ся, мы берем ваниль­ное ядро той же вер­сии (но луч­ше, конеч­но, взять от вен­дора), кон­фигури­руем его, ком­пилиру­ем толь­ко модули, закиды­ваем их в /system/lib/modules и заг­ружа­ем с помощью коман­ды insmod на устрой­стве. Если же ядро модулей не под­держи­вает, мож­но либо взять готовое кас­томное ядро с под­дер­жкой модулей (об этом читай в статье «Выбира­ем кас­томное ядро для сво­его Android-аппа­рата»), либо соб­рать свое, вклю­чив нуж­ные модули в образ ядра.

В слу­чае сам­сунгов­ских устрой­ств (у меня как раз такое) исходни­ки ядер лежат на opensource.samsung.com. Для сбор­ки ядра нам понадо­бит­ся его кон­фиг. В некото­рых устрой­ствах он находит­ся в фай­ле /proc/config.gz, но, к сожале­нию, не во всех, поэто­му раз­берем дру­гой метод его получе­ния. Пос­ле ска­чива­ния и рас­паков­ки перехо­дим в соот­ветс­тву­ющий каталог, смот­рим фай­лы, находя­щиеся в arch/arm/configs/, и выбира­ем под­ходящий по архи­тек­туре. В моем слу­чае там был толь­ко один файл — n1a_00_defconfig. Перехо­дим обратно в каталог, куда мы пер­воначаль­но рас­пакова­ли ядро, и набира­ем сле­дующую коман­ду:

$ make n1a_00_defconfig

Да­лее нас­тра­иваем ядро с помощью стан­дар­тной коман­ды make menuconfig, что­бы вклю­чить нуж­ные нам модули. Затем собира­ем:

$ make -j9 CFLAGS_MODULE=-fno-pic
Конфигурирование ядра для устройства
Кон­фигури­рова­ние ядра для устрой­ства

Сборка модулей

Для сбор­ки исклю­читель­но модулей без самого ядра мож­но исполь­зовать либо коман­ду make modules, либо, если ты вклю­чил все­го один модуль, сле­дующие коман­ды (вмес­то net/netfilter под­ставь каталог собира­емо­го модуля):

$ make modules_prepare
$ make M=net/netfilter CFLAGS_MODULE=-fno-pic

Пос­ле сбор­ки нам нуж­но все получив­шиеся фай­лы ско­пиро­вать в еди­ный каталог:

$ mkdir final
$ cp arch/arm/boot/zImage final
$ find . -name '*ko' -exec cp '{}' final \;

За­тем, в слу­чае пол­ной ком­пиляции, нуж­но соб­рать фай­лы в ZIP-архив. Не абы какой, а сфор­мирован­ный опре­делен­ным обра­зом (речь идет о фай­ле обновле­ния для кас­томной кон­соли вос­ста­нов­ления. — Прим. ред.). Для это­го кло­ниру­ем с гит­хаба шаб­лон для дан­ного фай­ла:

$ cd final
$ git clone https://github.com/koush/AnyKernel.git
$ cp ./*.ko ./AnyKernel/system/lib/modules/
$ cp ./zImage ./AnyKernel/kernel/

Пос­коль­ку те ути­литы, что име­ются в этом авто­мати­чес­ком апдей­тере, нем­ного уста­рели (во вся­ком слу­чае, на моем план­шете они завер­шались с сег­фолтом), нуж­но их заменить рабочи­ми, которые берем на d-h.st/RgI, и, рас­паковав, заменя­ем ими фай­лы с теми же наз­вани­ями в катало­ге AnyKernel/kernel/. Кро­ме того, нуж­но изме­нить скрипт для авто­апдей­тера, находя­щий­ся в AnyKernel/META-INF/com/google/android/updater-script. В конеч­ном ито­ге дол­жно получить­ся при­мер­но сле­дующее:

ui_print("Extracting System Files...");
set_progress(1.000000);
mount("ext4","MTD", "system", "/system");
package_extract_dir("system", "/system");
unmount("/system");
ui_print("Extracting Kernel files...");
package_extract_dir("kernel", "/tmp");
ui_print("Installing kernel...");
set_perm(0, 0, 0777, "/tmp/dump_image");
set_perm(0, 0, 0777, "/tmp/mkbootimg.sh");
set_perm(0, 0, 0777, "/tmp/mkbootimg");
set_perm(0, 0, 0777, "/tmp/unpackbootimg");
run_program("/sbin/busybox", "dd", "if=/dev/block/mmcblk0p9", "of=/tmp/boot.img");
run_program("/tmp/unpackbootimg", "-i", "/tmp/boot.img", "-o", "/tmp/");
run_program("/tmp/mkbootimg.sh");
run_program("/sbin/busybox", "dd", "if=/tmp/newboot.img", "of=/dev/block/mmcblk0p9");
ui_print("Done!");

Путь /dev/block/mmcblk0p9 здесь — та часть, которую необ­ходимо изме­нить. Это раз­дел boot, и поч­ти на всех устрой­ствах он будет пред­став­лен раз­ными фай­лами. Что­бы узнать имя фай­ла на сво­ем устрой­стве, выпол­ни сле­дующую коман­ду:

$ for i in /dev/block/platform/*/by-name/boot; \
do ls -l $i; done

Пос­ле прав­ки запако­выва­ем каталог:

$ cd AnyKernel && zip -r AnyKernel.zip *

За­тем кида­ем файл на устрой­ство и уста­нав­лива­ем его с помощью кас­томно­го рекаве­ри (TWRP или CWM).

После сборки и установки ядра должна получиться примерно такая картинка
Пос­ле сбор­ки и уста­нов­ки ядра дол­жна получить­ся при­мер­но такая кар­тинка
 

Сборка приложений

Мо­дули ядра поз­воля­ют добав­лять фун­кци­ональ­ность исклю­читель­но низ­кого уров­ня, которую в общем слу­чае нель­зя исполь­зовать нап­рямую. Для добав­ления же фун­кци­ональ­нос­ти, которую мож­но исполь­зовать нап­рямую, нуж­но собирать прог­раммы, чем мы сей­час и зай­мем­ся, — поп­робу­ем соб­рать нес­коль­ко при­ложе­ний. Перед сбор­кой поч­ти всех при­ложе­ний нуж­но экспор­тировать ряд перемен­ных:

$ export CROSS_COMPILE=$CROSS_COMPILE_LINARO
$ export CC=arm-unknown-linux-gnueabi-gcc
$ export CPP=arm-unknown-linux-gnueabi-cpp
$ export CXX=arm-unknown-linux-gnueabi-g++
$ export LD=arm-unknown-linux-gnueabi-ld
$ export AS=arm-unknown-linux-gnueabi-as
$ export AR=arm-unknown-linux-gnueabi-ar
$ export RANLIB=arm-unknown-linux-gnueabi-ranlib
$ export CPPFLAGS="--sysroot=$LINARO_SYSROOT"
$ export CFLAGS="--static --sysroot=$LINARO_SYSROOT"
$ export CXXFLAGS="--sysroot=$LINARO_SYSROOT"
$ export LDFLAGS="--sysroot=$LINARO_SYSROOT"

И лишь затем мож­но прис­тупать.

 

Bash

Bash собирать с помощью тул­чей­на Linaro очень лег­ко — ска­чива­ем исходни­ки c офи­циаль­ного FTP и рас­паковы­ваем:

$ wget http://ftp.gnu.org/gnu/bash/bash-4.3.30.tar.gz
$ tar xzvf bash-4.2.53.tar.gz && cd bash-4.3.30

Вы­пол­няем скрипт configure и собира­ем:

$ ./configure --host=arm-linux --enable-static-link --without-bash-malloc --disable-rpath --disable-nls
$ make

Пос­ле сбор­ки появит­ся файл bash, который мы и копиру­ем на устрой­ство в /system/xbin.

Bash, запущенный под Android
Bash, запущен­ный под Android

Сто­ит дать ком­мента­рии, почему bash нуж­но ком­пилиро­вать с помощью тул­чей­на Linaro. В Bionic, стан­дар­тной реали­зации биб­лиоте­ки libc в Android, отсутс­тву­ют некото­рые POSIX-сов­мести­мые фун­кции, исполь­зуемые bash (такие, нап­ример, как mkfifo() или wctomb()). Соот­ветс­твен­но, соб­рать bash с исполь­зовани­ем этой биб­лиоте­ки без тан­цев с буб­ном не вый­дет. В Linaro же, с дру­гой сто­роны, исполь­зует­ся стан­дар­тная POSIX-сов­мести­мая биб­лиоте­ка glibc. Пос­коль­ку мы собира­ем bash ста­тичес­ки, нам все рав­но, что исполь­зует­ся в Android, — глав­ное, что­бы вер­сия glibc, с которой мы собира­ем, подош­ла к ядру. Впро­чем, сегод­ня обратное малове­роят­но.

 

Lshw

Lshw — удоб­ная кон­соль­ная ути­лита, поз­воля­ющая быс­тро соб­рать информа­цию о дос­тупном железе. Ком­пилиро­вать ее (опять же исполь­зуя Linaro) дос­таточ­но прос­то. Ска­чива­ем пос­леднюю вер­сию, рас­паковы­ваем и заменя­ем в фай­лах src/Makefile и src/core/Makefile ком­пилятор C++ на ком­пилятор от Linaro (перемен­ной CXX нуж­но прис­воить зна­чение arm-unknown-linux-gnueabi-g++), добавив так­же опцию --static в CXXFLAGS. Затем собира­ем обыч­ным обра­зом.

 

Htop

Это дос­таточ­но удоб­ный кон­соль­ный менед­жер про­цес­сов для Linux. Для вывода информа­ции он исполь­зует биб­лиоте­ку ncurses, так что для его ком­пиляции пот­ребу­ется чуть боль­ше вре­мени. Соз­даем каталог htop, перехо­дим в него и ска­чива­ем ncurses:

$ mkdir htop && cd $_
$ wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
$ tar xzvf ncurses-5.9.tar.gz
$ cd ncurses-5.9

Ус­танав­лива­ем перемен­ную $SYSROOT_ADDITIONS, запус­каем configure с нуж­ными парамет­рами и собира­ем:

$ export SYSROOT_ADDITIONS=${HOME}/htop/rootdir
$ ./configure --with-normal --without-shared --without-cxx-binding --enable-root-environ --disable-widec --disable-GPM --without-ada --without-tests --host=arm-linux --prefix=$SYSROOT_ADDITIONS
$ make && make install

Пос­коль­ку нам нет смыс­ла вклю­чать под­дер­жку юни­кода и мыши и мы не собира­емся делать эту биб­лиоте­ку динами­чес­кой, отклю­чаем эти опции (а так­же отклю­чаем под­дер­жку язы­ка Ada).

Ска­чива­ем и рас­паковы­ваем сам htop, пред­варитель­но перей­дя на уро­вень выше:

$ cd ..
$ wget http://hisham.hm/htop/releases/1.0.3/htop-1.0.3.tar.gz
$ tar xzvf htop-1.0.3.tar.gz
$ cd htop-1.0.3

Вновь пере­опре­деля­ем перемен­ные окру­жения для сбор­ки:

$ export CPPFLAGS="--sysroot=$LINARO_SYSROOT"
$ export CFLAGS="--static -I${SYSROOT_ADDITIONS}/include --sysroot=$LINARO_SYSROOT"
$ export CXXFLAGS="--sysroot=$LINARO_SYSROOT"
$ export LDFLAGS="-L${SYSROOT_ADDITIONS}/ncurses-5.9/lib --sysroot=$LINARO_SYSROOT"
$ export LIBS="${SYSROOT_ADDITIONS}/lib/libncurses.a"

Кон­фигури­руем и собира­ем:

$ ./configure --host=arm --enable-static --disable-unicode
$ make

Все бы хорошо, но пос­ле попыт­ки запус­ка на устрой­стве вывали­вает­ся ошиб­ка «Error opening terminal: screen». Лечит­ся это прос­то — дос­таем отку­да‑нибудь каталог terminfo (я его выдер­нул из Terminal IDE, прос­то потому, что он ока­зал­ся под рукой), копиру­ем в /system/etc и выпол­няем в тер­минале на гад­жете сле­дующую коман­ду:

# export TERMINFO=/system/etc/terminfo

Пос­ле это­го htop запус­тится без заморо­чек.

Htop, запущенный под Android
Htop, запущен­ный под Android
 

Tmux

Tmux — менед­жер тер­миналов, более прод­винутая аль­тер­натива извес­тно­го всем адми­нам screen, соз­данная раз­работ­чиками OpenBSD. В слу­чае с Android его удоб­но исполь­зовать для работы с устрой­ством через adb shell или SSH (нап­ример, ходить на TV Box или HDMI-стик под управле­нием Android. — Прим. ред.).

Для ком­пиляции tmux нам понадо­бит­ся все та же ncurses — ее мож­но взять из пре­дыду­щей сбор­ки, ско­пиро­вав каталог rootdir. Помимо ncurses, пот­ребу­ется биб­лиоте­ка libevent. Соз­даем каталог tmux, уста­нав­лива­ем перемен­ную $SYSROOT_ADDITIONS и ска­чива­ем libevent и сам tmux:

$ export SYSROOT_ADDITIONS=${HOME}/tmux/rootdir
$ git clone https://github.com/libevent/libevent.git
$ git clone git://git.code.sf.net/p/tmux/tmux-code

Со­бира­ем libevent:

$ cd ../libevent
$ ./autogen.sh
$ ./configure --host=arm-linux --disable-shared --disable-openssl --disable-samples -prefix=$SYSROOT_ADDITIONS
$ make && make install

Под­готав­лива­емся к сбор­ке tmux:

$ export CFLAGS="--static -I${SYSROOT_ADDITIONS}/include -I/${SYSROOT_ADDITIONS}/include/ncurses --sysroot=$LINARO_SYSROOT"
$ export LDFLAGS=" -L${SYSROOT_ADDITIONS}/lib -L${SYSROOT_ADDITIONS}/include -L${SYSROOT_ADDITIONS}/include/ncurses --sysroot=$LINARO_SYSROOT"
$ export LIBEVENT_CFLAGS="-I${SYSROOT_ADDITIONS}/include --sysroot=$LINARO_SYSROOT"
$ export LIBEVENT_LIBS="-L${SYSROOT_ADDITIONS}/lib -levent --sysroot=$LINARO_SYSROOT"

И наконец, собира­ем сам tmux:

$ ./configure --enable-static --host=arm-linux && make

Пос­ле сбор­ки и залив­ки исполня­емо­го фай­ла перед запус­ком tmux, помимо перемен­ной TERMINFO, нуж­но опре­делить перемен­ную TMPDIR — лич­но я исполь­зовал /data/local/tmp.

# export TERMINFO=/system/etc/terminfo
# export TMPDIR=/data/local/tmp

Сто­ит заметить, что tmux может работать толь­ко от рута, потому что пра­ва дос­тупа не поз­воля­ют писать в выше­ука­зан­ную пап­ку кому попало.

Сеанс SSH-соединения с Android. Для разделения терминала используется tmux. В левой части можно увидеть вывод lshw
Се­анс SSH-соеди­нения с Android. Для раз­деления тер­минала исполь­зует­ся tmux. В левой час­ти мож­но уви­деть вывод lshw
 

Ngrep

А это край­не полез­ная ути­лита, поз­воля­ющая отлавли­вать пакеты с задан­ным пат­терном (может быть нуж­но, нап­ример, для отладки RESTful-при­ложе­ний). Для ее сбор­ки пот­ребу­ется соб­рать еще и libpcap. Как обыч­но, соз­даем каталог, куда и ска­чива­ем libpcap, рас­паковы­ваем его и собира­ем:

$ mkdir ngrep && cd $_
$ wget http://www.tcpdump.org/release/libpcap-1.6.2.tar.gz
$ tar xzvf libpcap-1.6.2.tar.gz
$ cd libpcap-1.6.2
$ export SYSROOT_ADDITIONS=${HOME}/ngrep/rootdir
$ ./configure --host=arm-linux --disable-shared --with-pcap=linux --disable-dbus --prefix=$SYSROOT_ADDITIONS
$ make && make install

Ска­чива­ем сам ngrep, рас­паковы­ваем, собира­ем:

$ export CFLAGS="--static -I${SYSROOT_ADDITIONS}/include -I${SYSROOT_ADDITIONS}/include/pcap --sysroot=$LINARO_SYSROOT"
$ export LDFLAGS=" -L${SYSROOT_ADDITIONS}/lib -L${SYSROOT_ADDITIONS}/include -L${SYSROOT_ADDITIONS}/include/pcap --sysroot=$LINARO_SYSROOT"
$ ./configure --enable-static --disable-dropprivs --host=arm-linux --with-pcap-includes=${SYSROOT_ADDITIONS}/include/pcap
$ make

Раз­берем опции обо­их configure. В слу­чае с libpcap мы отклю­чили под­дер­жку DBUS по понят­ной при­чине отсутс­твия его в Android и ука­зали тип зах­вата пакетов (пос­коль­ку ком­пилиру­ем мы в конеч­ном ито­ге под Linux, то и тип зах­вата ста­вим соот­ветс­тву­ющий). Для ngrep же мы ука­зали путь к заголо­воч­ным фай­лам libpcap и отклю­чили пониже­ние при­виле­гий по при­чине отсутс­твия фай­ла /etc/passwd в Android, куда эта фун­кци­ональ­ность смот­рит.

Перехватываем пакеты, содержащие слово google, используя ngrep
Пе­рех­ватыва­ем пакеты, содер­жащие сло­во google, исполь­зуя ngrep
 

Linux Deploy

Ком­пиляция прог­рамм может занять немало вре­мени, да и не вся­кое при­ложе­ние мож­но с лег­костью соб­рать (нап­ример, тек­сто­вый torrent-кли­ент rtorrent пот­ребу­ет сбор­ку libtorrent, а уж эта биб­лиоте­ка, в свою оче­редь, потянет за собой Boost). И если для пары‑трой­ки при­ложе­ний это не столь кри­тич­но, то в слу­чае сбор­ки боль­шего количес­тва тру­дозат­раты ста­новят­ся слиш­ком велики. Да и сами при­ложе­ния в слу­чае ста­тичес­кой ком­понов­ки могут раз­дувать­ся до нево­обра­зимых раз­меров. Одна­ко есть решение и для этой ситу­ации — Linux Deploy, который с лег­костью мож­но най­ти в Google Play.

Пос­коль­ку Android пос­тро­ен на базе ядра Linux, а изме­нения в нем не нас­толь­ко силь­ны, что­бы мешать запус­ку обыч­ных POSIX-при­ложе­ний (что и было про­демонс­три­рова­но выше), сущес­тву­ет воз­можность раз­верты­вания chroot-окру­жения (с проб­росом соот­ветс­тву­ющих псев­дофай­ловых сис­тем) и уста­нов­ки в нем userland-час­ти дис­три­бути­вов, под­держи­вающих архи­тек­туру ARM. При­ложе­ние Linux Deploy дела­ет имен­но это, соз­давая образ и мон­тируя его как loop-устрой­ство.

Под­держи­вают­ся сле­дующие дис­три­бути­вы:

  • Ubuntu;
  • OpenSUSE;
  • Fedora;
  • Arch Linux;
  • Gentoo;
  • и, наконец, Kali Linux (его наличие, несом­ненно, обра­дует пен­тесте­ров).

Пос­ле раз­верты­вания и запус­ка сис­темы в нее необ­ходимо каким‑то обра­зом вой­ти. Для это­го сущес­тву­ет два метода: по SSH и через VNC. При наличии SSH-сер­вера в самом Android в Linux Deploy нуж­но либо его отклю­чить, либо пере­опре­делить порт. А если исполь­зовать VNC, необ­ходимо доус­тановить в Android VNC-кли­ент (рекомен­дую bVNC). Стан­дар­тные имя поль­зовате­ля / пароль — android/changeme соот­ветс­твен­но.

Запуск окружения Ubuntu в Linux Deploy
За­пуск окру­жения Ubuntu в Linux Deploy
Ubuntu в Linux Deploy по виду неотличим от десктопного
Ubuntu в Linux Deploy по виду неот­личим от дес­ктоп­ного

В дан­ном кон­тей­нере мож­но про­изво­дить прак­тичес­ки те же дей­ствия, что и в обыч­ном нас­толь­ном дис­три­бути­ве Linux, — со скид­кой на под­держи­ваемую ядром фун­кци­ональ­ность. Замечу, что кон­тей­нер не изо­лиро­ван от основной сис­темы, и запуск служб в некото­рых дис­три­бути­вах не под­держи­вает­ся по при­чине исполь­зования в них сов­ремен­ных сис­тем ини­циали­зации. Так­же сто­ит пом­нить, что при­ложе­ния в кон­тей­нере натив­ные, — это изрядно куша­ет батарею.

 

Заключение

В статье были опи­саны два (а если счи­тать ком­пиляцию ядра с модуля­ми, то три) метода рас­ширения фун­кци­ональ­нос­ти на Android. Под­ведем ито­ги.

Ком­пиляция ядра и модулей име­ет смысл толь­ко в тех слу­чаях, ког­да тебе нуж­на низ­коуров­невая фун­кци­ональ­ность — будь то под­дер­жка ФС или, допус­тим, модуль iptables. В сов­ремен­ных сто­ковых ядрах под­дер­жка заг­рузки модулей чаще все­го отклю­чена, так что для добав­ления фун­кци­ональ­нос­ти вся­ко пот­ребу­ется ком­пиляция все­го ядра.

В слу­чае с ком­пиляци­ей неболь­ших POSIX-при­ложе­ний мож­но попытать­ся исполь­зовать гуг­лов­ский NDK, иду­щий с Bionic и прак­тичес­ки несов­мести­мый с POSIX, а мож­но исполь­зовать сто­рон­ний тул­чейн для архи­тек­туры ARM, в котором, как пра­вило, есть биб­лиоте­ка glibc, и ком­пилиро­вать при­ложе­ния ста­тичес­ки. Одна­ко сле­дует пом­нить, что ста­тичес­ки слин­кован­ное при­ложе­ние весит дос­таточ­но мно­го, таким обра­зом, нелиш­ним будет еще раз под­чер­кнуть, что этот метод годит­ся лишь для неболь­ших при­ложе­ний.

Для запус­ка круп­ных при­ложе­ний мож­но исполь­зовать Linux Deploy, поз­воля­ющий раз­вернуть на Android пол­ноцен­ную userland-часть популяр­ных дис­три­бути­вов. Одна­ко и у него есть недос­татки. Во‑пер­вых, он изрядно куша­ет батарею, а во‑вто­рых, раз­мер обра­за с дан­ной userland-частью не может быть боль­ше 4 Гб, так что, если рас­катал губу на кучу при­ложе­ний, закатай ее обратно.

В целом же запуск POSIX-при­ложе­ний в Android впол­не воз­можен — что и было показа­но в статье. А уж каким спо­собом ты будешь что‑то делать, ты волен выбирать сам. Stay freedom.

Библиотеки, портированные на Android

Нес­мотря на то что Android не явля­ется в пол­ной мере POSIX-сов­мести­мой ОС, под него все же были пор­тирова­ны некото­рые из биб­лиотек, дос­тупных под дес­ктоп­ной Linux. Пос­мотрим, что это за биб­лиоте­ки:

  • SDL — удоб­ная «обер­тка» вок­руг низ­коуров­невых муль­тимеди­афун­кций; исполь­зует­ся в основном для раз­работ­ки игр;
  • FFmpeg — кон­верта­ция боль­шинс­тва аудио- и виде­офор­матов;
  • Qt — начиная с пятой вер­сии, Qt дос­тупна и под Android;
  • Unity — игро­вой дви­жок;
  • Ogre — «обер­тка» вок­руг OpenGL для работы с 3D-гра­фикой.

В общем, с точ­ки зре­ния пор­тирова­ния при­ложе­ний выб­рать есть из чего.

Оставить мнение