143 lines
12 KiB
Typst
143 lines
12 KiB
Typst
#import "../lib.typ": todo, num, APK, JAR, AXML, ART, SDK, JNI, NDK, DEX, XML, API, ZIP, jfl-note
|
|
|
|
== Android <sec:bg-android>
|
|
|
|
Android is the smartphone operating system develloped by Google.
|
|
It is based on a Long Term Support Linux Kernel, to which are added patches develloped by the Android community.
|
|
On top of the kernel, Android redeveloped many of the usual components used by linux-based operating systems, and added new ones.
|
|
Those change make Android a verry unique operating system.
|
|
#jfl-note[][Chiffres pour illustrer?]
|
|
|
|
=== Android Applications <sec:bg-android>
|
|
|
|
Application in the Android ecosystem are distributed in the #APK format.
|
|
#APK files are #JAR files with additionnal features, which are themself #ZIP files with additionnal features.
|
|
|
|
A minimal #APK file contains a file `AndroidManifest.xml`, the `META-INF/` folder containing the #JAR manifest and signature files, and an #APK Signing Block at the end of the #ZIP file.
|
|
The code of the application is then store in a custom format, the Dalvik bytecode, or in the binary ELF format, called native code in the Android ecosystem, or both.
|
|
Dalvik bytecode is stored in the `classes.dex`, `classes2.dex`, `classes3.dex`, ... while native code is stored in `lib/<arch>/*.so`.
|
|
The `res/` folder contains the ressources required for the user interface.
|
|
When ressources are present in `res/`, the file `resources.arsc` is also present at the root of the archive.
|
|
The `assets/` folder contains the files that are used directly by the code application.
|
|
Depending on the application and compilation process, any kind of other files and folders can be added to the application.
|
|
|
|
==== Signature
|
|
|
|
Android applications are cryptographically signed to prove the autorship.
|
|
Applicatations signed with same key are considered developed by the same entity.
|
|
This allow to securely update applications, and applications can declare security permission to restrict access to some feature to only application with the same author.
|
|
|
|
Android has several signature schemes coexisting:
|
|
- The v1 signature scheme is the #JAR signing scheme, where the signature data is stored in the `META-INF/` folder.
|
|
- The v2, v3 and v3.1 signature scheme are store in the '#APK Signing Block' of the #APK.
|
|
The v2 signature scheme was introduced in Android 7.0, and to keep retrocompatibility with older version, the v1 scheme is still used in addition to the #APK Signing Block.
|
|
The Signing block is an unindexed binary section added to the #ZIP file, between the #ZIP entries and the Central Directory.
|
|
The signature was added in an unindexed section of the #ZIP to avoid interferring with the v1 signature scheme that sign the files inside the archive, and not the archive itself.
|
|
- The v4 signature scheme is complementary to the v2/v3 signature scheme.
|
|
Signature data are stored in an external, `.apk.idsig` file.
|
|
|
|
==== Android Manifest
|
|
|
|
The Android Manifest is stored in the `AndroidManifest.xml`, encoded in the binary #AXML format.
|
|
The manifest declare important informations about the application:
|
|
- Generic informations like the application name, id, icon.
|
|
- The Android compatibility of the applications, in the form of 3 values: the Android `min-sdk`, `target-sdk` and `max-sdk`. Those are the minimum, targeted and maximum version of the Android SDK supported by the application.
|
|
- The application componants (Activity, Service, Receiver and Provider) of the application and their associated classes.
|
|
- Intent filters to list the intents that can start or be sent to the application componants.
|
|
- Security permissions required by the application.
|
|
|
|
==== Code <sec:bg-android-code-format>
|
|
|
|
An application usually contains at least a `classes.dex` file containing Dalvik bytecode.
|
|
This is the format executed by the Android #ART.
|
|
It is common for an application to have more thant one #DEX file, when application need to reference more methods than the format allows in one file
|
|
(each method referenced inside a #DEX is associated to a 16 bits number, limiting their number to #num(65536)).
|
|
Support for multiple #DEX files was added in the #SDK 21 version of Android, and applications that have multiple #DEX file are sometimes refered to as 'multi-dex'.
|
|
|
|
In addition to #DEX files, and sometimes instead of #DEX files, applications can contain `.so` ELF (Executable and Linkable Format) files in the `lib/` folder.
|
|
In the Android ecosystem, binary code is called native code.
|
|
Because native code is compiled for a specific architecture, `.so` files are present in different versions, stored in different subfolders, depending on the targetted architecture.
|
|
For example `lib/arm64-v8a/libexample.so` is the version of the `example` library compiled for an ARM 64 architecture.
|
|
Because smartphones mostly use ARM processors, it is not rare to see applications that only have the ARM version of their native code.
|
|
|
|
==== Ressources
|
|
|
|
Application user interface require many kind of specific assets, which are stored in `lib/`.
|
|
Those ressources include bitmap images, text, layout, etc.
|
|
Data like layout, color or text are stored in binary #AXML.
|
|
An additionnal file, `resources.arsc`, in a custom binary format, contains a list of the ressources names, ids, and their properties.
|
|
|
|
==== Compilation Process
|
|
|
|
For the developer, the compilation process is handled by Android Studio and is mostly transparent.
|
|
Behind the scene, Android Studio rely on Gradle to orchestrate the different compilation steps:
|
|
|
|
The sources #XML files like `AndroidManifest.xml` and the one in `res/` are compile to binary #AXML by `aapt`, which also generate the ressource table `resources.arsc` and a `R.java` file that define for each ressources variable named after the variable, set to the id of the ressouce.
|
|
The `R.java` file allows the developer to refere to ressources with readable names and avoid using the often automatically generated ressources ids, that can change from a version of the application to another.
|
|
|
|
The source code is then compile.
|
|
The most common programming langages used for Android application are Java and Kotlin.
|
|
Both are first compiled to java bytecode in `.class` files using the langage compiler.
|
|
To allow access to the Android #API, the `.class` are linked during the compilation to an `android.jar` file that contains classes with the same signatures as the one in the Android #API for the targeted SDK.
|
|
The `.class` files are then converted into the #DEX format using `d8`.
|
|
During those steeps, both the original langage compiler and `d8` can perform optimizations on the classes, like code shrinking, inlining, etc.
|
|
|
|
If the application contains native code, the original C or C++ code is compile using tools Android from the #NDK to target the different possible architectures.
|
|
|
|
`aapt` is then used once again to package all the generated #AXML, #DEX, `.so` files, as well as the other ressources files, assets, `resources.arsc`, and any additionnal files deemed necessary to form the final #ZIP file.
|
|
`aapt` ensures that the generated #ZIP is compatible with the requirement from Android.
|
|
For instance, the `resources.arsc` will be mapped directly in memory at runtime, so it must not be compressed inside the #ZIP file.
|
|
|
|
If necessary, the #ZIP file is then aligned using `zipalign`.
|
|
Again, this is to ensure compatibility with android optimizations: some files like `resources.arsc` need to be 4 bits alligned to be mapped in memory.
|
|
|
|
The last step is to sign the application using the `apksigner` utility.
|
|
|
|
Since 2021, Google requires that new applications in the Google Play app store to be uploaded in a new format called Android App Bundles.
|
|
The main difference is that Google will perform the last packaging steps and generate (and sign) the application itself.
|
|
This allow Google to generate different applications for different target, and avoid including unnecessary files in the application like native code targetting the wrong architecture.
|
|
|
|
=== Android Runtime <sec:bg-art>
|
|
|
|
Android runtime environement has many specificities that sets it appart from other platforms.
|
|
An heavy emphasis is put on isolating the applications from one another as well from the systems critical capabilities.
|
|
The code execution itself can be confusing at first.
|
|
Instead of the usual linear model with a single entry point, applications have many entrypoints that are called by the Android framework in accordance to external events.
|
|
|
|
==== Application Architecture
|
|
|
|
#todo[Subsection name?]
|
|
|
|
Android application expose their componants to the Android Runtime (#ART) via classes inheriting specific classes from the Android #SDK.
|
|
Four classes represent application components that can be used as entry points:
|
|
|
|
/ Activities: An activity represent a single screen with a user interface. This is the component used to interact with a user.
|
|
/ Services: A service serves as en entrypoint to run the application in the background.
|
|
/ Broadcast receivers: A broadcast receiver is an entry point used when a matching event is broadcasted by the system.
|
|
/ Content providers: A content provider is a component that manage data accessible by other app through the content provider.
|
|
|
|
Components must be listed in the `AndroidManifest.xml` of the application so that the system knows of them.
|
|
In the live cicle of a component, the system will call specific methods defined by the classes associated to each componant type.
|
|
Those methods are to be overridden by the classes defined in the application if they are specific action to be perfomed.
|
|
For instance, an activity might compute some values in `onCreate()`, called when the activity is created, save the value of those variable to the file system in `onStop()`, called when the acitivity stop being visible to the user, and recover the saved values in `onRestart()`, called when the user navigate back to the activity.
|
|
|
|
In addition to the componants declared in the manifest that act as entry points, the Android #API heavily relies on callbacks.
|
|
The most obvious cases are for the user interface, for example a button will call a callback method defined by the application when clicked.
|
|
Other part of the #API also rely on non-linear execution, for example when an application sends an intent (see @sec:bg-sandbox), the intent sent in responce is transmitted back to the application by calling another method.
|
|
|
|
==== Application Isolation and Interprocess Communication <sec:bg-sandbox>
|
|
|
|
On Android, each application has its own storage folders and the application process are isolated from other applications and the hardware interfaces.
|
|
This sandboxing is done using Linux security features like group and user permissions, SELinux, and seccomp.
|
|
The sandboxing is adjusted according to the permissions requested in the `AndroidManifest.xml` file of the applications.
|
|
In addition, most feature of the Android system can only be accessed through Binder, Android main interprocess communication channel.
|
|
|
|
Binder is a componant of tha Android framework, external to the application, that all applications can communicate with.
|
|
Applicatians can send messages to Binder, called *intent*, that will check if the application is allowed to send it then foward it to the appropriate componant that can then responce with another intent.
|
|
Applications can also receive intent must declare intent filters to indicate which intent can be send to the application, and which classes receive the intents.
|
|
Intent are central to Android applications and are not used just to access Android capabilities.
|
|
For instance, the activities and services are started by receiving intent, and it is not uncommon for application to send intents to itself to switch activities.
|
|
Intent can also be sent directly from Android to the application: when a user starts an application by tapping the app icons, Android will send an intent to the class of the application that defined the intent filter for the `android.intent.action.MAIN` intent.
|
|
One interesting feature of the Binder is that intent do not need to explicitly name the targetted application and class: intent can be implicit and request an action without knowing the exact application that will performed it.
|
|
An example of this behavior is when an application whant open a file: an `android.intent.action.VIEW` intent is sent with the file location, and Binder will find an application capable of viewing the file.
|
|
|