📜 ⬆️ ⬇️

Debugging native code for Android: manual and automated testing

With the development and growth of the popularity of the Android OS, the number and variety of devices under its control is steadily increasing. Due to differences in architecture, purpose, and optimization, the speed and stability of the executable code can vary significantly. Therefore, to ensure stability and optimization of applications and operating systems, especially using features of a specific architecture, platform, or code ported from other platforms, special attention should be paid to the process of debugging code for Android. In this article we will talk about the key points and features of working with native-code for Android. Anyone who is interested in this manual, please under the cat.

image


Back in 2007, Google released a new generation of operating systems - Android .
')
Its appearance has made a real revolution in the market of mobile devices, suppressing the hegemony of Microsoft Widows Mobile, Apple iOS and Symbian OS, in consequence of becoming the most popular and mass operating system for mobile systems in the world. Until now, the popularity of the system continues . Over the past six years, Android has greatly expanded and evolved, and the range of supported devices continues to grow. Now this operating system is used not only in mobile phones, but also in tablets, TVs, music players, cameras, laptops, nettops and other exotic things, including military equipment. The fillings of these devices can differ quite noticeably from each other: over the past years, the list of supported architectures has expanded from ARM to MIPS and x86, support has been provided for various peripherals, not to mention the evolving Android API.

Such a huge number of different devices, despite their functional and architectural differences, are controlled by the same system, minus platform-specific libraries and optimizations for specific devices. It is quite natural that Android assemblies and even application libraries often differ from each other, often even depending on the vendor, since performance requirements only increase in the face of fierce competition from the growing market for Android devices.



Nevertheless, ensuring unification and cross-platform, application speed is one of the priorities of today's market for high-performance applications and system assemblies. This, first of all, means increased requirements for the operating system itself, which is able to work and do it efficiently on various hardware, as well as high demands on Android applications.



One of the most effective solutions for optimizing and accelerating the operation of applications, the system and its components is optimization at the native, native-level. In other words, the use of optimized, often hardware-dependent libraries and code for the applications and system, and in a global sense - a number of libraries supplied for each of the target platforms. Such a variety of hardware platforms, different operating system versions, API platforms, and requirements for ensuring stable and fast operation of applications requires considerable efforts to test applications and libraries for specific configurations.

Nevertheless, one of the most convenient tools for Android developers is still the Android NDK - Android Native Development Kit , which includes almost everything needed to develop and debug applications, libraries, and the system itself.

In this article, I will discuss its use for testing and debugging Android native code and testing automation using the example of such a framework as DejaGnu .
Android is developing very dynamically, and now DejaGnu comes with almost everything needed for a quick start of testing, both with and without Android NDK. The main objective of this article will be a story about the nuances and features of testing for Android and some of the pitfalls that engineers may encounter.

For a start, a small remark: Android, as you know, is a Unix-like operating system, very similar to regular Linux or BSD, and most Android source code follows a license, ASL2.0 . Who worked with Android, knows that a considerable number of Android modules have moved from BSD to a greater extent than from Linux. However, everything related to native-code and architecture, if not to go into details, is very close and known to all those who used Linux. Therefore, it is quite possible to use exactly the same or similar tools for developing and debugging code as for Unix-like systems. In the case of compilers, these are gcc, clang (llvm), icc and others. The same can be said about the whole GCC toolchain and some other utilities that are either already ported or not very difficult to port.

The main reason for including native code or using native libraries in native applications is the desire to increase performance or reuse previously written C / C ++ / ASM code from a Linux / Unix-like system.

Advantages of using native code :
• High performance
• Direct use of CPU / HW features
• Ability to reuse existing Linux code

Disadvantages of using native code :
• Individual setting for CPU / HW
• Insufficient support for system libraries

Pros and cons require thorough testing, both in terms of code quality, stability, and in terms of its performance on different platforms. In spite of the fact that one of the postulates of Android is independence from hardware, in order to work on various configurations, in fact, native-code applications are supplied in so-called fat binary (apk, including native-code / libraries for all possible hardware configurations). under which the application will work). Despite the fact that, ideally, the NDK compiler should create functionally equivalent code for different configurations and, therefore, the libraries for fat binary (or system ones for the image) should be equivalent - this, unfortunately, does not always correspond to reality and requires testing, especially when it comes to optimization (Neon and SSE for example) and the use of third-party libraries.



In addition, with the development of the Android OS and devices under its control, various versions of the OS, the delivery of this OS, as well as the specifics of the devices, change regularly. In some cases, it is justified for the developer to use some kind of optimizations or another compiler to build native code. Evaluating the performance, correctness and stability of this code on various configurations is the task of the tester who is engaged in Android Native testing.
The process of building, debugging and testing native applications for Android is not much different from the same process on Linux, with the only difference that we collect binary files (executable and libraries) not on Android, but on the host (Linux, MacOS, Windows) and execute on an Android device (physical or emulator). Therefore, adb - the Android Debug Bridge, which is part of the Android SDK , is a universal means of communicating a host with an Android device. For building and debugging applications, it is advisable to use the toolchain and API that we need, as well as, if necessary (for c ++), the version of the stdc ++ library that interests us.

Android native builds can vary by:
  1. API versions used:
  2. versions of libstdc ++ used:
  3. device architecture (target):
  4. bit depth (32, 64 or x32) target:
  5. build host and bit depth:


However, from the point of view of the developer and the tester, there should be no differences between the resulting code depending on the build host, and it is not necessary to use different configurations of build hosts for testing and testing.
The number of options for testing grows threateningly, and this does not take into account the optimization of the CPU instructions: neon, core-avx2, core-i7, atom, slm; by size \ speed and other. All this Cartesian product of variants of the obtained code (source and binary) is the starting point for testing. In the case when the purpose of testing is the device itself or some custom build of Android, then, quite likely, the main significant difference will be the bionic library - an analogue of the libc library for Android.

Having finished the introductory theory, it's time to move on to practice.

Tools for manual assembly and testing



All the necessary tools are included in the delivery of Android NDK , which is for 32 and 64 bits under Linux, MacOS, Windows.

Creating and running the application


gcc

bash-4.2$ #   hello_world.c bash-4.2$ cat ./hello_world.c #include <stdio.h> int main(void) { printf(“Hello, World!\n”); return 0; } bash-4.2$ #   Android,  gcc 4.7  x86,  18 bash-4.2$ /users/NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gcc –sysroot=/users/NDK_current/platforms/android-18/arch-x86 ./hello_world.c -o ./hello_world.exe bash-4.2$ echo $? 0 bash-4.2$ #,  bash-4.2$ #  bash-4.2$ ./hello_world.exe bash-4.2$ #,     bash-4.2$ #     bash-4.2$ adb devices List of devices attached 0146AFFC18020012 device bash-4.2$ #,   -    bash-4.2$ adb -s 0146AFFC18020012 shell echo 'Hello, Android!' Hello, Android! bash-4.2$ #,       bash-4.2$ export ANDROID_SERIAL=0146AFFC18020012 bash-4.2$ #   bash-4.2$ adb shell echo 'Hello, Android!' Hello, Android! bash-4.2$ #- ,      bash-4.2$ adb push ./hello_world.exe /data/local/ bash-4.2$ #- ,   bash-4.2$ adb shell /data/local/hello_world.exe Hello, World! bash-4.2$ #adb ,   ,    ,    bash-4.2$ adb shell “/data/local/hello_world.exe && echo $?” Hello, World! 0 bash-4.2$ #,          bash-4.2$ #   ,        bash-4.2$ #  ,        (linux, mac, windows) bash-4.2$ #   ,   -     bash-4.2$ #  ,    -static /users//NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gcc –sysroot=/users/ /NDK_current/platforms/android-18/arch-x86 -static ./hello_world.c -o ./hello_world.exe bash-4.2$ echo $? 0 bash-4.2$ #,      -         bash-4.2$ ./hello_world.exe Hello, World! bash-4.2$ echo $? 0 bash-4.2$ #,           bash-4.2$ 


g ++


 bash-4.2$ #      g++ bash-4.2$ cat ./hello_world.C #include <iostream> int main(void) { std::cout << “Hello, World!\n”; return 0; } bash-4.2$ #    STL,  bash-4.2$ #          bash-4.2$ #    ,     bash-4.2$ # ,   -l%STL_LIB%      ! bash-4.2$ #    _shared,   _static  bash-4.2$ #    g++ -L, -I     – gnustl/stlport/gabi bash-4.2$ /users/ /NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-g++ –sysroot=/users/NDK_current/platforms/android-18/arch-x86 -I/users/NDK_current/sources/cxx-stl/gnu-libstdc++/4.7/include -I/users/NDK_current/sources/cxx-stl/gnu-libstdc++/4.7/libs/x86/include -L/users//NDK_current/sources/cxx-stl/gnu-libstdc++/4.7/libs/x86 ./hello_world.C -o ./hello_world.exe -lgnustl_shared bash-4.2$ echo $? 0 bash-4.2$ #,      -    /   /  bash-4.2$ adb push ./hello_world.exe /data/local/ bash-4.2$ #- ,   bash-4.2$ adb shell “/data/local/hello_world.exe && echo $?” soinfo_link_image(linker.cpp:1635): could not load library “libgnustl_shared.so” needed by “/data/local/hello_world.exe”; caused by load_library(linker.cpp:745): library “libgnustl_shared.so” not foundCANNOT LINK EXECUTABLE bash-4.2$ # ,    bash-4.2$ #libgnustl_shared.so     Android,       bash-4.2$ adb push /users//NDK_current/sources/cxx-stl/gnu-libstdc++/4.7/libs/x86/libgnustl_shared.so /data/local/libgnustl_shared.so bash-4.2$ #,   ,    LD_LIBRARY_PATH bash-4.2$ adb shell “export LD_LIBRARY_PATH=/data/local/:$LD_LIBRARY_PATH && /data/local/hello_world.exe && echo $\?” Hello, World! 0 bash-4.2$ #       – /system/lib bash-4.2$ # bash-4.2$ adb shell “/data/local/hello_world.exe && echo $\?” Hello, World! 0 bash-4.2$ 

If the host and target architectures coincide (usually x86) and root privileges, it is quite possible to use a cunning trick with launching Android x86 binaries on the host if desired. To do this, you must explicitly use the dynamic linker for Android on the system (/ system / bin / linker), as well as use the non-stripped version of the bionic in the ways (LD_LIBRARY_PATH). See the example Makefile: ( https://android.googlesource.com/platform/bionic/+/master/tests/Android.mk : bionic-unit-tests-run-on-host).

 # ----------------------------------------------------------------------------- # Run the unit tests built against x86 bionic on an x86 host. # ----------------------------------------------------------------------------- ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86) ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64)) ifeq ($(TARGET_ARCH),x86) LINKER = linker else LINKER = linker64 endif # gtest needs ANDROID_DATA/local/tmp for death test output. # Make sure to create ANDROID_DATA/local/tmp if doesn't exist. # bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT. bionic-unit-tests-run-on-host: bionic-unit-tests $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh if [ ! -d /system -o ! -d /system/bin ]; then \ echo "Attempting to create /system/bin"; \ sudo mkdir -p -m 0777 /system/bin; \ fi mkdir -p $(TARGET_OUT_DATA)/local/tmp cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin ANDROID_DATA=$(TARGET_OUT_DATA) \ ANDROID_ROOT=$(TARGET_OUT) \ LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \ $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests endif endif 


Such a trick, for example, is relevant for the execution of binary files without an emulator (in the absence of a 64-bit image or using -mx32).

GCOV and profiles

 bash-4.2$ # ,  , - ,          bash-4.2$ #, ,   coverage  bash-4.2$ # ,     ,         bash-4.2$ #     ,   -fprofile-dir=%android_exec_dir% bash-4.2$ #  ,  ,  GCOV_PREFIX  GCOV_PREFIX_STRIP bash-4.2$ #   ,    env      adb ( shell   adb shell %command% bash-4.2$ /users//NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gcc –sysroot=/users//NDK_current/platforms/android-18/arch-x86 ./gcov-1.c -fprofile-arcs -fprofile-dir=. -ftest-coverage -lm -o ./gcov-1.exe bash-4.2$ adb push ./gcov-1.exe /data/local/gcov-1.exe bash-4.2$ #adb shell “export GCOV_PREFIX=/data/local && export GCOV_PREFIX_STRIP=13 && /data/local/gcov-1.exe && echo $\?” bash-4.2$ unset GCOV_PREFIX && unset GCOV_PREFIX_STRIP && cd /data/local && ./gcov-1.exe && echo $\?” 0 bash-4.2$ adb shell ls /data/local/gcov-1.gcda /data/local/gcov-1.gcda bash-4.2$ #  bash-4.2$ adb pull /data/local/gcov-1.gcda . bash-4.2$ ls ./gcov-1.gcda ./gcov-1.gcda bash-4.2$ #  NDK  gcov,   ,   bash-4.2$ /users/NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gcov gcov-1.gcda File 'gcov-1.c' Lines executed:100.00% of 6 Creating 'gcov-1.c.gcov' bash-4.2$ 


image


Debug \ debugging: gdb / logcat


 bash-4.2$ #  NDK     , , gdb bash-4.2$ #        -g,      bash-4.2$ /users /NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gcc –sysroot=/users/NDK_current/platforms/android-18/arch-x86 ./hello_world.c -o ./hello_world.exe bash-4.2$ adb push ./hello_world.exe /data/local/hello_world.exe bash-4.2$ adb shell gdbserver :5039 /data/local/hello_world.exe & Process /data/local/hello_world.exe created; pid = 29744 Listening on port 5039 bash-4.2$ adb forward tcp:5039 tcp:5039 bash-4.2$ /users/NDK_current/toolchains/x86-4.7/prebuilt/linux-x86/bin/i686-linux-android-gdb hello_world.exe Remote debugging from host 127.0.0.1 libthread_db:td_ta_new: Probing system for platform bug. libthread_db:td_ta_new: Running as root, nothing to do. Hello, World! Child exited with status 0 GDBserver exiting bash-4.2$ cat test.gdb set sysroot /users/igveresx set solib-absolute-prefix /users/igveresx/symbols/ set solib-search-path /users/igveresx/symbols/lib set auto-solib-add on target remote :5039 stepi stepi c Quit bash-4.2$ #       logcat bash-4.2$ adb logcat *:E >logcat.log & bash-4.2$ tail -5 logcat.log E/Intel PowerHAL( 2093): Error in reading vsync hint E/Intel PowerHAL( 2093): Error reading from /sys/devices/system/cpu/cpufreq/interactive/vsync_count: No such file or directory E/Intel PowerHAL( 2093): Error in reading vsync count E/Intel PowerHAL( 2093): Error reading from /sys/devices/system/cpu/cpufreq/interactive/touch_event: No such file or directory E/Intel PowerHAL( 2093): Error in reading vsync hint bash-4.2$ #      kernel bash-4.2$ adb shell dmesg | tail -5 <6>[245665.256198] intel_mdf_battery msic_battery: vbus_volt:4974 <6>[245665.265332] intel_mdf_battery msic_battery: vbatt:4116250 temp:300 <4>[245669.213759] kct_daemon: loop. <4>[245673.213561] kct_daemon: loop. <4>[245677.213379] kct_daemon: loop. bash-4.2$ adb shell 'cat /proc/kmsg' >kmsg.log bash-4.2$ tail -5 kmsg.log <4>[245673.213561] kct_daemon: loop. <4>[245677.213379] kct_daemon: loop. <4>[245681.213248] kct_daemon: loop. <4>[245685.213083] kct_daemon: loop. <4>[245689.212932] kct_daemon: loop. bash-4.2$ 


Test Automation


To automate testing, you can use a framework such as dejagnu. Since February 2013, DejaGnu has included the board androideabi, which allows testing native-code on Android via adb.

In general, everything is similar to what was described above, with the exception of some nuances.

For many dejagnu tests, host / target checks for triplets are crucial. For example, at least in order to understand whether it is possible to run a binary file on a device, the host = target = build (native) check is often performed. However, in our case, generally speaking, build_triplet is not equal to target_triplet , but at the same time, we are quite capable of performing and receiving results on Android. In addition, you should take into account the fact that by default NDK uses the –fpic flag, which also affects the ability to run tests and their results (check effective-target pic / nonpic). In the case of static linking, it should be borne in mind that, perhaps, not everything will also meet expectations (the static, dynamic libraries can differ from each other and generate different code ( -fpic / -fpie ). Also, some tests are critical to launch directories or specify a directory for results; and before launching a binary file, change the directory to the desired one.In addition, during the transfer of a binary file to a device, launch rights can be reset (due to the rights to the folder or the rights to the file system ), so it is also worth convincing sya that the executable file is set executable bit. In addition, the best solution for testing organization is the use of non-sd-card and ram-disk with the correct permissions to avoid rapid wear of the first.

To run testing on Android, it’s enough to run with the host installed dejagnu:

runtest –target_board = androideabi


You should make sure that you have explicitly specified the ADB_SERIAL variable corresponding to the serial number of your device.
However, it is much more convenient and pleasant to run testing through the local configuration file - site.exp

For example, the configuration file to run gcc testsuite:
 set rootme “.” set tmpdir “.” set srcdir “/path/to/gcc_%version%_release/gcc/testsuite” set CFLAGS “” set CXXFLAGS “” set GDB “/path/to/GDB_UNDER_TEST” set GCOV_UNDER_TEST “/path/to/GCOV_UNDER_TEST” set GCC_UNDER_TEST “/path/to/GCC_UNDER_TEST” set GXX_UNDER_TEST “/path/to/GXX_UNDER_TEST” set GFORTRAN_UNDER_TEST “no” set OBJC_UNDER_TEST “no” set libiconv “” set HOSTCC “gcc” set HOSTCFLAGS “” set TESTING_IN_BUILD_TREE 1 set GMPINC “” set ENABLE_LTO 1 set HAVE_LIBSTDCXX_V3 1 set host_triplet i686-pc-linux-gnu set build_triplet i686-pc-linux-gnu set target_triplet i686-pc-linux-android-gnu set target_alias i686-pc-linux-android set android_tmp_dir “/temporary/folder/on/device/with/executable/permissions” set bridge_tmp_dir “/temporary/folder/on/device/with/executable/permissions” append boards_dir “/path/to/share/dejagnu/baseboards” 

and to run the same gcc:

 export ADB_SERIAL=$ANDROID_SERIAL make -j $parallel check DEJAGNU=/path/to/site.exp RUNTESTFLAGS=”–target_board=androideabi” 


Note: Please note that you should make sure that during the launch of the gcc check, someone will not rub the variable GCC_EXEC_PREFIX , and that it is unset.

It is worth noting that you should specify not only the path to the compiler, but you should keep in mind everything that we did above manually, namely, to specify:
  • sysroot
  • paths to libraries and header files
  • flags and link libraries (at least for libstdc ++)


Based on this, the best solution is to use an executable file wrapper from the toolchain (wrapper-binaryname), of the following form:

wrapper-gcc

 #!/bin/bash /path/to/NDK_folder/toolchains/$arch-%compiler_version%/prebuilt/linux-x86/bin/%arch_prefix%-linux-android-gcc –sysroot=/path/to/NDK_folder/platforms/android-${device_platform}/arch-$arch “$@” 


wrapper-g ++

 #!/bin/bash echo $@ | grep ” \-nostdlib” 1>/dev/null 2>/dev/null if [ $? != 0 ]; then echo $@ | grep ” \-static” 1>/dev/null 2>/dev/null if [ $? != 0 ]; then /path/to/NDK_folder/toolchains/$arch-%compiler_version%/prebuilt/linux-x86/bin/%arch_prefix%-linux-android-g++ –sysroot=/path/to/NDK_folder/platforms/android-${device_platform}/arch-$arch -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/include -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch/include -L/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch “$@” -lgnustl_shared else /path/to/NDK_folder/toolchains/$arch-%compiler_version%/prebuilt/linux-x86/bin/%arch_prefix%-linux-android-g++ –sysroot=/path/to/NDK_folder/platforms/android-${device_platform}/arch-$arch -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/include -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch/include -L/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch “$@” -lgnustl_static fi else /path/to/NDK_folder/toolchains/$arch-%compiler_version%/prebuilt/linux-x86/bin/%arch_prefix%-linux-android-g++ –sysroot=/path/to/NDK_folder/platforms/android-${device_platform}/arch-$arch -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/include -I/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch/include -L/path/to/NDK_folder/sources/cxx-stl/%stl lib folder%/%compiler version%/libs/$arch “$@” fi 


If necessary, if you need to get some data from Android, then we can use the remote_upload function ( adb_upload% target_board%% source%% dest% ). This functionality should be provided by testsuite.

Profiling, performance testing



In this article, the details of collecting and using profiles will not be discussed in detail, but for Android, the most common profiling tools are:
  • perf
  • oprofile
  • sep

For example, having a static perf assembly, just run:

 adb push perf /data/local/ adb shell cd /data/local chmod 777 perf perf record ./coremark.exe 0×0 0×0 0×66 0 7 1 2000 # or any arguments required # data saved at ./perf.data</li> export PAGER=cat # otherwise it will look for “less” perf report 


Performance testing on Android can be performed not only with the help of benchmarks working through Dalvik, but also at the native-level, i.e. using benchmarks compiled by the same Android NDK. As an example: SPEC , EEMBC , CoreMark .



I will not dwell on the nuances of porting frameworks for Android (they are similar to the methods described above), but it is worth noting that the principle of using adb to work with devices or emulators is also the basis, as well as critical attention to the processes taking place on devices.
You need to make sure that the result is affected:
  • processor mode
  • applications running in the background
  • clean startup and errors (which can and should be tracked through logcat / dmesg)


Relevant results can be obtained only on deterministic devices (if we are not talking about obtaining a profile of real use of the device and application). Therefore, before starting it is necessary to make sure that:
  • All non-essential services and applications are disabled.
  • The device is used exclusively
  • The device is hard set mode


For example, for testing CPUs, a typical practice is to set all processor cores and frequencies to an equal value and fix them. If necessary, disable all cores, in addition, on which the testing takes place.

 adb shell echo userspace > /sys/devices/system/cpu/cpuX/cpufreq/scaling_governor echo 2000000 > /sys/devices/system/cpu/cpuX/cpufreq/scaling_max_freq echo 2000000 > /sys/devices/system/cpu/cpuX/cpufreq/scaling_min_freq 


Make sure that the value
/ sys / devices / system / cpu / cpuX / cpufreq / online is also installed correctly depending on the benchmark \ profile and \ or testing needs.
Just by making sure that everything works in the right mode (cat / proc / cpuinfo) you can begin testing and analysis.

To simplify the work and debug the native-code, for Android there is a set of utilities busybox , which is not included in the Android package by default (since it is supplied under the GPL 2.0 license).
[, [[, ar, arp, awk, base64, basename, bbconfig, beep, blkid, blockdev, bootchartd, bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr, chgrp, chmod, chown, chpst, chroot, chrt, chvt, cksum, clear, cmp, comm, cp, cpio, crond, crontab, cttyhack, cut, dc, dd, deallocvt, depmod, devmem, diff, dirname, dmesg, dnsd, dos2unix, dpkg, dpkg-deb, du, dumpkmap, echo, ed, egrep, env, envdir, envuidgid, expand, expr, fakeidentd, false, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs, flash_lock, flash_unlock, flashcp, flock, fold, free, freeramdisk, fsync, ftpd, ftpget, ftpput, fuser, getopt, grep, gunzip, gzip, halt, hd, hdparm, head, hexdump, httpd, hwclock, ifconfig, ifdown, ifup, init, inotifyd, insmod, install, iostat, ip, ipaddr, ipcalc, iplink, iproute, iprule, iptunnel, klogd, less, linuxrc, ln, loadkmap, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lsof, lspci, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, md5sum, mdev, mesg, mkdir, mkfifo, mknod, mkswap, mktemp, modinfo, modprobe, more, mpstat, mv, nbd-client, nc, netstat, nice, nmeter, nohup, od, openvt, patch, pidof, ping, pipe_progress, pmap, popmaildir, poweroff, powertop, printenv, printf, ps, pscan, pstree, pwd, pwdx, raidautorun, rdev, readlink, readprofile, realpath, reboot, reformime, renice, reset, resize, rev, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-parts, runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setconsole, setkeycodes, setlogcons, setserial, setsid, setuidgid, sha1sum, sha256sum, sha3sum, sha512sum, showkey, sleep, smemcap, softlimit, sort, split, start-stop-daemon, strings, stty, sum, sv, svlogd, switch_root, sync, sysctl, tac, tail, tar, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time, timeout, top, touch, tr, traceroute, true, ttysize, tunctl, tune2fs, udpsvd, uname, uncompress, unexpand, uniq, unix2dos, unlzma, unlzop, unxz, unzip, uptime, usleep, uudecode, uuencode, vconfig, vi, volname, watch, wc, wget, which, whoami, whois, xargs, xz, xzcat, yes, zcat

Using the approach described in the article, you can quickly and easily port testing from Linux to Android, create from scratch and debug for various hardware configurations and emulators with the least amount of time.

Source: https://habr.com/ru/post/204642/


All Articles