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

Related