Skip to content

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

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

grenadin wants to merge 2 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

Problem

On Huawei EMUI devices (Android 12+), two related issues in vending-app
cause InstallDistActivity (Huawei's install confirmation dialog) to appear
repeatedly during app installation via microG Companion installer proxy.

Issue 1 — Missing USER_ACTION_NOT_REQUIRED flag

installPackagesInternal() in Install.kt creates PackageInstaller.SessionParams
without setting USER_ACTION_NOT_REQUIRED. On EMUI, the system intercepts every
session commit and routes it through InstallDistActivity, showing a mandatory
confirmation dialog — including for background DFM installs.

Issue 2 — splitDeferred() was a no-op stub

SplitInstallService.splitDeferred() only logged a warning and ACKed immediately
without performing any actual installation. Apps such as Facebook request background
pre-installation of DFM splits (e.g. pytorch, papaya, executorch) via
splitDeferred(). Because nothing was installed, the app fell back to startInstall()
for the same modules — triggering additional PackageInstaller sessions and additional
InstallDistActivity dialogs per module.

Context

SplitInstallService and splitDeferred() were originally introduced in #2500
(Implement SplitInstallService). At that time splitDeferred() was left as a stub —
it only logged "not implemented" and never called back, which is the root cause of
Issue 2 above. This PR implements it by routing through the same splitInstallFlow()
already used by startInstall(), rather than introducing a new code path.

Fix

Install.kt — Add USER_ACTION_NOT_REQUIRED to SessionParams for API 31+:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    params.setRequireUserAction(SessionParams.USER_ACTION_NOT_REQUIRED)
}

SplitInstallService.kt — Route splitDeferred() through splitInstallFlow()
(same as startInstall()), then ACK with onDeferredInstall() after completion
instead of being a no-op.

Testing

Tested on Huawei MatePad Mini (EMUI 12, Android 12) with microG Companion
0.3.15.250932-hw built from this branch.

Test steps:

  1. Install Aurora Store → select microG as installer method
  2. Install Facebook (com.facebook.katana) and TikTok (com.tiktok)
  3. Open each app and allow DFM modules to load

Before fix (logcat evidence in #3541):

  • InstallDistActivity appeared as topActivity before every session commit
  • splitDeferred() called for com.facebook.katana, but is not implemented (repeated per module)
  • App fell back to startInstall() for same DFM modules → additional dialogs

After fix:

  • InstallDistActivity no longer appears as topActivity ✅
  • splitDeferred not implemented no longer logged ✅
  • Facebook and TikTok DFM modules install silently in background ✅

Notes

  • USER_ACTION_NOT_REQUIRED requires API 31 (Android 12+), guarded by
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
  • splitDeferred() ACKs with onDeferredInstall(Bundle()) regardless of
    install result so the calling app is never left waiting
  • This fix matches the behavior already implemented in Aurora Store's
    SessionInstaller.kt for its own session installer path
  • Related: PR #3074 (App Installer Proxy)
  • Builds on the SplitInstallService skeleton introduced in Implement SplitInstallService #2500

Full logcat after fix (Facebook + TikTok):
facebook_log_after_fix_redacted.txt

// 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.

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