4

I'm working on a custom AOSP 8.1 based OS. I have a system app (in /system/priv-app) with an exported broadcast receiver. This means it can accept Intents from outside the application. If I refactor the broadcast receiver, e.g. change its package location or class name and install the updated APK with "adb install -r ...", everything works great and the broadcast receiver receives the intent.

However if I produce an OTP image with the new app (APK + VDEX + ODEX) and flash it from the recovery, the app crashes as Android is still trying to reference the old broadcast receiver class:

AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.example.app.receiver.ExampleReceiver: java.lang.ClassNotFoundException: Didn't find class "com.example.app.receiver.ExampleReceiver" on path: DexPathList[[zip file "/system/priv-app/ExampleApp/ExampleApp.apk"],nativeLibraryDirectories=[/system/priv-app/ExampleApp/lib/arm, /system/lib, /vendor/lib, /system/lib, /vendor/lib]]

It tries to reference com.example.app.receiver.ExampleReceiver, but the new class is com.example.app.receiver.NewReceiver. The old one is "cached" somewhere.

I can simulate the same problem by remounting the /system partition RW and using adb push ... to replace the new APK, ODEX and VDEX files. Strange enough if I delete the ODEX and VDEX files from /system, everything works great as apparently this act forces Android to parse again the APK.

As I understand the PackageManager system app should be able to detect when an app is updated and parse the exported parts (like classes for broadcast receivers and activities). Unfortunately this doesn't happen.

I also guess that's what happens after OTA when Android shows "Optimizing app xxx/xxx", but this doesn't happen here. How is this process supposed to be triggered?

Relevant information: http://www.programmersought.com/article/8031444654/

georgiptr
  • 111
  • 9

1 Answers1

0

Android sourcecode for PackageManagerService has following lines:

mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
... some other code

if (mIsUpgrade && !onlyCore) {
                Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                ... cache clearing logic
                ver.fingerprint = Build.FINGERPRINT;
}

That is, code caches will be cleared if build fingerprint is changed. This problem might occur because your OTA package has same fingerprint as the system it is installed on.

Check your makefile and make sure you are generating a unique fingerprint for each build.

Fingerprint value can be found in "system/buildprops" file. So you can check if that is the problem.

t.m.
  • 1,430
  • 16
  • 29
  • Thank you very much. I no longer work on the same product, but my colleagues just informed me that your answer solved the problem. Cheers! – georgiptr May 13 '21 at 07:46