Skip to content

Improve Debug Report with condition performance and event activity - #1081

Open
vibhor1102 wants to merge 13 commits into
Nain57:masterfrom
vibhor1102:feature/debug-report-condition-performance
Open

Improve Debug Report with condition performance and event activity#1081
vibhor1102 wants to merge 13 commits into
Nain57:masterfrom
vibhor1102:feature/debug-report-condition-performance

Conversation

@vibhor1102

@vibhor1102 vibhor1102 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR completes the Debug Report work started in the foundation-only draft #1065.

It adds the per-condition performance UI proposed in discussion #1064, together with the practical report improvements proposed in discussion #958: Event activity, detection/action timing, faster navigation, clearer filtering, and consistent sorting interactions.

The low-level measurement architecture and its real-device overhead validation are documented in #1065.

Conditions tab

Debug Report now has a third tab dedicated to condition performance. Enabling Debug Report generation automatically collects the data; there is no separate profiling mode.

Every condition currently configured in the Scenario is listed, including conditions that were not reached because of event ordering, disabled paths, or AND/OR short-circuiting. Each card shows:

  • the condition visual and name;
  • its parent event;
  • cumulative processing time;
  • fulfilled and total check counts;
  • average duration per check; and
  • its share of all time spent checking conditions.

The list can be sorted by total time, average per check, check count, or Scenario order. Total time is the default because it most directly identifies the conditions with the greatest overall effect. Durations use four meaningful digits, very small non-zero measurements remain visible, and an explanatory footer defines the percentage denominator.

In the rare case where a report persists across an app update from before condition profiling was introduced, missing profile data is treated as empty data so the report still opens safely.

Event activity

Overview now contains an Event activity summary showing:

  • how many unique events were reached;
  • the total number of occurrences; and
  • the most frequently reached event.

Opening the summary displays a detailed list separated into Screen Events and Trigger Events. Configured events with no occurrences remain visible in a subdued state, which helps distinguish an unreached event from one missing from the Scenario.

The detailed list can be sorted by Scenario order, most frequent, or first execution. Counts are derived from the existing report occurrences, so this feature does not record duplicate event data.

Timeline timing

Timeline occurrences now use the moment their conditions become fulfilled as their timestamp, instead of the later point at which their actions have completed.

Each modern Timeline card replaces the absolute timestamp with two elapsed phases:

  • +175.9 ms detecting: elapsed time from the previous event's action completion (or Scenario start for the first event) until this event is fulfilled;
  • +86.9 ms actions: elapsed time from fulfillment until this event's actions and immediate processing are complete.

Detection and action timings therefore belong to the event that performed them and form one continuous sequence without losing the time between occurrences. Values remain in milliseconds for direct comparison. Events without actions omit the action row.

The exact millisecond detection timestamp remains available in the event-occurrence details, alongside its frame or trigger metadata. Legacy reports retain their existing timestamp under the neutral Recorded at label and do not display a fabricated detection/action split.

Overview also shows Execution Limiter idle time as the percentage of detection-related time deliberately spent waiting for the limiter. Event action phases are excluded from its denominator.

Timeline and report navigation

  • Add a draggable fast scrollbar with a usable minimum thumb and stronger feedback while dragging.
  • Show the number of active Timeline filter categories on the filter button: time range, Screen Events, and Trigger Events.
  • Distinguish a genuinely empty report from a filter result containing no matching events.
  • Provide a direct Clear filters action from the filtered-empty state.
  • Use compact adaptive timestamps in the Timeline time-range selector.
  • Prevent recycled action icons from briefly animating into Timeline cards during fast scrolling.
  • Replace full-screen sort dialogs with compact anchored popups that keep the report visible and clearly highlight the selected option.
  • Keep the viewport at the same list position when changing sort order.
  • Use the same draggable scrollbar in Timeline, Conditions, Event activity, event occurrence details, and the filtered-events selector.

Scope notes

  • Event and condition names, visuals, and ordering are resolved from the Scenario currently stored in the app. Editing a Scenario after generating its report can therefore change the metadata shown for that report.

Verification

  • Rebased onto current master.
  • ARM64 F-Droid debug APK builds successfully.
  • The completed UI was exercised on an Android 14 physical device in portrait and landscape.
  • Focused regression tests are included for report timing, serialization, aggregation, sorting, and formatting; the complete suite is handled by CI.

FAQ

Why is condition performance a third tab while Event activity opens from Overview?

Event activity is a compact aggregate extension of the existing Overview. Condition performance is a larger analytical view containing visuals, several metrics, sorting, unreached conditions, and explanatory context. A dedicated tab keeps that information accessible without overloading Overview.

What exactly does a condition percentage represent?

It is the condition's cumulative duration divided by the sum of all recorded condition durations. It is not a percentage of total Scenario time, CPU use, battery use, or system activity.

Why are detection and action time shown separately?

The interval between two fulfilled events can contain both the previous event's actions and work spent finding the next event. Assigning the complete interval to either event would be misleading. Capturing fulfillment and action-completion boundaries lets every action duration remain with the event that executed those actions.

Why is Timeline detection time not calculated from the condition profiler?

Condition profiles are aggregate totals intended to identify expensive conditions. They cannot reconstruct an individual occurrence's boundaries or account for unsuccessful event checks, frame waiting, Execution Limiter waiting, and other processing between fulfilled events. Timeline timing therefore uses dedicated monotonic per-occurrence boundaries.

What is included in “detecting”?

It is elapsed time spent reaching the next fulfilled event, not a claim about CPU-active time alone. It includes condition processing, unsuccessful checks, frame waiting, Execution Limiter waiting, and intervening processing. Keeping those parts together gives users a simple, continuous Timeline while the Conditions tab provides the detailed performance breakdown they can act on.

How do the Timeline durations avoid gaps or overlap?

For the first occurrence, detection starts at the report session boundary. Afterwards it starts at the previous occurrence's action-completion boundary. Action time starts at the current occurrence's fulfillment boundary and ends at its own completion boundary. All values use the same monotonic clock, so consecutive phases meet exactly. Any time after the final occurrence remains outside the Timeline because there is no later event card to own it.

Why are unreached conditions and events shown?

Zero checks or occurrences can be diagnostically important. Keeping configured entries visible lets the user distinguish “present but never reached” from “not configured,” and it makes Scenario-order views complete.

Why derive Event activity from Timeline occurrences?

The report already records every event occurrence needed for these counts. Deriving the summary avoids another stored aggregate and prevents two sources of event-count data from disagreeing.

How are duplicate names and overlapping IDs handled?

Condition entries use their database IDs. Event activity identifies an event by both its event type and database ID, so Screen and Trigger Events with the same numeric ID cannot merge. Names are display metadata and do not determine identity.

Why use anchored sort popups?

The available sort choices are short and immediately applicable. An anchored popup keeps the underlying report visible, clearly marks the current selection, and avoids a full-screen dialog in landscape.

Why preserve the viewport position rather than the visible card when sorting?

Sorting is expected to rearrange the content beneath a stationary viewport. Following the previously visible card to its new location caused unexpected jumps through the list and made the new order harder to inspect.

Why use a custom scrollbar instead of RecyclerView's normal indicator?

The normal indicator is visual only and can become extremely small on long reports. The custom view provides a minimum draggable thumb, a larger touch corridor, continuous scrolling, and explicit drag feedback while leaving RecyclerView as the source of scroll state.

How do older reports behave?

The added protobuf fields use new field numbers, so existing Overview and Timeline data remain readable. If condition-profile data is absent, it falls back to empty data and the report remains safe to open. If the new occurrence boundaries are absent, Timeline keeps the legacy recorded timestamp and does not invent detection or action durations.

Where should the profiling architecture itself be reviewed?

The measurement boundary, disabled-path behavior, bounded aggregation, protobuf storage, benchmark design, and overhead interpretation are covered in #1065.

@vibhor1102
vibhor1102 marked this pull request as draft August 29, 2026 15:43
@vibhor1102
vibhor1102 marked this pull request as ready for review August 30, 2026 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant