2336 Commits

Author SHA1 Message Date
py - Pierre Yves Ricau
e7f9963b6a Merge pull request #2806 from blundell/update-min-sdk-to-api-21
Update minimum SDK to API 26 (Android 8.0 Oreo)
2026-03-05 05:13:05 -06:00
pblundell
2cbdce272b Remove obsolete AndroidLeakFixes after minimum SDK upgrade
Removes 5 AndroidLeakFixes enum constants that are no longer needed
with minimum SDK 26+:

- MEDIA_SESSION_LEGACY_HELPER (API 21 only)
- CONNECTIVITY_MANAGER (API ≤23 only)
- ACTIVITY_MANAGER (Samsung API 22 only)
- IMM_FOCUSED_VIEW (API ≤23 only)
- SPELL_CHECKER (API 23 only)

These fixes were already no-ops with early returns after the min SDK
upgrade. Removing them completely eliminates ~200 lines of dead code
and documentation while maintaining all functional leak fixes.

The remaining 10 AndroidLeakFixes enum constants continue to provide
useful leak fixes for Android 26+.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-04 10:01:35 +00:00
pblundell
6f79d2232b Fix ObsoleteSdkInt lint errors after API 26 upgrade
With minSdkVersion now set to API 26 (Android 8.0), many of the Android leak fixes in the plumber module are no longer necessary as they targeted older API levels. This commit resolves lint warnings by adding early returns to obsolete fixes and removing unnecessary API annotations.

Changes made:
- AndroidLeakFixes.kt: Added early returns to 6 leak fixes that only applied to API levels below 26:
  • MEDIA_SESSION_LEGACY_HELPER (was for API 21)
  • FLUSH_HANDLER_THREADS (was for API 14-25)
  • LEAK_CANARY_THREAD_EDGE_CASE (was for API 21-25)
  • ACTIVITY_THREAD_EDGE_CASE (was for API 16-25)
  • CONNECTIVITY_MANAGER (was for API 21-25)
- FixedWindowCallback.java: Removed obsolete @RequiresApi(23) annotation from onSearchRequested method
- Cleaned up unused Build.VERSION imports after removing version checks

These changes eliminate 11 ObsoleteSdkInt lint errors while maintaining API compatibility. The affected leak fixes are no longer needed since Android 8.0+ doesn't have these issues.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-28 23:06:30 +00:00
py - Pierre Yves Ricau
0cbefba206 Merge pull request #2736 from square/py/strip_more
HprofPrimitiveArrayStripper: sync with android-register, fix bugs, clean up
2026-02-28 05:42:33 -06:00
Pierre-Yves Ricau
a6b2310ce8 HprofPrimitiveArrayStripper: fix bugs, add StreamingSinkProvider
Fix two correctness bugs:

- INSTANCE_DUMP: stackTraceSerialNumber is always u4 (4 bytes), not
  identifier-sized. This was silently corrupting output for heap dumps
  with 8-byte identifiers.
- PRIMITIVE_ARRAY_DUMP: CopyingSource.transferUnsignedByte() already
  copies the type byte to the sink — the extra sink.writeByte(type) call
  was writing it twice, corrupting all primitive array records.

Fix a third bug in CopyingSource.transferUtf8: it decoded bytes as
UTF-8 into a Java String then re-encoded, which produces different byte
counts for Modified UTF-8 sequences (used by HotSpot HPROF). The fix
reads the raw bytes and copies them unchanged, only decoding to String
for the return value.

Other changes:
- Add StreamingSinkProvider (mirrors StreamingSourceProvider) so the
  sink lifecycle is managed inside the function via .use {}
- Replace BufferedSink parameter with StreamingSinkProvider in the
  streaming overload
- Refactor parsing into a private stripPrimitiveArrays(CopyingSource)
  method
- Add CopyingSource.indexOf delegate
- Also updates all primitive wrapper instance values to 0 (in addition
  to primitive arrays), as an additional PII safety measure
- Add deleteInputHprofFile parameter to delete the input file eagerly
  after the source is opened, using the Unix trick
- Clean up test: replace raw-byte helpers with HprofWriter-based
  fixture, add JVM heap dump tests for string replacement and wrapper
  value zeroing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 05:34:06 -05:00
pblundell
6885e6876a Update minimum SDK to API 26 (Android 8.0 Oreo)
This commit migrates the entire LeakCanary project from minimum SDK API 21
to API 26, enabling modern Android features and further simplifying the codebase.

API 26 corresponds to Android 8.0 (Oreo), released in 2017, providing
over 7 years of Android compatibility while enabling notification channels
and modern development practices.

Changes included:

## Build Configuration
- Update androidMinSdk from "21" to "26" in version catalog
- Update hardcoded minSdk value in leakcanary-app from 21 to 26
- Update comment to reflect modern Android features requirement

## GitHub Actions / CI
- Remove API 21 and API 23 from test matrix
- Streamline CI to test only API 26+ (26, 31, 33, 34)
- Improve CI efficiency with fewer test combinations

## Code Modernization
- Simplify notification builder to always use notification channels (API 26+ requirement)
- Remove obsolete PendingIntent FLAG_IMMUTABLE version checks (API 23+ always available)
- Simplify instant app detection (API 26+ always supports this)
- Remove obsolete SDK version checks for dynamic shortcuts (N_MR1 no longer relevant)
- Modernize Context.getColor() usage (API 23+ always available)
- Simplify process utilities in UiAutomator (API 23+ features always available)
- Remove obsolete @TargetApi annotations for API levels below 26

## Resources & UI
- Move adaptive icons from mipmap-anydpi-v26 to mipmap-anydpi (no qualifier needed)
- Move app launcher icons from drawable-v24 to drawable (API 26+ always supports adaptive icons)
- Remove obsolete resource version qualifiers

## Code Cleanup
- Remove unused import statements after version check removals
- Simplify conditional logic where version checks became always true/false
- Remove dead code branches for pre-API 26 compatibility

## Benefits
- Access to notification channels (API 26 requirement) without compatibility code
- Simplified codebase with removed legacy compatibility workarounds
- Modern UI patterns with adaptive icons as standard
- Faster CI builds with fewer test matrix combinations

## Compatibility
All modules now consistently require Android 8.0 (API 26, 2017) or higher.
This affects minSdk but does not change the public API surface.
Library consumers benefit from simplified, more reliable notification handling.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-27 14:14:22 +00:00
pblundell
c1b9efe482 Update minimum SDK to API 21 (Android 5.0 Lollipop)
This commit migrates the entire LeakCanary project from minimum SDK API 14
to API 21, enabling modern Android features and simplifying the codebase.

API 21 corresponds to Android 5.0 (Lollipop), released in 2014, providing
over a decade of Android compatibility while enabling Material Design and
modern development practices.

Changes included:

## Build Configuration
- Update androidMinSdk from "14" to "21" in version catalog
- Standardize all modules to use libs.versions.androidMinSdk reference
- Update hardcoded minSdk values in sample and library modules to use TOML

## GitHub Actions / CI
- Remove API 16 and API 19 from test matrix
- Streamline CI to test only API 21+ (21, 23, 26, 31, 33, 34)
- Improve CI efficiency with fewer test combinations

## Test Infrastructure
- Upgrade androidx.test:orchestrator from 1.4.2 to 1.5.0
- Modernize test assertions to use direct assertThat(Throwable) calls
- Remove API 16 workaround comments and code

## Code Modernization
- Remove obsolete SDK version checks (9 lint issues resolved)
- Simplify file provider methods for API 21+ only
- Update notification builder usage for modern APIs
- Remove legacy view tree observer workarounds
- Modernize layout and rendering code

## Resources & UI
- Migrate drawable resources from selectors to Material ripple effects
- Update themes from Holo to Material Design (API 21+ requirement)
- Merge and remove obsolete -v21 resource folders
- Modernize button and touch feedback using ripples

## Benefits
- Access to Material Design components and APIs
- Simplified codebase with removed legacy compatibility code
- Enhanced test infrastructure with latest orchestrator
- Improved user experience with modern UI patterns
- Faster CI builds with fewer test matrix combinations

## Compatibility
All modules now consistently require Android 5.0 (API 21, 2014) or higher.
This affects minSdk but does not change the public API surface.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-27 00:04:42 +00:00
py - Pierre Yves Ricau
c2ddc5a5c5 Merge pull request #2737 from jjliu15/reference_matchers_mnextservedview
Extend InputMethodManager workaround to API level 35
2026-02-26 17:49:12 -06:00
py - Pierre Yves Ricau
a6d2b6b935 Merge pull request #2799 from blundell/fix-instru-tests
Update Gradle, AGP, Hilt
2026-02-26 14:47:04 -06:00
Pierre-Yves Ricau
89a3079e56 Remove trailing inline comments from @Suppress annotations
Move the explanation to the preceding comment line instead of appending
it to the annotation itself, per project style conventions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 21:28:39 +01:00
Pierre-Yves Ricau
cd658fe3c3 Merge remote-tracking branch 'origin/main' into fix-instru-tests
* origin/main:
  Pin gradle/actions/wrapper-validation to commit SHA to satisfy code scanning
  Drop API 28 and 29 from instrumentation test matrix
  Fix LeakActivityTest on API 33+ by disabling notifications during test
  Fix INSTALL_FAILED_DEPRECATED_SDK_VERSION on API 28+ for leakcanary-android tests
  Upgrade wrapper-validation-action to gradle/actions/wrapper-validation@v4
  Add recent Android API levels to instrumentation test matrix
  Fix pkill self-match: use qemu-syste[m] pattern
  Update changelog entry wording for ToastEventListener fix
  Fix emulator process hanging 20+ min after CI tests finish
  Add changelog entry for ToastEventListener race condition fix
  Fix ToastEventListener race condition retaining finished Toast
2026-02-26 21:28:23 +01:00
py - Pierre Yves Ricau
fabd71f66c Merge pull request #2803 from square/worktree-add-emulators
Add recent Android API levels (28, 29, 31, 33, 34) to instrumentation CI matrix
2026-02-26 14:25:11 -06:00
Pierre-Yves Ricau
1731885746 Pin gradle/actions/wrapper-validation to commit SHA to satisfy code scanning
Fixes "Insecure GitHub Actions: Third-Party Action Not Pinned to Commit SHA"
flagged by GitHub Advanced Security on PR #2803. Pins to the commit SHA
corresponding to v4 while keeping the tag as a comment for readability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 21:11:31 +01:00
Pierre-Yves Ricau
b72effd744 Drop API 28 and 29 from instrumentation test matrix
Based on timing analysis across two full CI runs:
- API 28 averaged 652s (~11 min), slowest after API 29
- API 29 averaged 672s (~11 min), consistently the slowest new addition

API 31, 33, and 34 provide good modern Android coverage at reasonable
cost (568–622s avg). APIs 28 and 29 can be reconsidered later if
Android 9/10 coverage becomes a specific need.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:06:54 +01:00
Pierre-Yves Ricau
38deaf55dd Fix LeakActivityTest on API 33+ by disabling notifications during test
When targetSdk >= 33 and notifications are not enabled (fresh emulator),
Notifications.canShowNotification launches RequestPermissionActivity with
FLAG_ACTIVITY_NEW_TASK to request POST_NOTIFICATIONS permission. This
pushes LeakActivity to PAUSED, causing Espresso's onView() to throw
NoActivityResumedException.

The test is validating the heap import flow, not notifications. Setting
showNotifications = false prevents the permission activity from launching
so LeakActivity stays in the RESUMED state for the Espresso assertions.
The tryAndRestoreConfig wrapper already restores the original config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:06:47 +01:00
Pierre-Yves Ricau
b79e8a9076 Fix INSTALL_FAILED_DEPRECATED_SDK_VERSION on API 28+ for leakcanary-android tests
Android 9 (API 28) and above refuse to install APKs that target
SDK version < 23. The leakcanary-android module was missing an explicit
targetSdk in its defaultConfig, causing the test APK to default to
targetSdkVersion = minSdkVersion = 14.

leakcanary-android-core already had this fix with an explanatory comment.
Apply the same to leakcanary-android so it can run on API 28-34 emulators.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:06:47 +01:00
Pierre-Yves Ricau
d42b3b575f Upgrade wrapper-validation-action to gradle/actions/wrapper-validation@v4
The old gradle/wrapper-validation-action@v1 was silently failing on all
PR runs (works on push-to-main but not on PR merge commits). The modern
replacement is gradle/actions/wrapper-validation which is actively
maintained by Gradle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:06:47 +01:00
Pierre-Yves Ricau
14b806eb5d Add recent Android API levels to instrumentation test matrix
Add API levels 28, 29, 31, 33, and 34 (Android 9-14) to the CI
emulator matrix. API 29 was previously marked flaky but is worth
retrying with current tooling. All use x86_64 + google_apis + stable
channel, consistent with the existing modern emulator configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:06:47 +01:00
py - Pierre Yves Ricau
31ca31149e Merge pull request #2804 from square/changelog-toast-fix
Add changelog entry for ToastEventListener race condition fix
2026-02-26 13:03:35 -06:00
py - Pierre Yves Ricau
96375aa57e Merge pull request #2805 from square/fix-emulator-hang
Fix CI: force-kill emulator to prevent 20+ min hang after tests
2026-02-26 13:02:38 -06:00
Pierre-Yves Ricau
9d92fecd0c Fix pkill self-match: use qemu-syste[m] pattern 2026-02-26 17:56:15 +01:00
Pierre-Yves Ricau
e89fff6bef Update changelog entry wording for ToastEventListener fix 2026-02-26 17:51:14 +01:00
Pierre-Yves Ricau
5630f9b03f Fix emulator process hanging 20+ min after CI tests finish
On API 26 google_apis, the emulator process does not exit after
receiving adb emu kill. The android-emulator-runner post-step
polls until the process dies, which never happens before the
30-minute job timeout triggers, wasting ~23 minutes of CI time.

Force-kill the qemu-system process at the end of the test script,
before the action's post-step cleanup runs. When the post-step
then checks whether the process has exited, it is already gone
and the cleanup step exits immediately.
2026-02-26 17:13:18 +01:00
Pierre-Yves Ricau
51608c24bb Add changelog entry for ToastEventListener race condition fix
Document the fix from #2802 in the Unreleased section.
2026-02-26 17:13:14 +01:00
py - Pierre Yves Ricau
aba44b21ed Merge pull request #2802 from square/py/fix-toast-leak
Fix ToastEventListener race condition that retains a finished Toast
2026-02-26 10:07:12 -06:00
pblundell
1395f93c41 Regenerate the gradle wrapper on gradle bump 2026-02-26 15:57:19 +00:00
pblundell
5a187b6566 Downgrade test orchestrator
- allow the instrumentation tests running an API 16 to pass
2026-02-26 15:54:56 +00:00
Pierre-Yves Ricau
9890f6931f Fix ToastEventListener race condition retaining finished Toast
showToastBlocking() blocks the heap dump thread (via CountDownLatch)
until onAnimationEnd fires, but only up to a 5-second timeout. If the
timeout fires before the animation completes, the heap dump proceeds and
HeapDump posts a cleanup runnable to the main thread. That cleanup runs
while toastCurrentlyShown is still null (animation not done yet), so it
is a no-op. Then onAnimationEnd fires and sets toastCurrentlyShown = toast
permanently — no subsequent event clears it, causing a memory leak.

The fix: set toastCurrentlyShown = toast immediately after toast.show(),
before starting the animation. The cleanup runnable then always sees a
non-null reference and cancels + nulls it correctly, regardless of
whether onAnimationEnd has fired yet.

The partial fix in ade42f792 (adding toastCurrentlyShown = null to the
cleanup) addressed the common case but not this timeout-driven race.

Fixes #2301
Fixes #2325

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 16:21:49 +01:00
pblundell
82d8c80642 Use the toml hash in the cache file name
- This allows a new emu to be created if dependencies are updated
- Dependencies being updated can cause signature mismatches in installed test apks
2026-02-26 14:52:19 +00:00
pblundell
dc01b261e4 Use AGP 8.2.2 for successful test report finding 2026-02-26 13:12:59 +00:00
pblundell
30f34075b9 Update the API baseline
What These Changes Mean:

  Removed Methods: getDefaultImpl() and setDefaultImpl()
  These were part of an older AIDL pattern for handling default implementations when the service isn't available. This was a fallback mechanism that's been deprecated in favor of better error handling.

  Added: DESCRIPTOR Field
  This is the standard AIDL interface descriptor string - it's always been there internally, but now it's explicitly exposed in the public API.

  Added: LeakUiApp$_Parcel Class
  This is a newer AIDL tooling artifact - modern AIDL compilers generate additional helper classes for parcelization.

  Impact Analysis:  Likely SAFE - No Breaking Changes for Clients

  Why this is probably fine:
  1. Internal APIs: These are in org.leakcanary.internal.* package - the internal namespace signals these aren't meant for public consumption
  2. AIDL Evolution: The Android AIDL compiler has been evolving to generate more modern, efficient code. The removed methods were legacy patterns.
  3. Backwards Compatible:
  - The core sendHeapAnalysis() method remains unchanged
    - The DESCRIPTOR field addition doesn't break existing clients
    - The new _Parcel class is just tooling infrastructure
  4. LeakCanary Context: This appears to be inter-process communication between LeakCanary components, not a public API for app developers
  ⚠️ Potential Concerns:
  1. If any external code was using the removed methods (unlikely since they're internal APIs)
  2. Binary compatibility for any code that was directly instantiating or reflection-accessing these classes

 What Could Have Caused This:
  1. Java 17 + newer Android Gradle Plugin - may use a newer AIDL compiler
  2. Updated compileOptions - could affect how AIDL generates code
  3. Build environment changes - newer toolchain versions
Recommendation:
  This is likely safe because:
  - It's internal LeakCanary APIs
  - The core functionality (sendHeapAnalysis) is preserved
  - This follows AIDL tooling evolution patterns

 However, you should consider:
  - Testing: Ensure LeakCanary still works properly between processes
  - Release notes: Document that internal AIDL APIs changed (if you publish these changes)
  - Monitoring: Watch for any reports of inter-process communication issues

 The changes appear to be tooling evolution rather than functional changes, but it's worth testing the actual LeakCanary functionality to be sure.
2026-02-26 13:12:59 +00:00
pblundell
85cfff6776 Fix UI test infrastructure
Updates Android instrumentation test dependencies and configuration to work with compileSdk 35 and API level 36:

- Update Gradle from 8.2 to 8.10.2
- Move from KAPT to KSP
- Update AGP to 8.2.2 and Gradle to 8.2
- Update Hilt to consistently be 2.53
- Update AndroidX Test dependencies to modern versions compatible with API 36
- Fix test namespace configuration to match actual package structure
- Move TuPeuxPasTest to correct package structure for proper test discovery
- Fixes build warnings about packagingOptions
- Add missing Java sourceCompatibility declarations
- Appease lint by suppressing the failures, we could remove the checks but they where written for a reason so keeping them

This ensures UI tests are properly discovered and executed by Gradle with correct reporting, while maintaining compatibility with newer Android APIs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-26 13:12:59 +00:00
py - Pierre Yves Ricau
f3f9207494 Merge pull request #2801 from square/worktree-fix-ci-instrumentation-tests
Fix instrumentation tests: uninstall stale APKs before connectedCheck
2026-02-26 06:25:01 -06:00
Pierre-Yves Ricau
470859b3d0 Fix instrumentation tests failing with INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
When a cached AVD snapshot has LeakCanary packages installed with different
signing certificates than the current build, Android refuses to reinstall them.
Fix by explicitly uninstalling all known LeakCanary packages before running
connectedCheck, so the fresh build APKs always install cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 13:13:00 +01:00
py - Pierre Yves Ricau
959be77f7d Merge pull request #2797 from blundell/fix-compose-inspector-main
Fix COMPOSITION_IMPL inspector for new Compose state field structure
2026-02-25 13:20:45 -06:00
pblundell
58a5c1cc67 Fix COMPOSITION_IMPL inspector for new Compose state field structure
Fixes NullPointerException when analyzing heap dumps from newer Compose versions
where CompositionImpl uses "state" int field instead of "disposed" boolean field.

The inspector now gracefully handles both field structures:
- Old Compose: disposed boolean field (backward compatibility)
- New Compose: state int field with values RUNNING=0, DISPOSED=3, etc.
- Edge case: neither field exists (graceful fallback)

Before: NullPointerException at AndroidObjectInspectors$COMPOSITION_IMPL$inspect line 792
After: Analysis completes successfully with proper state detection

Fixes: https://github.com/square/leakcanary/issues/2781

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-25 16:40:02 +00:00
py - Pierre Yves Ricau
6de01db223 Merge pull request #2788 from roberto-git0/fix-shark-compliance
Update Shark for newer Okio and Kotlin compliance
2026-02-04 04:25:21 -06:00
Roberto Stanciu
6f95ee9b6d removing okio 1.x from Gradle Version Catalog 2026-01-28 19:41:50 +02:00
Roberto Stanciu
1f33b250a6 Update Shark for newer Okio and Kotlin compliance 2026-01-20 17:04:00 +02:00
py - Pierre Yves Ricau
b9bea46f27 Merge pull request #2779 from 0legg/oleg/fits-system-windows
Enforce LeakActivity to fit system windows
2026-01-05 04:58:22 -06:00
Oleg Godovykh
1aec6dddff Enforce LeakActivity to fit system windows to avoid the content being cut on Android 15+ 2025-10-23 10:56:27 -07:00
py - Pierre Yves Ricau
22bef70ba5 Merge pull request #2772 from Amokrane/amokrane/add_motorola_to_xiami_resources_impl
Add Motorola to OEMs causing a static context leak
2025-08-04 23:43:50 -06:00
Amokrane Chentir
da99e29507 Add Motorola to OEMs causing a static context leak 2025-08-04 23:32:49 +02:00
py - Pierre Yves Ricau
83a8ad486f Merge pull request #2743 from gmazzo/fix-ci
Fixes CI (with minimal changes)
2025-03-14 14:52:49 -07:00
Guillermo Mazzola
8df729c9f1 Fixing CI (adding detekt issues to baseline) 2025-03-14 14:47:53 +01:00
jjliu15
23cd68b081 Extend API level for InputMethodManager.NextServedView in AndroidReferenceMatchers. 2025-01-14 16:52:35 -08:00
py - Pierre Yves Ricau
02d0d8b6eb Merge pull request #2697 from square/jwilson.0806.kts
Convert builds to KTS
2024-08-28 15:51:11 -07:00
Jesse Wilson
ffdf55c3a5 Actually convert 2024-08-06 16:40:25 -07:00
Jesse Wilson
540a39bfcd Rename build.gradle to build.gradle.kts 2024-08-06 16:39:08 -07:00
py - Pierre Yves Ricau
315b335fcd Merge pull request #2687 from msfjarvis/patch-1
Fix unbalanced code fences in changelog
2024-06-07 18:11:32 -07:00