Repository: square/leakcanary
File: leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java (Java)

Code before:
    @Override void add(ExcludedRefs.Builder excluded) {
      // The main thread stack is ever changing so local variables aren't likely to hold references
      // for long. If this is on the shortest path, it's probably that there's a longer path with
      // a real leak.
      excluded.thread("main").alwaysExclude();
    }
  },

  LEAK_CANARY_THREAD {
    @Override void add(ExcludedRefs.Builder excluded) {
      excluded.thread(LEAK_CANARY_THREAD_NAME).alwaysExclude();
    }
  },

  EVENT_RECEIVER__MMESSAGE_QUEUE {
    @Override void add(ExcludedRefs.Builder excluded) {
      //  DisplayEventReceiver keeps a reference message queue object so that it is not GC'd while
      // the native peer of the receiver is using them.
      // The main thread message queue is held on by the main Looper, but that might be a longer
      // path. Let's not confuse people with a shorter path that is less meaningful.
      excluded.instanceField("android.view.Choreographer$FrameDisplayEventReceiver",
          "mMessageQueue").alwaysExclude();
    }
  };

  /**
   * This returns the references in the leak path that should be ignored by all on Android.
   */
  public static ExcludedRefs.Builder createAndroidDefaults() {
    return createBuilder(
        EnumSet.of(SOFT_REFERENCES, FINALIZER_WATCHDOG_DAEMON, MAIN, LEAK_CANARY_THREAD,
            EVENT_RECEIVER__MMESSAGE_QUEUE));
  }

  /**
   * This returns the references in the leak path that can be ignored for app developers. This
   * doesn't mean there is no memory leak, to the contrary. However, some leaks are caused by bugs
   * in AOSP or manufacturer forks of AOSP. In such cases, there is very little we can do as app
   * developers except by resorting to serious hacks, so we remove the noise caused by those leaks.
   */
  public static ExcludedRefs.Builder createAppDefaults() {
    return createBuilder(EnumSet.allOf(AndroidExcludedRefs.class));
  }

  public static ExcludedRefs.Builder createBuilder(EnumSet<AndroidExcludedRefs> refs) {
    ExcludedRefs.Builder excluded = ExcludedRefs.builder();
    for (AndroidExcludedRefs ref : refs) {
      if (ref.applies) {
        ref.add(excluded);
        ((ExcludedRefs.BuilderWithParams) excluded).named(ref.name());
      }

Review comment (suggestion):
- Should be `==` (P, not P+)
- Create a `P` constant for it at the top of the class


Code after:
    @Override void add(ExcludedRefs.Builder excluded) {
      // The main thread stack is ever changing so local variables aren't likely to hold references
      // for long. If this is on the shortest path, it's probably that there's a longer path with
      // a real leak.
      excluded.thread("main").alwaysExclude();
    }
  },

  LEAK_CANARY_THREAD {
    @Override void add(ExcludedRefs.Builder excluded) {
      excluded.thread(LEAK_CANARY_THREAD_NAME).alwaysExclude();
    }
  },

  EVENT_RECEIVER__MMESSAGE_QUEUE {
    @Override void add(ExcludedRefs.Builder excluded) {
      //  DisplayEventReceiver keeps a reference message queue object so that it is not GC'd while
      // the native peer of the receiver is using them.
      // The main thread message queue is held on by the main Looper, but that might be a longer
      // path. Let's not confuse people with a shorter path that is less meaningful.
      excluded.instanceField("android.view.Choreographer$FrameDisplayEventReceiver",
          "mMessageQueue").alwaysExclude();
    }
  },

  VIEWLOCATIONHOLDER_ROOT(SDK_INT >= 28) {
    @Override void add(ExcludedRefs.Builder excluded) {
      //  In Android P+, ViewLocationHolder has an mRoot field that is not cleared in its clear()
      // method.
      // Introduced in https://github.com/aosp-mirror/platform_frameworks_base/commit/86b326012813f09d8f1de7d6d26c986a909de894
      // Bug report: https://issuetracker.google.com/issues/112792715
      excluded.instanceField("android.view.ViewGroup$ViewLocationHolder",
          "mRoot").alwaysExclude();
    }
  };

  /**
   * This returns the references in the leak path that should be ignored by all on Android.
   */
  public static ExcludedRefs.Builder createAndroidDefaults() {
    return createBuilder(
        EnumSet.of(SOFT_REFERENCES, FINALIZER_WATCHDOG_DAEMON, MAIN, LEAK_CANARY_THREAD,
            EVENT_RECEIVER__MMESSAGE_QUEUE));
  }

  /**
   * This returns the references in the leak path that can be ignored for app developers. This
   * doesn't mean there is no memory leak, to the contrary. However, some leaks are caused by bugs
   * in AOSP or manufacturer forks of AOSP. In such cases, there is very little we can do as app
   * developers except by resorting to serious hacks, so we remove the noise caused by those leaks.
   */