Accessing Android system APIs¶
Introduction¶
A basic Android application has no permissions associated with it by default, meaning it cannot do anything that would adversely impact the user experience or any data on the device. To make use of protected features of the device, you must declare the permissions that your application needs.
However, looking at the list of permissions we notice that some permissions are marked as Not for use by third-party applications. This means that those permissions can only be requested by a "system application". An example is the SET_TIME permission, needed to set the system clock time.
To be a "system application", thus have access to the protected system permissions, an application needs to be one of the following:
- embedded in the system image of the Android OS
- signed with the platform keys
Embedding in the system image¶
To embed the application in the system image of the Android OS image to be flashed on the device, configure your build system in order for the <application>.apk
to be copied in the folder system/priv-app
.
Please keep in mind, the system image cannot be modified after the build if dm-verity is enabled.
Signing with the platform keys¶
The application can be installed after the Android OS image has already been built by signing the application with the platform key. The availability of the platform key, part of the keys used to sign the Android OS images, is a hard requirement for the procedure.
In the case where images are built using NXP's Android BSP, the keys are found under device/fsl/common/security/
and are available for example in the NXP Android BSP repositories.
We need, in particular, the files:
platform.pk8
platform.x509.pem
There are two ways to sign the application with the platform keys:
- signing manually with an external application
- signing during the build using gradle / Android Studio
Signing manually¶
To manually sign the apk the apksigner
utility is required. apksigner
is part of the Android SDK Build tools.
Note
Make sure you have:
- installed the Android SDK with the latest version of the Build tools
- configured the
ANDROID_HOME
variable, as specified in the SDK Tools Environment variables documentation
Once you have all the required tools and files, run the following command to sign the apk (adapt paths and file names as needed):
$ANDROID_HOME/build-tools/<build-tools-version>/apksigner sign --key platform.pk8 --cert platform.x509.pem --in <application>.apk --out <application>_platform-signed.apk
The resulting signed apk can be installed in the system with adb:
adb install <application>_platform-signed.apk
Signing during the build¶
Another option is to configure the build.gradle
of your Android application to directly generate an APK signed as a "system application" and install it on your device. This is particularly useful while developing as it allows to test system APIs and debug applications without additional intermediate steps.
What you need is a keystore containing the private key to be used to sign the APK.
So first you import the platform.pk8
and the platform.x509.pem
in a new keystore. With the following commands:
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out platform.priv.pem -nocrypt
openssl pkcs12 -export -in platform.x509.pem -inkey platform.priv.pem -out platform.pk12 -name MyAndroidKey
you convert the format of platform.pk8
key into platform.priv.pem
and then export the platform.x509.pem
certificate and the platform.priv.pem
key into the platform.pk12
with alias MyAndroidKey
.
Then you import the newly created key in the keystore with:
keytool -importkeystore -destkeystore MyKeystore.jks -srckeystore platform.pk12 -srcstoretype PKCS12 -srcstorepass MyKeystorePassword -alias MyAndroidKey
This command will automatically create a new keystore.
Afterwards you add this new section into the build.gradle
:
signingConfigs {
debug {
keyAlias 'MyAndroidKey'
keyPassword 'MyKeyPassword'
storeFile file('MyKeystore.jks')
storePassword 'MyKeystorePassword'
v2SigningEnabled true
v1SigningEnabled true
}
}
MyAndroidKey
.
Then you have to check if in the section:
buildTypes {
debug {
signingConfig signingConfigs.debug
}
}
of the build.gradle
there is a sub-section named debug
which calls the signingConfigs.debug
routine during the signing configuration phase (otherwise, add it and sync again your build.gradle
).
Now all you have to do is click on the "Run" button of Android Studio and it will generate the APK signed as "system application" and install it on your device.