Skip to content

Accessing Android system APIs

by Diego Rondini, Roberto Sartori and Marta Todeschini

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 (more about it at: https://www.kynetics.com/docs/2018/introduction-to-dm-verity-on-android/).

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 https://github.com/boundarydevices/android_device_fsl/tree/boundary-imx-o8.0.0_1.0.0-ga/common/security.

We need, in particular, the files:

  • platform.pk8
  • platform.x509.pem

There are two ways to sign the application with the platform keys:

  1. signing manually with an external application
  2. signing during the build using gradle / Android Studio

Signing manually

To manually sign the apk the signapk.jar tool is required. The tool can be found in the Android OS buildsystem folder:

out/host/linux-x86/framework/signapk.jar

Once all of the required components are sourced, the application can be signed with the following command:

java -jar signapk.jar <path-to>/platform.x509.pem <path-to>/platform.pk8 <path-to>/<application>.apk <path-to>/<application>_platform-signed.apk

The resulting, signed apk can be installed in the system with adb:

adb install <path-to>/<application>_platform-signed.apk

Please be aware that recent versions of the signapk.jar tool require the libconscrypt_openjdk_jni.so external library. If needed it can be found in the out/host/linux-x86/lib64/libconscrypt_openjdk_jni.so folder of the Android OS buildsystem. Put it in the same folder of signapk.jar and add the -Djava.library.path="." parameter to the java command.

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
        }
    }

where you specify that in the signing configuration of debug you will use the private key with alias 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.