Skip to content

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

At a glance

Topic: Android system API access · Methods: System image embedding, platform key signing · Tools: apksigner, Gradle

Two approaches let apps access protected Android system APIs: embedding in the system image under system/priv-app, or signing the APK with the platform keys. This article covers both methods with practical examples.

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:

  1. signing manually with an external application
  2. 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:

  1. installed the Android SDK with the latest version of the Build tools
  2. 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
        }
    }
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.

Frequently Asked Questions

What is a system application in Android?

A system application is an app that resides in the device's read-only system partition (/system/app or /system/priv-app). System apps can be granted permissions that are unavailable to regular third-party applications, such as SET_TIME or INSTALL_PACKAGES.

Why can't third-party apps request system permissions?

Android's permission model deliberately prevents untrusted apps from accessing sensitive system APIs. Permissions marked Not for use by third-party applications are enforced at both the package manager and framework level; they will be silently ignored or cause a SecurityException at runtime if requested by a non-system app.

How do I sign an APK with platform keys?

Use the apksigner utility (part of the Android SDK Build Tools) with the platform.pk8 private key and platform.x509.pem certificate provided by your BSP vendor. Alternatively, import the keys into a JKS keystore and configure Gradle to sign automatically on every build, as described in the Signing during the build section above.

What is the difference between embedding in system/app vs system/priv-app?

Apps placed under system/priv-app are considered privileged and may be granted a broader set of permissions (those declared with protectionLevel="privileged"). Apps under system/app are regular system apps and cannot obtain privileged permissions. For most use cases requiring restricted system APIs, system/priv-app is the correct location.

Does dm-verity prevent adding apps to the system partition after build?

Yes. When dm-verity is enabled, the system partition is verified against a hash tree at boot time. Any modification to the partition — including adding or replacing APKs — will cause the device to fail verification and refuse to boot. To add a system app after the build you must either disable dm-verity or sign the APK with the platform key and install it as a system app through an OTA update.