-
Notifications
You must be signed in to change notification settings - Fork 4
Add Doze network-block repro test script, Fixes AB#3612535 #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rpdome
wants to merge
5
commits into
master
Choose a base branch
from
rapong/doze-repro-script
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
5e7fffe
Add Doze network-block repro test script
rpdome fc315ac
Fix Doze script cleanup and serial-scoped adb usage
Copilot 66f7568
Remove redundant explicit cleanup call in doze script
Copilot da21a41
Harden serial resolution and signal-based cleanup trap
Copilot adc6172
kill msaltestapp before launching the test
rpdome File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| #!/usr/bin/env bash | ||
| # doze-repro-test.sh — Reproduce Android Doze network block on Broker auth | ||
| # | ||
| # This script tests that the Android Broker (Authenticator/BrokerHost) fails | ||
| # with a DNS/network error when a background caller triggers silent auth | ||
| # during Doze mode. It uses the SilentAuthReceiver in MsalTestApp to invoke | ||
| # acquireTokenSilent from a BroadcastReceiver (PROCESS_STATE_RECEIVER), | ||
| # which does NOT elevate the Broker's process importance enough to get a | ||
| # dozable-allow firewall rule from NetworkPolicyManagerService. | ||
| # | ||
| # Root cause (validated via AOSP source + on-device netpolicy dump): | ||
| # When a foreground app binds to Broker via IPC, Android's | ||
| # NetworkPolicyManagerService dynamically adds a dozable-allow firewall | ||
| # rule for the Broker's UID. When the caller is in a background context | ||
| # (BroadcastReceiver handling FCM), the binding does NOT elevate the | ||
| # Broker enough — Doze firewall blocks its DNS resolution. | ||
| # | ||
| # Prerequisites (manual, one-time): | ||
| # 1. Install exactly ONE broker app (Authenticator, Company Portal, | ||
| # BrokerHost, or Link to Windows) | ||
| # 2. Install MsalTestApp (must have SilentAuthReceiver registered) | ||
| # 3. Sign in to an account in MsalTestApp via interactive auth | ||
| # 4. Connect device via USB with adb authorized | ||
| # | ||
| # Usage: | ||
| # bash scripts/doze-repro-test.sh | ||
| # | ||
| # Expected result: | ||
| # AUTH FAILED with either: | ||
| # - io_error: Doze firewall blocked Broker's DNS resolution | ||
| # - device_network_not_available_doze_mode: Broker's proactive Doze check | ||
| # TOKEN ACQUIRED if broker is battery-exempt (DeviceIdle whitelist) | ||
| # | ||
| set -euo pipefail | ||
|
|
||
| RECEIVER_PKG="com.msft.identity.client.sample.local" | ||
| RECEIVER_CLASS="com.microsoft.identity.client.testapp.SilentAuthReceiver" | ||
| RECEIVER_ACTION="com.microsoft.identity.client.testapp.SILENT_AUTH" | ||
| WAIT_SECONDS=15 | ||
| TAG="SilentAuthReceiver" | ||
| DOZE_FORCED=false | ||
|
|
||
| RED='\033[0;31m' | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| NC='\033[0m' | ||
|
|
||
| echo "=============================================" | ||
| echo " Doze Network Block Reproduction Test" | ||
| echo "=============================================" | ||
| echo "" | ||
|
|
||
| # --- Prerequisite checks --- | ||
| echo "[1/9] Checking adb connection..." | ||
| if ! adb devices 2>/dev/null | grep -q "device$"; then | ||
| echo -e "${RED}ERROR: No adb device connected.${NC}" | ||
| echo "Connect a device via USB and authorize adb." | ||
| exit 1 | ||
| fi | ||
| SERIAL=$(adb devices | grep "device$" | head -1 | awk '{print $1}') | ||
| if [ -z "$SERIAL" ]; then | ||
| echo -e "${RED}ERROR: Failed to resolve adb device serial.${NC}" | ||
| exit 1 | ||
| fi | ||
| echo " Device: $SERIAL" | ||
| ADB=(adb -s "$SERIAL") | ||
|
|
||
| adb_cmd() { | ||
| "${ADB[@]}" "$@" | ||
| } | ||
|
|
||
| cleanup() { | ||
| if [ "$DOZE_FORCED" = true ]; then | ||
| echo "[9/9] Cleaning up Doze..." | ||
| adb_cmd shell dumpsys deviceidle unforce > /dev/null 2>&1 || true | ||
| adb_cmd shell dumpsys battery reset > /dev/null 2>&1 || true | ||
| DOZE_FORCED=false | ||
| echo " Doze reset to ACTIVE" | ||
| fi | ||
| } | ||
|
|
||
| trap cleanup EXIT INT TERM | ||
|
|
||
| echo "[2/9] Checking SilentAuthReceiver is registered..." | ||
| if ! adb_cmd shell "dumpsys package $RECEIVER_PKG" 2>/dev/null | grep -q "SilentAuthReceiver"; then | ||
| echo -e "${RED}ERROR: SilentAuthReceiver not found in $RECEIVER_PKG.${NC}" | ||
| echo "Install MsalTestApp." | ||
| exit 1 | ||
| fi | ||
| echo " SilentAuthReceiver: registered" | ||
|
|
||
| echo "[3/9] Checking broker apps installed..." | ||
| BROKER_PKGS=( | ||
| "com.azure.authenticator" | ||
| "com.microsoft.windowsintune.companyportal" | ||
| "com.microsoft.identity.testuserapp" | ||
| "com.microsoft.appmanager" | ||
| ) | ||
| BROKER_NAMES=( | ||
| "Microsoft Authenticator" | ||
| "Company Portal" | ||
| "BrokerHost (test)" | ||
| "Link to Windows" | ||
| ) | ||
| INSTALLED_BROKERS=() | ||
| INSTALLED_NAMES=() | ||
| for i in "${!BROKER_PKGS[@]}"; do | ||
| if adb_cmd shell pm list packages -e 2>/dev/null | grep -q "${BROKER_PKGS[$i]}"; then | ||
| INSTALLED_BROKERS+=("${BROKER_PKGS[$i]}") | ||
| INSTALLED_NAMES+=("${BROKER_NAMES[$i]}") | ||
| fi | ||
| done | ||
| if [ ${#INSTALLED_BROKERS[@]} -eq 0 ]; then | ||
| echo -e "${RED}ERROR: No broker app installed.${NC}" | ||
| echo "Install one of: Authenticator, Company Portal, BrokerHost, or Link to Windows." | ||
| exit 1 | ||
| fi | ||
| if [ ${#INSTALLED_BROKERS[@]} -gt 1 ]; then | ||
| echo -e "${RED}ERROR: Multiple broker apps installed (${#INSTALLED_BROKERS[@]}):${NC}" | ||
| for i in "${!INSTALLED_BROKERS[@]}"; do | ||
| echo " - ${INSTALLED_NAMES[$i]} (${INSTALLED_BROKERS[$i]})" | ||
| done | ||
| echo "" | ||
| echo "Uninstall all but one broker to get a deterministic test." | ||
| echo "With multiple brokers, MSAL's broker discovery picks one at runtime" | ||
|
rpdome marked this conversation as resolved.
|
||
| echo "and the test can't guarantee which broker handles the request." | ||
| exit 1 | ||
| fi | ||
| BROKER="${INSTALLED_BROKERS[0]}" | ||
| BROKER_NAME="${INSTALLED_NAMES[0]}" | ||
| echo " Broker: $BROKER_NAME ($BROKER)" | ||
|
|
||
| # --- Battery exemption check --- | ||
| echo "[4/9] Checking battery optimization for broker..." | ||
| BATTERY_EXEMPT=false | ||
| if adb_cmd shell dumpsys deviceidle whitelist 2>/dev/null | grep -q "$BROKER"; then | ||
| BATTERY_EXEMPT=true | ||
| fi | ||
| if [ "$BATTERY_EXEMPT" = true ]; then | ||
| echo -e "${YELLOW} WARNING: $BROKER_NAME is battery-exempt (DeviceIdle whitelist).${NC}" | ||
| echo " The broker may bypass Doze network restrictions." | ||
| echo " To remove exemption: Settings > Apps > $BROKER_NAME > Battery > Optimized" | ||
| echo " Or run: adb shell dumpsys deviceidle whitelist -$BROKER" | ||
| echo "" | ||
| echo -e " Continuing anyway — test may show UNEXPECTED SUCCESS...${NC}" | ||
| else | ||
| echo " Battery optimization: active (not exempt) — good" | ||
| fi | ||
|
|
||
| # --- Kill MsalTestApp to ensure cold start --- | ||
| echo "[5/9] Killing MsalTestApp (ensure cold start)..." | ||
| adb_cmd shell am force-stop "$RECEIVER_PKG" > /dev/null 2>&1 | ||
| echo " Killed $RECEIVER_PKG" | ||
| sleep 1 | ||
|
|
||
| # --- Force Doze --- | ||
| echo "[6/9] Forcing Doze mode..." | ||
| adb_cmd logcat -c | ||
| adb_cmd shell dumpsys battery unplug > /dev/null 2>&1 | ||
| adb_cmd shell dumpsys deviceidle force-idle > /dev/null 2>&1 | ||
| DOZE_FORCED=true | ||
|
|
||
| DOZE_STATE=$(adb_cmd shell dumpsys deviceidle get deep 2>/dev/null) | ||
| IDLE_MODE=$(adb_cmd shell "dumpsys power | grep mDeviceIdleMode" 2>/dev/null | tr -d '[:space:]') | ||
| echo " Doze state: $DOZE_STATE" | ||
| echo " $IDLE_MODE" | ||
|
|
||
| if [ "$DOZE_STATE" != "IDLE" ]; then | ||
| echo -e "${RED}ERROR: Failed to enter Doze. State: $DOZE_STATE${NC}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # --- Send broadcast --- | ||
| echo "[7/9] Sending SILENT_AUTH broadcast (background context)..." | ||
| adb_cmd shell "am broadcast \ | ||
| -a $RECEIVER_ACTION \ | ||
| -n $RECEIVER_PKG/$RECEIVER_CLASS \ | ||
| --es scopes 'https://graph.microsoft.com/.default'" > /dev/null 2>&1 | ||
|
|
||
| echo " Waiting ${WAIT_SECONDS}s for auth to complete..." | ||
| sleep "$WAIT_SECONDS" | ||
|
|
||
| # --- Capture results --- | ||
| echo "[8/9] Capturing logcat results..." | ||
| LOGCAT=$(adb_cmd logcat -d -s "${TAG}:*" 2>/dev/null) | ||
|
|
||
| # --- Report results --- | ||
| echo "" | ||
| echo "=============================================" | ||
| echo " Results" | ||
| echo "=============================================" | ||
| echo "" | ||
|
|
||
| if echo "$LOGCAT" | grep -q "=== SUCCESS ==="; then | ||
| echo -e "${GREEN}Result: TOKEN ACQUIRED${NC}" | ||
| echo "" | ||
| echo "The Broker had network access during Doze." | ||
| if [ "$BATTERY_EXEMPT" = true ]; then | ||
| echo " (Broker is battery-exempt — this is expected)" | ||
| fi | ||
| echo "" | ||
| echo "$LOGCAT" | grep "$TAG" | ||
| elif echo "$LOGCAT" | grep -q "=== FAILED ==="; then | ||
| ERROR_CODE=$(echo "$LOGCAT" | grep "Error code:" | sed 's/.*Error code: //') | ||
| ERROR_MSG=$(echo "$LOGCAT" | grep "Message:" | sed 's/.*Message: //') | ||
|
|
||
| echo -e "${RED}Result: AUTH FAILED${NC}" | ||
| echo "" | ||
| echo " Error code: $ERROR_CODE" | ||
| echo " Message: $ERROR_MSG" | ||
| echo "" | ||
|
|
||
| if echo "$ERROR_CODE" | grep -q "io_error"; then | ||
| echo " Interpretation: Doze firewall blocked Broker's network." | ||
| echo " This is the raw DNS/network failure — the Broker attempted" | ||
| echo " the eSTS call but Android's dozable chain dropped the packet." | ||
| elif echo "$ERROR_CODE" | grep -q "device_network_not_available\|power_optimization"; then | ||
| echo " Interpretation: Broker's proactive Doze check caught it." | ||
| echo " The powerOptCheck detected Doze before attempting the" | ||
| echo " network call and returned a classified error." | ||
| else | ||
| echo " Interpretation: Unexpected error code — see details above." | ||
| fi | ||
| elif echo "$LOGCAT" | grep -q "=== CANCELLED ==="; then | ||
| echo -e "${YELLOW}Result: AUTH CANCELLED${NC}" | ||
| echo "$LOGCAT" | grep "$TAG" | ||
| elif echo "$LOGCAT" | grep -q "No signed-in account\|No accounts found"; then | ||
| echo -e "${YELLOW}Result: NO ACCOUNT${NC}" | ||
| echo " Sign in to MsalTestApp first via interactive auth." | ||
| else | ||
| echo -e "${YELLOW}Result: NO OUTPUT${NC}" | ||
| echo " SilentAuthReceiver did not produce expected logs." | ||
| echo "" | ||
| echo "Raw logcat:" | ||
| echo "$LOGCAT" | head -20 | ||
| fi | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.