A guide to application development within the Android Open Source Project (AOSP) and elevating standard apps to System Apps or Privileged Apps to access special APIs.

1. AOSP App vs Gradle App

App development on AOSP uses a different Build Platform (Soong/Make) compared to Android Studio (Gradle).

Key Differences

  1. Build System: Uses Android.bp (Soong) instead of build.gradle
  2. Location: Source Code resides in the Android Source Tree (e.g., packages/apps/MyApp)
  3. API Access: Direct access to Hidden APIs (@hide) and Internal Resources (com.android.internal.R)

1.5 The Battle: Android.bp vs Android.mk

FeatureAndroid.mk (Legacy)Android.bp (Modern)
EngineGNU MakeSoong (Blueprint)
LogicShell Script / If-else SupportDeclarative JSON-like (No Logic)
StatusDeprecatedRecommended (Standard)

Recommendation: Use Android.bp for all new modules unless complex Shell Scripts are required.


2. Basic AOSP App Structure

File structure example for the MySystemControl app:

Directory: packages/apps/MySystemControl/

  • AndroidManifest.xml
  • Android.bp (Build Config)
  • src/ (Java/Kotlin Code)
  • res/ (Resources)

Android.bp Example:

android_app {
    name: "MySystemControl",
    srcs: ["src/**/*.java"],
    resource_dirs: ["res"],
    static_libs: ["androidx.appcompat_appcompat"],
    
    // Key Configs
    platform_apis: true,          // Allow Hidden APIs
    certificate: "platform",      // Sign with System Key
}

Build Command:

source build/envsetup.sh
lunch aosp_arm64-userdebug
m MySystemControl

2.5 Bonus: Importing Prebuilt APK

If you want to include an APK from Android Studio into the ROM without moving the Source Code:

android_app_import {
    name: "PrebuiltMyApp",
    apk: "MyApp.apk",
    presigned: true, // Keep original signature
    // privileged: true, // Optional
}

Note: presigned: true cannot use Shared System UID.

2.6 Workflow: Debugging System Apps from Android Studio

The INSTALL_FAILED_UPDATE_INCOMPATIBLE issue arises from mismatched Signatures (Debug Key vs Platform Key).

Solution: Sign APK with Platform Key

  1. Get Key from build/target/product/security/ (platform.pk8, platform.x509.pem)
  2. Convert to KeyStore (.jks) using openssl and keytool
  3. Configure signingConfig in Android Studio’s build.gradle to use this Key.

3. System App vs Privileged App

Installation location determines the app’s privilege level.

3.1 System App (/system/app)

  • Definition: Pre-installed app in ROM
  • Capabilities: Cannot be uninstalled by user.
  • Setup: Include module in Product Makefile.

3.2 Privileged App (/system/priv-app)

  • Definition: System App with elevated permissions.
  • Capabilities: Access Signature/Privileged Permissions (e.g., REBOOT, SHUTDOWN, INSTALL_PACKAGES).
  • Setup: Add privileged: true in Android.bp.

4. How to Create a Privileged App

Steps to create a complete Privileged App:

  1. Android.bp: Add privileged: true and certificate: "platform"
  2. Manifest: Request desired Permission (e.g., <uses-permission android:name="android.permission.REBOOT" />)
  3. Allowlist XML (Mandatory): Create XML file in /system/etc/permissions/ to verify rights (Prevents Boot Loop in Android 8.0+)

XML Example:

<permissions>
    <privapp-permissions package="com.example.mysystemcontrol">
        <permission name="android.permission.REBOOT"/>
    </privapp-permissions>
</permissions>

5. The “God Mode”: Shared System UID

android:sharedUserId="android.uid.system"
  • Concept: Run app as System User (uid=1000), not a general User.
  • Requirements: Must be signed with Platform Key only.
  • Capabilities: Full Access to /data/system, Kill processes, Direct Hardware access.
  • Risk: App crash = System Crash.

Comparison Table

FeaturePrivileged AppShared System UID
IdentityNormal User IDSystem User ID (1000)
AccessVia Permissions (Reboot, etc.)Direct File/Process Access
LocationMust be in /system/priv-appAnywhere (if signed correctly)

6. Summary

TypeLocationUninstallable?Special API AccessConfiguration
User App/data/appYesNoGradle Standard
System App/system/appNoSomemk/bp include
Priv App/system/priv-appNoFullprivileged: true + Whitelist