Modern Way of Building Android App From Source in AOSP Environment

Written by rajatgupta1998 | Published 2023/04/28
Tech Story Tags: android | android-app-development | programming | guide | tutorial | coding | beginners-guide | coding-skills

TLDRThis will be my first post here, I will start with the first steps one usually does in AOSP; compile an Android App in AOSP Environment as a system application.via the TL;DR App

This will be my first post here, I will start with the first steps one usually does in AOSP; compile an Android App in AOSP Environment as a system application.

This topic is also vast, considering the large number of changes you can do with the same, the documents I share will keep evolving. For the scope of this document, I will not consider a prebuilt apk.

Goals

Compile an android app from source, in AOSP tree and include it as a part of the OS images, like a system app which lives in the directory like: /system/app/SampleSystemApp

Similar paths like a /system/priv-app or partitions like system_ext, product, odm, vendor can also be done in a similar manner. It very much depends on your requirement which partition you want to use, as long as you pass xTS - if required.


Environment:

OS - AOSP Android 13 - android-13.0.0_r37

Target Product: 64 bit only Emulator - sdk_phone64_x86_64-userdebug


Implementation:

1. Add the app source code to aosp tree.

Here let us assume we have a sample application by the name of SampleSystemApp. Most of the apps are mostly set up under $(SRC_ROOT_DIR)\packages\apps\ Let us assume it looks something like this:

packages
    apps
        SampleSystemApp

And here we have the regular android application source structure inside it, like we have for a normal app from Android Studio.

Make sure the AndroidManifest.xml has the package attribute defined in <manifest> tag or else aapt will fail the compilation.

2. Create an Android.bp file for the build system (soong).

References can be taken from any default AOSP app as well. Blueprint based Android.bp files will be familiar to developers who have used Bazel before.

Example Android.bp file for our app. This app is written in Kotlin, with compile and target sdk as 33, and min sdk as 28. It will have dependencies on certain libraries (the ones I used are already part of AOSP tree). If you want to use internal SystemAPIs then you can mention platform_apis: true and sign this app with platform certificate by using the certificate: "platform" entry in Android.bp

package {
    // See: http://go/android-license-faq
    default_applicable_licenses: ["Android-Apache-2.0"],
}

android_app {
    name: "SampleSystemApp",
    srcs: [
        "app/src/main/java/**/*.kt",
    ],
    resource_dirs: [
        "app/src/main/res",
    ],
    manifest: "app/src/main/AndroidManifest.xml",
    sdk_version: "33",
    min_sdk_version: "28",
    target_sdk_version: "33",
    static_libs: [
        "com.google.android.material_material",
        "androidx.core_core",
        "androidx.preference_preference",
        "androidx.lifecycle_lifecycle-extensions",
        "androidx-constraintlayout_constraintlayout"
    ]
}

To make it a privileged app system/priv-app add the attribute privileged: true.

For different partitions, you can consider different attributes like.

(a.) system_ext_specific (b.) product_specific (c.) device_specific (d.) soc_specific

More documentation on Soong modules and attributes can be referenced from Android CI - here.

3. Now include this module in the PRODUCT_PACKAGES.

After lunch, You can manually test the compilation via make name. Replace the name with the module name you defined in Android.bp. Here it will be SampleSystemApp.

To include it in the build you need to add it to PRODUCT_PACKAGES.

Since we are building emulator (goldfish) target, we should add it to a .mk file under the device/generic/goldfish directory. Here we will use emulator64_x86_64/device.mk:

PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
	system/app/SampleSystemApp/%

PRODUCT_PACKAGES += SampleSystemApp

The PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST flag is required for system and system_ext path from Android 11 (API 30) and higher - link. You don't need it if the module you are building is to be a part of odm, vendor or product partitions.

4. Verification - on build output and live emulator.

A. Verify it gets added to the system image via building the entire emulator image.

make -j$(nproc --all)

B. Check the following paths:

(a) - out/target/product/emulator64_x86_64/system/app/

(b) - out/target/product/emulator64_x86_64/installed-files.json

Here you should see the files / paths for your app.

C. Clean Boot your emulator with permissive SE Linux, printing verbose logs:

emulator -no-snapshot-load -selinux permissive

Wait for the emulator to boot to the home app, and check the app in the app drawer launcher screen.

Or programmatically via adb shell pm list packages where you will see your app package name.

D. Test your app and fix bugs if any.


Written by rajatgupta1998 | Android - AOSP - Linux - XR
Published by HackerNoon on 2023/04/28