Fixed leaks of WatchFaceControlService from headless clients
Bug: 254393038
Test: Manual testing with android studio profiler, I observed WatchFaceControlService being retained after editing and this went away after the fix
Change-Id: Ifd7ea931a4ac1ca6981bee00bb9c10399d06998e
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
index 11ef49f..b41c16a 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
@@ -58,7 +58,7 @@
@VisibleForTesting
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public open class WatchFaceControlService : Service() {
- private val watchFaceInstanceServiceStub by lazy { createServiceStub() }
+ private var watchFaceInstanceServiceStub: IWatchFaceInstanceServiceStub? = null
/** @hide */
public companion object {
@@ -69,6 +69,9 @@
override fun onBind(intent: Intent?): IBinder? =
TraceEvent("WatchFaceControlService.onBind").use {
if (ACTION_WATCHFACE_CONTROL_SERVICE == intent?.action) {
+ if (watchFaceInstanceServiceStub == null) {
+ watchFaceInstanceServiceStub = createServiceStub()
+ }
watchFaceInstanceServiceStub
} else {
null
@@ -94,13 +97,19 @@
HeadlessWatchFaceImpl.dump(indentingPrintWriter)
indentingPrintWriter.flush()
}
+
+ override fun onDestroy() {
+ super.onDestroy()
+ watchFaceInstanceServiceStub?.onDestroy()
+ }
}
/** @hide */
@RequiresApi(27)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public open class IWatchFaceInstanceServiceStub(
- private val service: Service,
+ // We need to explicitly null this object in onDestroy to avoid a memory leak.
+ private var service: Service?,
private val uiThreadCoroutineScope: CoroutineScope
) : IWatchFaceControlService.Stub() {
override fun getApiVersion(): Int = IWatchFaceControlService.API_VERSION
@@ -169,11 +178,11 @@
method!!.isAccessible = true
method.invoke(
watchFaceService,
- service as Context,
+ service!! as Context,
null,
watchFaceService::class.qualifiedName,
null,
- service.application,
+ service!!.application,
null
)
} catch (e: Exception) {
@@ -280,4 +289,8 @@
throw e
}
}
+
+ fun onDestroy() {
+ service = null
+ }
}