Search code examples
androiddocumentationlibcbionic

Where is the Android libc documentation?


For glibc you can find an online documentation here.

I am looking for an equivalent documentation for Android's libc implementation (headers located under sysroot/usr/include).

Is there a documentation for these?

(For example the call statfs() under sysroot/usr/include/sys/vfs.h).


Solution

  • Where is the Bionic documentation?

    Google’s documentation is sparse, to say the least. You can find it here and here. There’s a lot of good information if you’re generally familiar with C run-time libraries, but there is no full set of function-by-function documentation. Google appear to assume that you won’t be learning C/C++ programming for the first time on Android.

    The OpenBSD manual pages are available here. Use the form in the top part of the page to select a different function.

    The definitive source on functions available is the header files. Since you can install the NDK anywhere in your filesystem, I’ll describe the header locations relative to the NDK directory:

    On Windows, you’ll find most of them in:

    <NDK-directory>\sysroot\usr\include
    

    However, some headers, which are closely associated with the compiler, are in:

    <NDK-directory>\toolchains\llvm\prebuilt\windows-x86_64\lib64\clang\<clang-version>\include
    

    On Linux, those directories are:

    <NDK-directory>/sysroot/usr/include
    <NDK-directory>/lib64/clang/<clang-version>/include
    

    Why does Android use Bionic rather than glibc?

    When the Android project was taking shape, Google had some specific requirements for a C run-time library for it:

    • Small. Early Android devices had much less RAM than current equipment. The HTC Dream, the first Android device on sale, had 192MB, whereas 1GB is now the minimum. As well as the code being small, the library could not require large amounts of working memory.

    • Fast. The Dream ran at 528MHz, as opposed to 1GHz or more for current low-end devices. The size and speed requirements meant that simplicity was very desirable.

    • BSD-licensed. Google very much wanted to avoid application developers having to use GPL-licensed libraries. In the first decade of this century, open source was far less accepted in business, and many companies who were potential app suppliers would have nothing to do with GPL or other copyleft licenses. In early Android native code work, static linking was quite common, and if you statically link to GPL’ed code, you need to open-source your own code. The BSD license is far more permissive: you can do pretty much what you like with BSD-licensed code, provided you acknowledge it is present.

    Glibc evolved on reasonably fast PCs, which had far more RAM and processor speed than early Android devices, so it did not have the same pressure to be small and simple. The PCs could also use "swapping" of data and programs between memory and disk. Android has never supported that: the physical RAM is all of the memory that can be in use by all the programs running at the same time.

    Glibc is also a very complete C run-time library, with most of the features of every other C run-time combined. It’s also compatible with a very wide range of hardware and operating systems. Both of those things tend to make it bigger. It uses the LGPL, rather than full GPL, but understanding the distinction requires you to understand the difference between static and dynamic linking. Google didn’t want to try educating executives about that.

    Bionic has only ever supported ARM32, ARM64, x86, x86-64, MIPS and MIPS64, all of them little-endian. The only operating system kernel it has ever supported is Linux. Multi-threading is always in operation, and there’s always an MMU. These things definitely simplify the code of Bionic.

    An overview of Bionic from Android 4.0 can be found here.

    Differences from standards

    Bionic does not support all of POSIX, although it is fairly close. It contains many BSD extensions, and quite a few glibc extensions that don’t increase memory use unduly. Some things are deliberately excluded at the expense of standards conformance. For example, printf does not support the %n formatter on security grounds (a very sound decision), and there are no Unix password database functions because Android doesn’t have that kind of database.

    Evolution of Bionic

    The library has gained more functionality over the life of Android. The C headers in modern versions of the NDK contain conditional compilation that let you choose a version of Android as the oldest you’re supporting. Only functions present on that version will be available in your compiles. From personal experience, porting C/C++ code to Android 5.0 “Lollipop” is considerably easier than for earlier versions. A lot of classic Unix functionality appeared then.

    Where did the code in Bionic come from?

    Quite a lot of it comes from the various BSD Unixes. Changes were needed to run on a Linux, rather than BSD, kernel. OpenBSD seems to be the largest contributor, but the math library is mostly from FreeBSD, with optimised assembler routines from SoC manufacturers. The pthreads library, and the dynamic linker were written from scratch. There is no separate libpthread, as it and many other extensions to a traditional Unix libc have been incorporated into Bionic’s libc.

    C++

    Bionic is a C run-time library, but C++ code often calls it. The C++ run-time library, unlike Bionic, is not part of the Android operating system. Historically, several different C++ runtimes were available, but nowadays libc++ from the LLVM project is the standard. You have to include libc++_shared.so in your application APK, since it is not provided by the operating system. This wastes some memory and storage, but not very much by the standards of modern apps.