Skip to content

Vending: Fix repeated EMUI install dialog and implement splitDeferred - #3543

Open
grenadin wants to merge 8 commits into
microg:masterfrom
grenadin:fix/emui-install-dist-dialog-user-action-required
Open

grenadin wants to merge 8 commits into
microg:masterfrom
grenadin:fix/emui-install-dist-dialog-user-action-required

Conversation

@grenadin

@grenadin grenadin commented Jun 8, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #3541

When an app installed through microG requests dynamic feature modules, microG asks for an install confirmation again and again. splitDeferred() was a no-op stub, so apps such as Facebook never got an answer and fell back to startInstall() for the same modules. Every request created a new PackageInstaller session that needed a confirmation: InstallDistActivity on Huawei EMUI, PackageInstallerActivity on stock Android.

As a side benefit, the same change removes the confirmation on stock Android 12+ for apps updated through the installer proxy (#3074), for example Aurora Store's "Update all" with the microG installer.

Changes

  • SplitInstallService.kt: implement splitDeferred() through the same splitInstallFlow() as startInstall(), and always call onDeferredInstall() afterwards so the caller is not left waiting.
  • Install.kt: set USER_ACTION_NOT_REQUIRED on the session for SDK_INT >= 31.
  • AndroidManifest.xml: request UPDATE_PACKAGES_WITHOUT_USER_ACTION (normal permission, API 31+). Without it, Android ignores USER_ACTION_NOT_REQUIRED (PackageInstallerSession.computeUserActionRequirement).
  • With both, Android 12+ skips the confirmation when microG is the installer of record (update owner on Android 14+) and the app meets the platform's target SDK requirement. Otherwise it still asks, as before. Huawei EMUI adds its own check, see Testing.

Security considerations

  • Updates through the installer proxy no longer show the system confirmation. The caller still has to be allowed in microG's installer settings (package name and signing certificate), so that is now the only prompt for updates. Apps installed by Google Play before switching to microG also have com.android.vending as installer of record, so they are covered too.
  • Android still enforces the usual rules: only updates of apps where microG is the installer of record, same signing certificate, no downgrade. New installs and runtime permissions still need the user.
  • Split installs only accept the calling app's own package (getAndCheckCallingPackage) and download the splits from Play.
  • Aurora Store's session installer uses the same flag and permission.

Testing

Dynamic feature modules (Huawei MatePad Mini, EMUI 12, fa111c0)

Huawei MatePad Mini (EMUI 15.0.0, Android 12), debug build of d0999c6, an update through the installer proxy (called the same way as Aurora)

  • Android's own check passes, but EMUI then asks its SilentUpdatePolicy, an allowlist of installer packages that Huawei's PackageInstaller fetches from Huawei's server. It returns allowed: false for com.android.vending, so InstallDistActivity is still shown once per install. This cannot be changed from microG.
Huawei log
01:50:34.781 V/GmsPackageInstaller: installPackages start org.microg.test.silentupdate.target
01:50:34.860 D/GmsPackageInstaller: installPackages session commit
01:50:34.869 D/SilentUpdatePolicy: installer: com.android.vending/10200, target: org.microg.test.silentupdate.target/10263, allowed: false
01:50:34.875 D/GmsPackageInstaller: onReceive status: -1 sessionId: 786341343
01:50:35.334 I/ActivityTaskManager: Displayed com.huawei.appmarket/com.huawei.appgallery.systeminstalldistservice.riskcheck.ui.activity.InstallDistActivity: +129ms
01:50:41.074 D/GmsPackageInstaller: onReceive status: 0 sessionId: 786341343

Side benefit: Android 12 emulator (AOSP image), Aurora Store 4.8.4 with the microG installer, "Update all" (2 apps, microG as installer of record)

  • Without the permission (bb9a37d): PackageInstallerActivity for both apps; they installed only after confirming.
  • With the permission (d0999c6): no confirmation, both apps updated, Aurora's task stayed at 4 activities.
Emulator logs

Without the permission (bb9a37d):

23:41:45.150 V/GmsPackageInstaller: installPackages start com.androidfung.drminfo
23:41:45.543 D/GmsPackageInstaller: installPackages session commit
23:41:45.713 I/ActivityTaskManager: START u0 {act=android.content.pm.action.CONFIRM_INSTALL ... cmp=com.android.packageinstaller/.PackageInstallerActivity (has extras)}
23:41:54.600 D/AppInstall: handleInstallRequest: installPackages<com.androidfung.drminfo> isSuccess: true
23:41:55.626 V/GmsPackageInstaller: installPackages start com.ytheekshana.deviceinfo
23:41:55.769 D/GmsPackageInstaller: installPackages session commit
23:41:55.833 I/ActivityTaskManager: START u0 {act=android.content.pm.action.CONFIRM_INSTALL ... cmp=com.android.packageinstaller/.PackageInstallerActivity (has extras)}
23:42:00.062 D/AppInstall: handleInstallRequest: installPackages<com.ytheekshana.deviceinfo> isSuccess: true

With the permission (d0999c6):

23:50:27.541 V/GmsPackageInstaller: installPackages start com.androidfung.drminfo
23:50:28.111 D/GmsPackageInstaller: installPackages session commit
23:50:29.519 V/GmsPackageInstaller: installPackages start com.ytheekshana.deviceinfo
23:50:30.144 D/GmsPackageInstaller: installPackages session commit
23:50:30.608 D/AppInstall: handleInstallRequest: installPackages<com.androidfung.drminfo> isSuccess: true
23:50:32.260 D/AppInstall: handleInstallRequest: installPackages<com.ytheekshana.deviceinfo> isSuccess: true

Before this PR: Aurora "Update all" (0.3.17 release, Huawei Mate X6, EMUI 15, Android 12, Aurora Store 4.8.3 / 4.8.4 with the microG installer)

  • InstallDistActivity for every app. While the dialogs waited, Aurora's task grew to 65 activities (MicroGInstallerActivity and AppInstallActivity), and Aurora could not be scrolled.
  • Requests that were overtaken never finished: 4 of 16 in one run.
  • These unconfirmed sessions are never abandoned. After a few days, the Companion had 50 committed but unfinished sessions, the per-installer limit, and every install through microG failed with Too many active sessions.
Logs
mCurrentFocus=Window{... com.huawei.appmarket/com.huawei.appgallery.systeminstalldistservice.riskcheck.ui.activity.InstallDistActivity}
Task{... #7736 type=standard A=11439:com.aurora.store ... translucent=true sz=65}
  * Hist #64: ActivityRecord{... com.android.vending/org.microg.vending.installer.AppInstallActivity t7736}
  * Hist #63: ActivityRecord{... com.aurora.store/.data.activity.MicroGInstallerActivity t7736}
  ...
W/GmsPackageInstaller: installPackagesInternal pendingSessions size: 45

Later, installing YouTube through the microG installer (50 sessions of com.android.vending listed under "Active install sessions" in dumpsys package):

W/GmsPackageInstaller: Error installing packages
W/GmsPackageInstaller: java.lang.IllegalStateException: Too many active sessions for UID 11376
    at com.android.server.pm.PackageInstallerService.checkSessionQuotaLocked(PackageInstallerService.java:1620)
    at com.android.server.pm.PackageInstallerService.createSession(PackageInstallerService.java:619)
D/AppInstall: handleInstallRequest: installPackages<com.google.android.youtube> isSuccess: false

Requests received by AppInstallActivity vs. completion (Aurora 4.8.4, app names replaced):

23:19:01.825  app20.example        finished 23:19:06.049
23:19:05.943  app21.example        NEVER FINISHED
23:19:09.161  app22.example        finished 23:19:11.589
23:19:13.055  app23.example        finished 23:19:15.413
23:19:25.211  app24.example        NEVER FINISHED
23:19:35.481  app25.example        finished 23:19:46.111
23:19:59.303  app26.example        finished 23:20:03.948
23:20:00.205  app27.example        NEVER FINISHED
23:20:06.202  app28.example        finished 23:20:16.513
23:20:12.314  app29.example        NEVER FINISHED

Full logs (filtered, app package names replaced):
aurora-4.8.3-microg-installer.log
aurora-4.8.4-microg-installer.log

// Without this flag, EMUI intercepts each PackageInstaller session and shows a
// mandatory user-confirmation dialog — including for Dynamic Feature Module installs.
// USER_ACTION_NOT_REQUIRED requires API 31 (Android 12 / S).
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use import android.os.Build.VERSION.SDK_INT and directly refer to SDK_INT (to not confuse with the Build from device profiles.

Also please use direct SDK level code (31) instead of named version codes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, updated in the latest commit.

- Add USER_ACTION_NOT_REQUIRED to SessionParams in installPackagesInternal()
  for API 31+ (Android 12+) to prevent Huawei EMUI InstallDistActivity from
  intercepting every PackageInstaller session commit with a confirmation dialog.

- Implement splitDeferred() in SplitInstallService to route deferred DFM
  install requests through splitInstallFlow() instead of being a no-op stub.
  Previously, apps like Facebook would fall back to startInstall() for each
  deferred module, triggering additional PackageInstaller sessions and
  additional InstallDistActivity dialogs on EMUI.

Fixes: microg#3541
@grenadin

grenadin commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor Author

@mar-v-in I've updated the SDK_INT import and switched to the direct API level (31) as requested. Ready for another look whenever you have time, please let me know if anything else needs changing.

@grenadin
grenadin requested a review from mar-v-in September 23, 2026 15:12
@mar-v-in mar-v-in added this to the 0.3.18 milestone Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants