142 lines
12 KiB
Typst
142 lines
12 KiB
Typst
#import "../lib.typ": todo, APK, JAR, AXML, ART, SDK, JNI, NDK, DEX, XML
|
|
|
|
== 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 patches 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.
|
|
|
|
=== 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 is a ZIP archive containing 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.
|
|
Other files are then added.
|
|
Dalvik bytecode is stored in the `classes.dex`, `classes2.dex`, `classes3.dex`, ... and 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 develloped by the same entity.
|
|
This allow to securelly update applications, and application 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 introduce 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 the classes they are associated to
|
|
- Intent filters to list the itents that can start or be sent to the application componants
|
|
- Security permissions required by the application
|
|
|
|
==== Code
|
|
|
|
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.
|
|
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 echosystem, binary code is called native code.
|
|
Because native code is compile 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 the converted to #DEX files using `d8`.
|
|
During those steeps, both the original langage compiler and `d8` can perform optimizations on the classes.
|
|
|
|
If the application contains native code, the original C or C++ code is compile using tools Android #NDK to target the different architecture target.
|
|
|
|
`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 in 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: 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 require 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 heavy empasis 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.
|
|
They are four type of application commponents, that serves as entry points for application.
|
|
Each has a class associated to it, and serves a different role.
|
|
|
|
/ Activities: An activity represent a single screen with a user interface. This is the componant 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. They allow to application responce to event event when not started.
|
|
/ Content providers: A content provider is a componant that manage data accessible by other app through the content provider.
|
|
|
|
Componant must be listed in the `AndroidManifest.xml` of the application so that the system nows of them.
|
|
In the course of a componant live cicle, the system will call specifics methods defined by the classes associated to each componant type.
|
|
Those methods are to be overrident by the classes defined in the application if they are specific action to be perfomed.
|
|
For instance, an activitymight 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 send an itent (see @sec:bg-sandbox), the intent sent in responce is transmitted to 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.
|
|
|