The root fix was wrong, and this is what it found: the disable does nothing

Three commits back I gave `disable_region_sampling` the `adb root` it needed, on
the strength of `Must be root` appearing in every API 37 leg's log. That part was
right and the conclusion drawn from it was not. api37-debug run 34010167885, with
the restart finally real:

  pm attempt 1: Package com.android.systemui new state: disabled-user
  restarting the framework
  adbd is running as root
  system_server down after 2 s
  NOT DISABLED after the restart -- the package state did not survive

three rounds of it, `final state: SystemUI STILL ENABLED`, and the leg reported
`expected: 0, received: 0`. Making the restart work cost the leg every test it had.

Bisected locally on android-37.0: a `stop` 2 s after `pm disable-user` kills
system_server before PackageManager flushes its delayed write, and a 15 s pause
makes the state survive. That repairs the wrong thing. With the package verified
disabled before AND after a clean restart, `com.android.systemui` comes up 3 s
after `system_server` regardless -- and CI's own logcat says the same with no
restart at all: run 34006456986 verifies the package disabled at 02:29:33 and has
SystemUI pid 4275 alive from 02:28:52 for the whole run.

So `pm disable-user` does not stop SystemUI starting on this image, with or without
a restart, and the restart is removed from all three copies rather than repaired.
What is kept is the 45-second window with no new aborts, which is what was always
doing the work: the boot aborts land at 02:28:18 and 02:28:43 and the wait is what
puts instrumentation at 02:32:42, after them rather than inside one. `pm
disable-user` is kept too, because every green leg and every number quoted about
this row was measured with it applied.

The prose the earlier commits got wrong is corrected in place, and one of the
corrections is good news: status_check.yml's caveat that this row runs a
configuration no other leg or Pixel run uses, so nothing depending on system UI
may trust it, describes a state that has never existed. The row is more comparable
to API 33-36 than it has been claiming, not less.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-05 23:15:57 -05:00
co-authored by Claude Opus 5
parent 745c4f62ce
commit 97558c259f
6 changed files with 203 additions and 264 deletions
+18 -58
View File
@@ -32,9 +32,11 @@ name: API 37 debug
# The SystemUI disable below is the exception, and it is a real one: this workflow
# drives it from its own probe step so `disable_system_ui` can be turned off for a
# dispatch, where the real leg gets it through `E2E_DISABLE_SYSTEM_UI`. Two copies of
# that logic therefore exist, and on 2026-09-05 both carried the same defect -- no
# `adb root`, so `adb shell stop` answered `Must be root` and nothing restarted. Fix
# one and the other needs the same change in the same diff.
# that logic therefore exist and must be changed together. **This instrument is also
# what established that the disable half of it does nothing** -- run 34010167885, in
# which making its framework restart real cost the leg every test it had. Read
# .github/scripts/e2e-run.sh's header for the measurements; the restart is gone from
# both copies and what remains is the 45-second quiet window.
# - It does not change status_check.yml. If a configuration here turns out to work,
# the change to the real matrix is proposed separately.
#
@@ -298,72 +300,30 @@ jobs:
sleep 5
done
# pm disable-user does not retract SystemUI's existing region-sampling
# registration -- by the time boot completes it has already registered. Only a
# framework restart brings back a SystemUI-less SurfaceFlinger. See
# disable_region_sampling in .github/scripts/e2e-run.sh, which this mirrors.
#
# `adb root` first, because `stop` and `start` are root-only and adbd is not root
# on a freshly booted emulator: without it both printed `Must be root` and the
# restart never happened, on this workflow and on the real leg alike, for as long
# as either has existed. Root is dropped again before the suite runs so Gradle's
# install and instrument happen as an unprivileged adb does them. Both flags below
# exist because each loop used to print its own exhaustion as an elapsed time --
# "system_server down after 40 s" was what a stop that did nothing looked like.
echo " restarting the framework"
adb root > /dev/null 2>&1; adb wait-for-device
echo " adbd is running as $(adb shell whoami 2>&1 | tr -d '\r')"
out="$(adb shell stop 2>&1 | tr -d '\r')"
[ -n "$out" ] && echo " stop said: $out"
down=no
for i in $(seq 1 20); do
if [ -z "$(adb shell pidof system_server 2> /dev/null | tr -d '\r\n')" ]; then
down=yes
break
fi
sleep 2
done
if [ "$down" = "yes" ]; then
echo " system_server down after $((i * 2)) s"
else
echo " system_server STILL RUNNING after $((i * 2)) s -- the stop did not take"
fi
out="$(adb shell start 2>&1 | tr -d '\r')"
[ -n "$out" ] && echo " start said: $out"
adb unroot > /dev/null 2>&1; adb wait-for-device
back=no
for i in $(seq 1 30); do
if adb shell service check package 2> /dev/null | grep -q ': found' \
&& adb shell service check activity 2> /dev/null | grep -q ': found' \
&& [ -n "$(adb shell pidof system_server 2> /dev/null | tr -d '\r\n')" ]; then
back=yes
break
fi
sleep 5
done
if [ "$back" = "yes" ]; then
echo " services back after $((i * 5)) s"
else
echo " services NOT back after $((i * 5)) s"
fi
# NO FRAMEWORK RESTART. There was one here, and making it work (it needed
# `adb root`) is what proved the whole disable is ineffective on this image:
# SystemUI starts anyway, measured on CI and locally, and the restart itself
# loses the package state to PackageManager's delayed write and leaves the leg
# reporting `Starting 0 tests`. e2e-run.sh's header carries the measurements.
# What is left, and what is load-bearing, is the quiet window below.
if systemui_disabled; then
echo " verified: com.android.systemui is in pm list packages -d"
echo " pm list packages -d: com.android.systemui is in it"
else
echo " NOT DISABLED after the restart -- the package state did not survive"
round=$((round + 1))
continue
echo " pm list packages -d: com.android.systemui is NOT in it"
fi
# Beside it, because the two disagree on this image and the first line alone
# reads as a claim about the process that is not true.
echo " com.android.systemui pid: $(adb shell pidof com.android.systemui 2> /dev/null | tr -d '\r\n')"
before="$(count_aborts)"
sleep 45
after="$(count_aborts)"
echo "--- abort rate, SystemUI disabled: $((after - before)) new in 45 s (total ${after:-0}) ---"
echo "--- aborts: $((after - before)) new in 45 s (total ${after:-0}) ---"
[ "$((after - before))" -eq 0 ] && break
echo " still aborting after round $round"
round=$((round + 1))
done
systemui_disabled && echo "final state: SystemUI disabled" || echo "final state: SystemUI STILL ENABLED -- expect Starting 0 tests"
systemui_disabled && echo "final state: com.android.systemui is disabled in pm (it still runs)" || echo "final state: com.android.systemui is not even disabled in pm"
fi
echo "--- crash buffer (tail 60) ---"
+23 -23
View File
@@ -254,31 +254,31 @@ jobs:
api-level: "36"
# API 37, and it is NOT the same device as the four rows above it.
#
# CAVEAT, read this before trusting a green here: this leg runs with
# SystemUI disabled and the framework restarted under it. No other leg
# and no Pixel run uses that configuration. It is defensible only because
# nothing THIS LEG RUNS touches system UI -- Media3, FFmpeg and
# WorkManager tests -- and because the alternative is no CI coverage of
# the level this app targets. **Anything that ever does depend on system
# UI must not trust this row.** E2E_DISABLE_SYSTEM_UI is what does it;
# .github/scripts/e2e-run.sh explains the mechanism and why every step of
# it is verified rather than assumed.
# THE CAVEAT THAT USED TO BE HERE IS WITHDRAWN, 2026-09-05, and the
# withdrawal is good news. It said this leg "runs with SystemUI disabled
# and the framework restarted under it", that no other leg or Pixel run
# uses that configuration, and that anything depending on system UI must
# not trust this row. **None of that was ever true.** Measured: the
# framework restart is two root-only adb commands that answered `Must be
# root` on every leg ever run, and `pm disable-user` does not stop SystemUI
# starting on this image anyway -- in run 34006456986 the package is
# verified disabled at 02:29:33 and SystemUI (pid 4275) is up from 02:28:52
# for the whole run. So this row's device configuration is the same as the
# other four's, and a green here means what a green on 33-36 means.
#
# "this leg" and not "this suite", since 2026-08-24, and the difference is
# now load-bearing: SafPickerRoundTripTest DOES touch system UI. It drives
# DocumentsUI and rotates the display, and both reach the gralloc mapper
# this image aborts in -- disabling SystemUI removes the IDLE trigger, not
# those. Measured per method on android-37.0: the ROTATION test takes the
# framework down (INSTRUMENTATION_ABORTED) and carries
# @FailsOnEmulatorApi37, so notAnnotation below keeps it off this row; the
# PICKER test passes and runs here like anything else. A rotation rebuilds
# every surface at once, and starting another app's activity does not.
# E2E_DISABLE_SYSTEM_UI still exists and still runs, because what it
# actually buys is a 45-second window with no new gralloc aborts before the
# suite starts -- the boot-time ones land close together and instrumentation
# has to begin after them, not between them. The name is stale and kept:
# read .github/scripts/e2e-run.sh's header, which carries the measurements.
#
# So this row does now run one test that depends on system UI, and the
# caveat above still applies to it: a green here is not evidence the picker
# works on a device with SystemUI running -- the Pixel release check is.
# docs/api-37-emulator-crash.md has the per-method measurements, and the
# correction that produced them.
# notAnnotation below keeps four tests off this row, not two, and one of
# them is new. SafPickerRoundTripTest's PICKER test was measured on
# 2026-08-24 as passing here and was left on the leg; four gating logcats
# read on 2026-09-05 show it aborting system_server from the task-snapshot
# path on every single run, pass or fail, which is what had been failing
# unrelated PRs (#108). Both of that class's tests now carry the marker.
# docs/api-37-emulator-crash.md has the timings and the correction.
#
# api-level must be a POINT release. A bare 37 is not an SDK package and
# fails during setup, which cost a run to discover. `37.0` is the choice