Loading core/java/android/appwidget/AppWidgetHostView.java +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Looper; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; Loading Loading @@ -1043,11 +1044,16 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW * This function returns the current set of widget event data being tracked by this widget. The * tracked data is cleared is returned here. * * This should always be called on the main thread. * * @hide */ @FlaggedApi(FLAG_ENGAGEMENT_METRICS) @Override public AppWidgetEvent collectWidgetEvent() { if (!Looper.getMainLooper().isCurrentThread()) { throw new IllegalStateException("collectWidgetEvent must be called from main thread"); } return mInteractionLogger.collectWidgetEvent(); } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManagerServiceTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -45,8 +45,10 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.doAnswer import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never Loading Loading @@ -143,7 +145,15 @@ class GlanceableHubWidgetManagerServiceTest : SysuiTestCase() { val service = IGlanceableHubWidgetManagerService.Stub.asInterface(binder) // Set listener val listener = mock<IGlanceableHubWidgetManagerService.IAppWidgetHostListener>() val listener = mock<IGlanceableHubWidgetManagerService.IAppWidgetHostListener> { on { collectWidgetEvent(any()) } doAnswer { (it.arguments[0] as IGlanceableHubWidgetManagerService.IAppWidgetEventCallback) .onResult(null) } } service.setAppWidgetHostListener(1, listener) // Verify a listener is set on the host Loading @@ -164,6 +174,9 @@ class GlanceableHubWidgetManagerServiceTest : SysuiTestCase() { appWidgetHostListener.onViewDataChanged(1) verify(listener).onViewDataChanged(1) appWidgetHostListener.collectWidgetEvent() verify(listener).collectWidgetEvent(any()) } @Test Loading packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt +19 −0 Original line number Diff line number Diff line Loading @@ -16,14 +16,17 @@ package com.android.systemui.communal.widgets import android.appwidget.AppWidgetEvent import android.appwidget.AppWidgetHost.AppWidgetHostListener import android.appwidget.AppWidgetProviderInfo import android.os.Looper import android.widget.RemoteViews import com.android.app.tracing.coroutines.launchTraced import com.android.systemui.dagger.qualifiers.Application import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.concurrent.CompletableFuture import kotlinx.coroutines.CoroutineScope /** Loading Loading @@ -55,4 +58,20 @@ constructor( override fun onViewDataChanged(viewId: Int) { mainScope.launchTraced("$tag#onViewDataChanged") { listener.onViewDataChanged(viewId) } } override fun collectWidgetEvent(): AppWidgetEvent? { if (!android.appwidget.flags.Flags.engagementMetrics()) { return null } if (Looper.getMainLooper().isCurrentThread()) { return listener.collectWidgetEvent() } val future = CompletableFuture<AppWidgetEvent?>() mainScope.launchTraced("$tag#collectWidgetEvent") { future.complete(listener.collectWidgetEvent()) } return future.get() } } packages/SystemUI/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManager.kt +5 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.server.servicewatcher.ServiceWatcher import com.android.server.servicewatcher.ServiceWatcher.ServiceListener import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.shared.model.GlanceableHubMultiUserHelper import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetEventCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetHostListener import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IConfigureWidgetCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IGlanceableHubWidgetsListener Loading Loading @@ -212,6 +213,10 @@ constructor( override fun onViewDataChanged(viewId: Int) { listener.onViewDataChanged(viewId) } override fun collectWidgetEvent(callback: IAppWidgetEventCallback) { callback.onResult(listener.collectWidgetEvent()) } } } Loading packages/SystemUI/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManagerService.kt +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.communal.widgets import android.appwidget.AppWidgetEvent import android.appwidget.AppWidgetHost.AppWidgetHostListener import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName Loading @@ -30,12 +31,14 @@ import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope import com.android.systemui.communal.data.repository.CommunalWidgetRepository import com.android.systemui.communal.shared.model.GlanceableHubMultiUserHelper import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetEventCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetHostListener import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IConfigureWidgetCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IGlanceableHubWidgetsListener import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.CommunalLog import java.util.concurrent.CompletableFuture import javax.inject.Inject import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Job Loading Loading @@ -260,6 +263,27 @@ constructor( } } } override fun collectWidgetEvent(): AppWidgetEvent? { if (!android.appwidget.flags.Flags.engagementMetrics()) return null val future = CompletableFuture<AppWidgetEvent?>() val callback = object : IAppWidgetEventCallback.Stub() { override fun onResult(event: AppWidgetEvent?) { future.complete(event) } } return try { listener.collectWidgetEvent(callback) future.get() } catch (e: RemoteException) { logger.e({ "Error collecting widget event: $str1" }) { str1 = e.localizedMessage } null } } } } Loading Loading
core/java/android/appwidget/AppWidgetHostView.java +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Looper; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; Loading Loading @@ -1043,11 +1044,16 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW * This function returns the current set of widget event data being tracked by this widget. The * tracked data is cleared is returned here. * * This should always be called on the main thread. * * @hide */ @FlaggedApi(FLAG_ENGAGEMENT_METRICS) @Override public AppWidgetEvent collectWidgetEvent() { if (!Looper.getMainLooper().isCurrentThread()) { throw new IllegalStateException("collectWidgetEvent must be called from main thread"); } return mInteractionLogger.collectWidgetEvent(); } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManagerServiceTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -45,8 +45,10 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.doAnswer import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never Loading Loading @@ -143,7 +145,15 @@ class GlanceableHubWidgetManagerServiceTest : SysuiTestCase() { val service = IGlanceableHubWidgetManagerService.Stub.asInterface(binder) // Set listener val listener = mock<IGlanceableHubWidgetManagerService.IAppWidgetHostListener>() val listener = mock<IGlanceableHubWidgetManagerService.IAppWidgetHostListener> { on { collectWidgetEvent(any()) } doAnswer { (it.arguments[0] as IGlanceableHubWidgetManagerService.IAppWidgetEventCallback) .onResult(null) } } service.setAppWidgetHostListener(1, listener) // Verify a listener is set on the host Loading @@ -164,6 +174,9 @@ class GlanceableHubWidgetManagerServiceTest : SysuiTestCase() { appWidgetHostListener.onViewDataChanged(1) verify(listener).onViewDataChanged(1) appWidgetHostListener.collectWidgetEvent() verify(listener).collectWidgetEvent(any()) } @Test Loading
packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt +19 −0 Original line number Diff line number Diff line Loading @@ -16,14 +16,17 @@ package com.android.systemui.communal.widgets import android.appwidget.AppWidgetEvent import android.appwidget.AppWidgetHost.AppWidgetHostListener import android.appwidget.AppWidgetProviderInfo import android.os.Looper import android.widget.RemoteViews import com.android.app.tracing.coroutines.launchTraced import com.android.systemui.dagger.qualifiers.Application import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.concurrent.CompletableFuture import kotlinx.coroutines.CoroutineScope /** Loading Loading @@ -55,4 +58,20 @@ constructor( override fun onViewDataChanged(viewId: Int) { mainScope.launchTraced("$tag#onViewDataChanged") { listener.onViewDataChanged(viewId) } } override fun collectWidgetEvent(): AppWidgetEvent? { if (!android.appwidget.flags.Flags.engagementMetrics()) { return null } if (Looper.getMainLooper().isCurrentThread()) { return listener.collectWidgetEvent() } val future = CompletableFuture<AppWidgetEvent?>() mainScope.launchTraced("$tag#collectWidgetEvent") { future.complete(listener.collectWidgetEvent()) } return future.get() } }
packages/SystemUI/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManager.kt +5 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.server.servicewatcher.ServiceWatcher import com.android.server.servicewatcher.ServiceWatcher.ServiceListener import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.shared.model.GlanceableHubMultiUserHelper import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetEventCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetHostListener import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IConfigureWidgetCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IGlanceableHubWidgetsListener Loading Loading @@ -212,6 +213,10 @@ constructor( override fun onViewDataChanged(viewId: Int) { listener.onViewDataChanged(viewId) } override fun collectWidgetEvent(callback: IAppWidgetEventCallback) { callback.onResult(listener.collectWidgetEvent()) } } } Loading
packages/SystemUI/src/com/android/systemui/communal/widgets/GlanceableHubWidgetManagerService.kt +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.communal.widgets import android.appwidget.AppWidgetEvent import android.appwidget.AppWidgetHost.AppWidgetHostListener import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName Loading @@ -30,12 +31,14 @@ import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope import com.android.systemui.communal.data.repository.CommunalWidgetRepository import com.android.systemui.communal.shared.model.GlanceableHubMultiUserHelper import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetEventCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IAppWidgetHostListener import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IConfigureWidgetCallback import com.android.systemui.communal.widgets.IGlanceableHubWidgetManagerService.IGlanceableHubWidgetsListener import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.CommunalLog import java.util.concurrent.CompletableFuture import javax.inject.Inject import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Job Loading Loading @@ -260,6 +263,27 @@ constructor( } } } override fun collectWidgetEvent(): AppWidgetEvent? { if (!android.appwidget.flags.Flags.engagementMetrics()) return null val future = CompletableFuture<AppWidgetEvent?>() val callback = object : IAppWidgetEventCallback.Stub() { override fun onResult(event: AppWidgetEvent?) { future.complete(event) } } return try { listener.collectWidgetEvent(callback) future.get() } catch (e: RemoteException) { logger.e({ "Error collecting widget event: $str1" }) { str1 = e.localizedMessage } null } } } } Loading