How does nRF Connect for Android receive BLE advertisements while the phone is in MIUI Deep Doze?

I'm developing a custom BLE sensor on an nRF52832 (E73-2G4M04S1B module, SoftDevice S132
7.2.0) with a companion Android app. On Xiaomi/HyperOS devices (confirmed on this exact
phone), when the phone enters real Deep Doze (confirmed via
`adb shell dumpsys deviceidle force-idle` / `get deep` -> IDLE), MIUI's own ScanManager
unconditionally refuses to start any BLE scan from a non-system app:

```
W/ScanManager: is Deep Doze, non-system software won't start scan!
```

This fires for every scan attempt from my own app - live `ScanCallback`, `PendingIntent`-based
delivery, a `foregroundServiceType="connectedDevice"` (and `connectedDevice|location`) service,
regardless of permissions held.

However, **nRF Connect for Android** (installed from Google Play on the same phone) keeps
receiving advertisements and updating its device list throughout confirmed Deep Doze - verified
directly via `dumpsys bluetooth_manager` showing 0ms suspended time and hundreds of delivered
scan results during a ~45s Deep Doze window, while my own app's scanner got 0 results in the
same window.

I've spent a long debugging session trying to find what's different, and ruled out everything
I could test:
- Matched `ACCESS_FINE_LOCATION`/`ACCESS_BACKGROUND_LOCATION` grants - no effect.
- Matched `foregroundServiceType="connectedDevice|location"` - no effect (and decompiling your
  APK shows the actual persistently-running `BluetoothLeService` only declares
  `connectedDevice`, not `location`, so this wasn't the mechanism anyway).
- Matched `BLUETOOTH_SCAN` **without** `neverForLocation` (as your manifest has it) - no effect.
- Reinstalled my app with `installerPackageName` spoofed to `com.android.vending` - no effect.
- Matched `targetSdkVersion` to 35 - no effect.
- Checked the signing certificate - it's just your normal Nordic Semiconductor ASA company
  certificate, nothing unusual.

So from what I can tell, nothing in the APK itself or in any manifest/permission declaration
explains it. That leaves either something OS/certificate-level that MIUI special-cases outside
the app (publisher allowlist, Play Protect reputation, etc.), or something I haven't thought to
check.

Since I'm building on your own chip, I'd really appreciate it if someone on the Android app
team could share whether there's a known technique here - even just confirming "we don't do
anything special, it's purely external to the app" would save me from chasing this further.

Device: Xiaomi running HyperOS (MIUI), nRF Connect version 4.29.1.

Thanks!

  • Do you start your bluetooth calls from a normal Activity or from a Foreground Service? The latter should allow running bluetooth scan and connections in sleeping states.

  • Thanks for the quick reply!

    Yes - I'm already calling `startScan()` from a Foreground Service, not from an Activity. To be
    precise about what I've tested:

    - My production app's scanning service is a `Service` declared with
      `android:foregroundServiceType="connectedDevice"`, started via `startForegroundService()` and
      calling `ServiceCompat.startForeground()` before any scan call - never scanning from an
      Activity directly.
    - I also tried `foregroundServiceType="connectedDevice|location"` (plus the matching
      `FOREGROUND_SERVICE_LOCATION` permission and `ACCESS_FINE_LOCATION`/`ACCESS_BACKGROUND_LOCATION`
      grants) in case the service *type* specifically mattered - no change in behavior.

    Both were confirmed with the same reproducible test: force the phone into real Deep Doze with
    `adb shell dumpsys deviceidle force-idle` (confirmed via `dumpsys deviceidle get deep` -> `IDLE`),
    then watch `adb logcat` live. The block fires immediately on every `startScan()` call from the
    foreground service, regardless of type:

    ```
    W/ScanManager: is Deep Doze, non-system software won't start scan!
    ```

    What made me rule out "foreground service vs. Activity" as the explanation specifically: nRF
    Connect itself (installed from Play Store on the same phone) keeps its own "Service is running"
    foreground notification up the whole time, so it's clearly scanning from a foreground service
    too - not from an Activity. Yet in the same forced Deep Doze state, `dumpsys bluetooth_manager`
    shows nRF Connect's scanner at 0ms suspended time with hundreds of delivered results over ~45s,
    while mine gets suspended immediately with zero results - even though both are, by all
    appearances, "the same kind" of foreground-service-based scan by Android's own classification.

    So on this specific MIUI/HyperOS build, the standard Android foreground-service Doze exemption
    doesn't seem to be what's actually deciding it - MIUI's own `ScanManager` layer is adding a
    separate check on top that singles my app out despite the service being a correctly-configured,
    connectedDevice-type foreground service.

  • Hi Pavel, 

    I see you've allready gotten some input here. I'll ask someone working with the app for some input on this shortly.

    Regards,

    Elfving

  • Hi again,

    I heard from the app team that they do not really do anything in particular to get it scanning in deep sleep. They weren't even aware of the application being able to do this, to be honest. So there is something on the phone side that allows this, that is beyond us.

    Regards,

    Elfving

Related