Dean Wild
Dean Wild

Reputation: 5964

Presigned APK loses signature in AOSP build

I am including a presigned APK in my AOSP build like so:

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)
APK_VERSION := 0.2.0
LOCAL_MODULE := SomeAPK
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := .apk
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PREBUILT)

However, when the device boots the APK is not installed and I see the following log:

2021-05-25 17:19:02.617 3568-3568/system_process W/PackageManager: Failed to scan /system/priv-app/SomeAPK: Failed to collect certificates from /system/priv-app/SomeAPK/SomeAPK.apk

I have tried setting:

LOCAL_DEX_PREOPT := false

and:

LOCAL_DEX_PREOPT := nostripping

But i'm still seeing the issue.

I can adb install the app fine and I have used all of the tools available to confirm the APK is actually signed.

How can we get AOSP to truly leave the APK signing alone?

Upvotes: 2

Views: 3401

Answers (4)

Nithesh Bafna
Nithesh Bafna

Reputation: 23

I was able to solve this in android.bp file as below.

// Import the APK
android_app_import {
    name: "MyApk",
    apk: "MyApk.apk",
    presigned: true,
    dex_preopt: {
    enabled: false,
  },
}

Upvotes: 2

Ronaldo Nunez
Ronaldo Nunez

Reputation: 53

Android team implemented another solution for this issue with the commit b34f64f of platform/build: https://cs.android.com/android/_/android/platform/build/+/b34f64fc7a017ebadd5fb2b1c81341491e4de9a1

In summary, for V2 (or higher) pre-signed APKs, you can define LOCAL_SDK_VERSION to 30 or higher to not alter the APK during its integration. In your case, it would be like (considering your APK was built with SDK version 30):

include $(CLEAR_VARS)
APK_VERSION := 0.2.0
LOCAL_MODULE := SomeAPK
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := .apk
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SDK_VERSION := 30
include $(BUILD_PREBUILT)

Upvotes: 3

Yong
Yong

Reputation: 2008

When prebuilt apk, it will try to uncompress the dex and jni so, if it's stored in apk(zip) with compress. It's checked by zipinfo. Then it will unzip the compress dex/jni so, and zip it again without uncompress. And the v2/v3 signature will be removed by unzip and zip again. v1 signature is stored as zip entry, and it will be keeped.

no compression

-rw-rw-rw- 0.0 unx 3598524 b- stor 81-Jan-01 01:01 classes.dex

You can avoid prebuilt apk to be processed by LOCAL_REPLACE_PREBUILT_APK_INSTALLED

include $(CLEAR_VARS)
APK_VERSION := 0.2.0
LOCAL_MODULE := SomeAPK
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := .apk
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/$(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)

Upvotes: 5

Dean Wild
Dean Wild

Reputation: 5964

I eventually found a solution.

Apps that were signed using gradle always seemed to be left with their signature stripped after the AOSP build process.

The solution was to remove the signing config from gradle altogether and sign the app manually instead using apksigner.

E.g:

apksigner sign --ks your-keystore.jks --ks-pass pass:"keystore-password" --ks-key-alias keystore-alias --key-pass pass:"alias-password" --out signed-output.apk input-file.apk

To verify if your APK is signed correctly, it should validate successfully using keytool:

keytool -printcert -jarfile signed-apk.apk

Upvotes: 2

Related Questions