Repository: square/leakcanary
File: plumber/plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt (Kotlin)

Code before:
          }
        }
        sServiceField[null] = proxyService
      } catch (ignored: Exception) {
        SharkLog.d(ignored) { "Unable to fix SpellChecker leak" }
      }
    }
  },

  /**
   * PermissionControllerManager stores the first context it's initialized with forever.
   * Sometimes it's an Activity context which then leaks after Activity is destroyed.
   *
   * This fix makes sure the PermissionControllerManager is created with the application context.
   *
   * For Pixel devices the issue can be tracked here
   * https://issuetracker.google.com/issues/318415056
   */
  PERMISSION_CONTROLLER_MANAGER {
    @SuppressLint("WrongConstant")
    override fun apply(application: Application) {
      try {
        application.getSystemService("permission_controller")
      } catch (ignored: Exception) {
        SharkLog.d(ignored) { "Unable to fix PermissionControllerManager leak" }
      }
    }
  }

  ;

  protected abstract fun apply(application: Application)

  private var applied = false

  companion object {

    private const val SAMSUNG = "samsung"
    private const val LG = "LGE"

    fun applyFixes(
      application: Application,
      fixes: Set<AndroidLeakFixes> = EnumSet.allOf(AndroidLeakFixes::class.java)
    ) {
      checkMainThread()
      fixes.forEach { fix ->
        if (!fix.applied) {
          fix.apply(application)
          fix.applied = true
        } else {
          SharkLog.d { "${fix.name} leak fix already applied." }

Review comment (security):
Should this only happen after a certain API level?

In your example repro on the google issue, you called `revokeSelfPermissionsOnKill` which is API 33+

Code after:
          }
        }
        sServiceField[null] = proxyService
      } catch (ignored: Exception) {
        SharkLog.d(ignored) { "Unable to fix SpellChecker leak" }
      }
    }
  },

  /**
   * PermissionControllerManager stores the first context it's initialized with forever.
   * Sometimes it's an Activity context which then leaks after Activity is destroyed.
   *
   * This fix makes sure the PermissionControllerManager is created with the application context.
   *
   * For Pixel devices the issue can be tracked here
   * https://issuetracker.google.com/issues/318415056
   */
  PERMISSION_CONTROLLER_MANAGER {
    @SuppressLint("WrongConstant")
    override fun apply(application: Application) {
      if (SDK_INT < 29) {
        return
      }
      try {
        application.getSystemService("permission_controller")
      } catch (ignored: Exception) {
        SharkLog.d(ignored) { "Unable to fix PermissionControllerManager leak" }
      }
    }
  }

  ;

  protected abstract fun apply(application: Application)

  private var applied = false

  companion object {

    private const val SAMSUNG = "samsung"
    private const val LG = "LGE"

    fun applyFixes(
      application: Application,
      fixes: Set<AndroidLeakFixes> = EnumSet.allOf(AndroidLeakFixes::class.java)
    ) {
      checkMainThread()
      fixes.forEach { fix ->
        if (!fix.applied) {
          fix.apply(application)