Skip to content

ADFA-4371: EOFException is reported for empty simpleperf reports#1420

Merged
itsaky-adfa merged 1 commit into
feat/ADFA-4333from
fix/ADFA-4371
Jun 18, 2026
Merged

ADFA-4371: EOFException is reported for empty simpleperf reports#1420
itsaky-adfa merged 1 commit into
feat/ADFA-4333from
fix/ADFA-4371

Conversation

@itsaky-adfa

Copy link
Copy Markdown
Contributor

No description provided.

Signed-off-by: Akash Yadav <itsaky01@gmail.com>
@itsaky-adfa itsaky-adfa requested a review from Daniel-ADFA June 18, 2026 17:55
@itsaky-adfa itsaky-adfa self-assigned this Jun 18, 2026
@itsaky-adfa itsaky-adfa changed the base branch from stage to feat/ADFA-4333 June 18, 2026 18:00
@itsaky-adfa itsaky-adfa merged commit 7e7c6d5 into feat/ADFA-4333 Jun 18, 2026
2 checks passed
@itsaky-adfa itsaky-adfa deleted the fix/ADFA-4371 branch June 18, 2026 18:02
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Release Notes: ADFA-4371 - EOFException Fix for Empty Simpleperf Reports

Bug Fix

  • Fixed EOFException when processing empty simpleperf reports: The SimpleperfReportParser now gracefully handles empty or truncated simpleperf report-sample --protobuf output by returning an empty CpuProfile instead of throwing an exception. The parser treats EOF during header validation and record parsing as valid empty profiles, enabling profiling operations to complete without crashes when no profiling data is available.

New Features

  • CPU Profiling: Added comprehensive CPU profiling support via simpleperf integration

    • Live CPU sample collection and streaming to UI via AIDL observers
    • Simpleperf report parsing with call tree reconstruction and symbol resolution
    • Per-method aggregation with self/inclusive timing, percentages, and method-level statistics
    • Support for multiple recording sessions with proper cleanup and timeout handling
  • Heap Dump Analysis: New HeapDumpAnalyzer for analyzing .hprof heap dumps

    • Per-class object count and shallow memory statistics
    • Human-readable byte and count formatting
  • Flamegraph Visualization: Interactive flamegraph UI for call tree rendering

    • Support for top-down and bottom-up orientations
    • Pan, zoom, and frame selection interactions
    • Folded-stack text parsing and tree building
    • Comprehensive test coverage for layout and parsing
  • Privileged Profiler Service: New Shizuku-based service for privileged profiling operations

    • Live process list observation with add/remove delta buffering and coalescing
    • Heap dumps and CPU profiling for any debuggable/profileable process
    • AIDL-based IPC with observer callbacks for real-time updates
    • Process discovery fallback for pre-API-31 systems
  • New Profiler Tab: Added experimental profiler tab to editor bottom sheet with dedicated UI for process selection, live profiling status, and result visualization

Technical Changes

  • Added new Gradle plugin (ProfilerPlugin) to inject android:profileable="android:shell=true" into app manifests for profiling support
  • New configuration property PROPERTY_PROFILEABLE_ENABLED to control profileable manifest generation
  • BuildViewModel.runQuickBuild() now accepts launchProfilerAfterInstall and gradleArgs parameters
  • BuildState.AwaitingInstall now tracks whether to launch profiler after installation
  • New subprojects: profiler, flamegraph, hidden-apis, hidden-apis-compat, privileged-services
  • Updated Shizuku manager provider to use synchronous polling with timeout for binder availability checks

Dependencies Added

  • LeakCanary shark libraries: shark, shark-android, shark-hprof, shark-graph

Risks & Best Practices Violations

⚠️ High Risk Areas:

  • Complex IPC/Binder Integration: Privileged service uses raw AIDL and binder APIs with reflection-based fallbacks to handle ActivityManager methods across APIs 26-35. Multiple overload variants for dumpHeap() with different signatures and return mechanisms (sync/async via RemoteCallback) increase maintenance complexity and potential for version-specific bugs.

  • Thread Safety & Concurrency: ProfilerUserService confines process-list state to a worker thread but uses buffers, debouncing delays (50ms), and coalesced delta notifications. Race conditions between observer registration and notifications are possible. CPU profiling uses a lock but only prevents concurrent sessions, not concurrent access patterns.

  • SDK-Version-Specific Code Paths: Multiple conditional branches for APIs 8, 9, 10-14, and 15+ without comprehensive test coverage across all API levels. Untested fallback paths could fail silently.

  • Resource Lifecycle Management:

    • Temporary files from profiling are deleted in finally blocks, but if simpleperf hangs during stop(), the forced process destruction may not clean up child processes
    • Parser catches EOF mid-record but doesn't validate remaining stream integrity
    • No explicit timeout for process discovery polling; system server restarts could stall discovery with bounded retries
  • Hidden API Reflection: Uses reflection to get app labels and detect app metadata without Context, with silent failures on missing fields. Version mismatches could cause incorrect profiling eligibility decisions.

⚠️ Design Concerns:

  • Experimental Feature Gating: Profiler is hidden behind FeatureFlags.isExperimentsEnabled with no clear graduation or deprecation plan. Long-term feature stability not documented.
  • Protobuf Format Assumptions: SimpleperfReportParser makes assumptions about simpleperf binary output format (little-endian, MAGIC header, record framing). Format changes in newer simpleperf versions could break parsing silently.
  • Process List Freshness: Pre-API-31 process discovery is event-driven (activity/service changes), potentially missing background process changes until next foreground event.
  • CPU Profile Accuracy: Sample buffering in first pass then symbol resolution in second pass assumes File records always arrive after samples; early File records would be skipped.

Walkthrough

This PR adds a profiler feature with profileable-build wiring, a privileged Shizuku-backed profiling service, a new profiler UI and app entry points, a standalone flamegraph module, and local tooling/configuration updates.

Changes

Profiler feature

Layer / File(s) Summary
Build and module wiring
app/build.gradle.kts, app/src/main/java/com/itsaky/androidide/actions/build/*, app/src/main/java/com/itsaky/androidide/viewmodel/*, gradle-plugin/..., profiler/build.gradle.kts, settings.gradle.kts, subprojects/projects/...
Adds profileable-build support, includes the profiler module, passes Gradle args through quick builds, and records install state for opening the profiler after APK install.
Privileged profiler backend
subprojects/hidden-apis*/*, subprojects/privileged-services/*, subprojects/shizuku-*/*
Adds hidden API contracts, compatibility wrappers, AIDL interfaces, a privileged profiler service, CPU profiling session management, and Shizuku service startup/binder handling updates.
Profiler client runtime
profiler/src/main/java/org/appdevforall/cotg/profiler/*, profiler/src/main/proto/report_sample.proto
Adds profiler models, heap and simpleperf result parsing, service binding, fragment hosting, and ViewModel logic for process selection, heap dumps, CPU profiling, and result state updates.
Profiler UI and app entry points
app/src/main/java/com/itsaky/androidide/actions/*, app/src/main/java/com/itsaky/androidide/actions/profiler/*, app/src/main/java/com/itsaky/androidide/adapters/*, app/src/main/java/com/itsaky/androidide/utils/*, resources/src/main/res/*, profiler/src/main/java/.../ui/*
Adds profiler screens and components, shared pairing/permission dialogs, a new profiler action, bottom-sheet tab wiring, post-install tab switching, and profiler strings and icon resources.

Flamegraph component

Layer / File(s) Summary
Flamegraph data and layout
subprojects/flamegraph/build.gradle.kts, subprojects/flamegraph/src/main/java/.../model/*, subprojects/flamegraph/src/main/java/.../internal/*, subprojects/flamegraph/src/test/*
Adds the standalone flamegraph module, folded-stack parsing, immutable tree models, iterative layout computation, and tests for parsing, focus, hit testing, sizing, and subtree rules.
Flamegraph rendering and state
subprojects/flamegraph/src/main/java/.../Flamegraph*.kt, subprojects/flamegraph/src/main/java/.../SampleFlameData.kt
Adds the interactive Compose renderer with zoom, pan, selection, orientation support, theme colors, saveable state, and preview/sample datasets.

Tooling updates

Layer / File(s) Summary
Local tooling files
.claude/settings.local.json, flox/local/.flox/env/manifest.toml
Updates local Claude MCP and command permissions, and revises the Flox manifest schema and selected package outputs.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProfilerAction
  participant BuildViewModel
  participant ProjectHandlerActivity
  participant ProfilerFragment
  participant ProfilerUserService

  User->>ProfilerAction: Start profiler build
  ProfilerAction->>BuildViewModel: runQuickBuild(..., gradleArgs)
  BuildViewModel->>ProjectHandlerActivity: AwaitingInstall(launchProfilerAfterInstall)
  ProjectHandlerActivity->>ProfilerFragment: Open profiler tab after install
  ProfilerFragment->>ProfilerUserService: bind via Shizuku service connection
  ProfilerUserService-->>ProfilerFragment: process list / heap dump / CPU profiling data
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

🐇 I tapped a tab called Profiler bright,
and heap and CPU woke up tonight.
Through Shizuku burrows, binders flew,
with graphs and tables fresh as dew.
A flamegraph flickered, warm and spry—
little code-rabbit carrots piled high.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning No description was provided by the author. This is a significant omission given the extensive nature of the changes, which includes new profiler subsystem, privileged services, flamegraph UI, and hidden API compatibility layers. Add a detailed pull request description explaining the profiler feature addition, the purpose of new modules (privileged-services, profiler, flamegraph, hidden-apis), and how the simpleperf report parsing fix addresses the EOFException issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly references a specific issue (ADFA-4371) and describes the main fix: handling EOFException for empty simpleperf reports, which is directly related to the profiler module additions and CPU profiling implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ADFA-4371

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PMD (7.25.0)
gradle-plugin/src/main/java/com/itsaky/androidide/gradle/ProfilerPlugin.kt

No java executable found in PATH


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

3 participants