Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +11 −1 Original line number Original line Diff line number Diff line Loading @@ -325,10 +325,15 @@ class AppHandleEducationController( /** /** * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in * datastore proto object. * datastore proto object. * * If [SHOULD_OVERRIDE_EDUCATION_CONDITIONS] is true, this flow will always emit false. That means * it will emit education has not been viewed yet always. */ */ private fun isEducationViewedFlow(): Flow<Boolean> = private fun isEducationViewedFlow(): Flow<Boolean> = appHandleEducationDatastoreRepository.dataStoreFlow appHandleEducationDatastoreRepository.dataStoreFlow .map { preferences -> preferences.hasEducationViewedTimestampMillis() } .map { preferences -> preferences.hasEducationViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS } .distinctUntilChanged() .distinctUntilChanged() /** /** Loading @@ -352,5 +357,10 @@ class AppHandleEducationController( val APP_HANDLE_EDUCATION_TIMEOUT_MILLIS: Long val APP_HANDLE_EDUCATION_TIMEOUT_MILLIS: Long get() = SystemProperties.getLong("persist.windowing_app_handle_education_timeout", 400L) get() = SystemProperties.getLong("persist.windowing_app_handle_education_timeout", 400L) val SHOULD_OVERRIDE_EDUCATION_CONDITIONS: Boolean get() = SystemProperties.getBoolean( "persist.desktop_windowing_app_handle_education_override_conditions", false) } } } } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt +10 −1 Original line number Original line Diff line number Diff line Loading @@ -23,10 +23,12 @@ import android.os.SystemClock import android.provider.Settings.Secure import android.provider.Settings.Secure import com.android.wm.shell.R import com.android.wm.shell.R import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.SHOULD_OVERRIDE_EDUCATION_CONDITIONS import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.WindowingEducationProto import com.android.wm.shell.desktopmode.education.data.WindowingEducationProto import java.time.Duration import java.time.Duration @kotlinx.coroutines.ExperimentalCoroutinesApi /** Filters incoming app handle education triggers based on set conditions. */ /** Filters incoming app handle education triggers based on set conditions. */ class AppHandleEducationFilter( class AppHandleEducationFilter( private val context: Context, private val context: Context, Loading @@ -35,9 +37,16 @@ class AppHandleEducationFilter( private val usageStatsManager = private val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager /** Returns true if conditions to show app handle education are met, returns false otherwise. */ /** * Returns true if conditions to show app handle education are met, returns false otherwise. * * If [SHOULD_OVERRIDE_EDUCATION_CONDITIONS] is true, this method will always return * ![captionState.isHandleMenuExpanded]. */ suspend fun shouldShowAppHandleEducation(captionState: CaptionState): Boolean { suspend fun shouldShowAppHandleEducation(captionState: CaptionState): Boolean { if ((captionState as CaptionState.AppHandle).isHandleMenuExpanded) return false if ((captionState as CaptionState.AppHandle).isHandleMenuExpanded) return false if (SHOULD_OVERRIDE_EDUCATION_CONDITIONS) return true val focusAppPackageName = val focusAppPackageName = captionState.runningTaskInfo.topActivityInfo?.packageName ?: return false captionState.runningTaskInfo.topActivityInfo?.packageName ?: return false val windowingEducationProto = appHandleEducationDatastoreRepository.windowingEducationProto() val windowingEducationProto = appHandleEducationDatastoreRepository.windowingEducationProto() Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +30 −2 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.desktopmode.education package com.android.wm.shell.desktopmode.education import android.os.SystemProperties import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import android.platform.test.flag.junit.SetFlagsRule Loading Loading @@ -50,6 +51,7 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Rule import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Mock import org.mockito.Mock import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.any Loading @@ -70,7 +72,10 @@ class AppHandleEducationControllerTest : ShellTestCase() { @JvmField @JvmField @Rule @Rule val extendedMockitoRule = val extendedMockitoRule = ExtendedMockitoRule.Builder(this).mockStatic(DesktopModeStatus::class.java).build()!! ExtendedMockitoRule.Builder(this) .mockStatic(DesktopModeStatus::class.java) .mockStatic(SystemProperties::class.java) .build()!! @JvmField @Rule val setFlagsRule = SetFlagsRule() @JvmField @Rule val setFlagsRule = SetFlagsRule() private lateinit var educationController: AppHandleEducationController private lateinit var educationController: AppHandleEducationController Loading Loading @@ -187,6 +192,29 @@ class AppHandleEducationControllerTest : ShellTestCase() { verify(mockTooltipController, never()).showEducationTooltip(any(), any()) verify(mockTooltipController, never()).showEducationTooltip(any(), any()) } } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun overridePrerequisite_educationViewedAlready_shouldCallShowEducationTooltip() = testScope.runTest { // App handle is visible but education has been viewed before. But as we are overriding // prerequisite conditions, we should show education tooltip. // Mark education viewed. testDataStoreFlow.value = createWindowingEducationProto(educationViewedTimestampMillis = 123L) val systemPropertiesKey = "persist.desktop_windowing_app_handle_education_override_conditions" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())) .thenReturn(true) setShouldShowAppHandleEducation(true) // Simulate app handle visible. testCaptionStateFlow.value = createAppHandleState(isHandleMenuExpanded = false) // Wait for first tooltip to showup. waitForBufferDelay() verify(mockTooltipController, times(1)).showEducationTooltip(any(), any()) } @Test @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_appHandleExpanded_shouldMarkFeatureViewed() = fun init_appHandleExpanded_shouldMarkFeatureViewed() = Loading Loading @@ -454,7 +482,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { .thenReturn(shouldShowAppHandleEducation) .thenReturn(shouldShowAppHandleEducation) /** /** * Class under test waits for some seconds before showing education, simulate advance time before * Class under test waits for some time before showing education, simulate advance time before * verifying or moving forward * verifying or moving forward */ */ private fun TestScope.waitForBufferDelay() { private fun TestScope.waitForBufferDelay() { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt +31 −2 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.wm.shell.desktopmode.education import android.app.usage.UsageStats import android.app.usage.UsageStats import android.app.usage.UsageStatsManager import android.app.usage.UsageStatsManager import android.content.Context import android.content.Context import android.os.SystemProperties import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner import android.testing.TestableContext import android.testing.TestableContext import android.testing.TestableResources import android.testing.TestableResources import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.wm.shell.R import com.android.wm.shell.R import com.android.wm.shell.ShellTestCase import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository Loading @@ -35,18 +37,26 @@ import com.google.common.truth.Truth.assertThat import kotlin.Int.Companion.MAX_VALUE import kotlin.Int.Companion.MAX_VALUE import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyLong import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations import org.mockito.kotlin.eq import org.mockito.kotlin.whenever /** Tests of [AppHandleEducationFilter] /** Tests of [AppHandleEducationFilter] Usage: atest AppHandleEducationFilterTest */ * Usage: atest AppHandleEducationFilterTest */ @SmallTest @SmallTest @RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class) @kotlinx.coroutines.ExperimentalCoroutinesApi class AppHandleEducationFilterTest : ShellTestCase() { class AppHandleEducationFilterTest : ShellTestCase() { @JvmField @Rule val extendedMockitoRule = ExtendedMockitoRule.Builder(this).mockStatic(SystemProperties::class.java).build()!! @Mock private lateinit var datastoreRepository: AppHandleEducationDatastoreRepository @Mock private lateinit var datastoreRepository: AppHandleEducationDatastoreRepository @Mock private lateinit var mockUsageStatsManager: UsageStatsManager @Mock private lateinit var mockUsageStatsManager: UsageStatsManager private lateinit var educationFilter: AppHandleEducationFilter private lateinit var educationFilter: AppHandleEducationFilter Loading Loading @@ -209,4 +219,23 @@ class AppHandleEducationFilterTest : ShellTestCase() { // We should not show app handle education if app menu is expanded // We should not show app handle education if app menu is expanded assertThat(result).isFalse() assertThat(result).isFalse() } } @Test fun shouldShowAppHandleEducation_overridePrerequisite_returnsTrue() = runTest { // Simulate that gmail app has been launched twice before, minimum app launch count is 3, hence // #shouldShowAppHandleEducation should return false. But as we are overriding prerequisite // conditions, #shouldShowAppHandleEducation should return true. testableResources.addOverride(R.integer.desktop_windowing_education_min_app_launch_count, 3) val systemPropertiesKey = "persist.desktop_windowing_app_handle_education_override_conditions" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())).thenReturn(true) val windowingEducationProto = createWindowingEducationProto( appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 2), appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE) `when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto) val result = educationFilter.shouldShowAppHandleEducation(createAppHandleState()) assertThat(result).isTrue() } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +11 −1 Original line number Original line Diff line number Diff line Loading @@ -325,10 +325,15 @@ class AppHandleEducationController( /** /** * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in * datastore proto object. * datastore proto object. * * If [SHOULD_OVERRIDE_EDUCATION_CONDITIONS] is true, this flow will always emit false. That means * it will emit education has not been viewed yet always. */ */ private fun isEducationViewedFlow(): Flow<Boolean> = private fun isEducationViewedFlow(): Flow<Boolean> = appHandleEducationDatastoreRepository.dataStoreFlow appHandleEducationDatastoreRepository.dataStoreFlow .map { preferences -> preferences.hasEducationViewedTimestampMillis() } .map { preferences -> preferences.hasEducationViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS } .distinctUntilChanged() .distinctUntilChanged() /** /** Loading @@ -352,5 +357,10 @@ class AppHandleEducationController( val APP_HANDLE_EDUCATION_TIMEOUT_MILLIS: Long val APP_HANDLE_EDUCATION_TIMEOUT_MILLIS: Long get() = SystemProperties.getLong("persist.windowing_app_handle_education_timeout", 400L) get() = SystemProperties.getLong("persist.windowing_app_handle_education_timeout", 400L) val SHOULD_OVERRIDE_EDUCATION_CONDITIONS: Boolean get() = SystemProperties.getBoolean( "persist.desktop_windowing_app_handle_education_override_conditions", false) } } } }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt +10 −1 Original line number Original line Diff line number Diff line Loading @@ -23,10 +23,12 @@ import android.os.SystemClock import android.provider.Settings.Secure import android.provider.Settings.Secure import com.android.wm.shell.R import com.android.wm.shell.R import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.SHOULD_OVERRIDE_EDUCATION_CONDITIONS import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.WindowingEducationProto import com.android.wm.shell.desktopmode.education.data.WindowingEducationProto import java.time.Duration import java.time.Duration @kotlinx.coroutines.ExperimentalCoroutinesApi /** Filters incoming app handle education triggers based on set conditions. */ /** Filters incoming app handle education triggers based on set conditions. */ class AppHandleEducationFilter( class AppHandleEducationFilter( private val context: Context, private val context: Context, Loading @@ -35,9 +37,16 @@ class AppHandleEducationFilter( private val usageStatsManager = private val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager /** Returns true if conditions to show app handle education are met, returns false otherwise. */ /** * Returns true if conditions to show app handle education are met, returns false otherwise. * * If [SHOULD_OVERRIDE_EDUCATION_CONDITIONS] is true, this method will always return * ![captionState.isHandleMenuExpanded]. */ suspend fun shouldShowAppHandleEducation(captionState: CaptionState): Boolean { suspend fun shouldShowAppHandleEducation(captionState: CaptionState): Boolean { if ((captionState as CaptionState.AppHandle).isHandleMenuExpanded) return false if ((captionState as CaptionState.AppHandle).isHandleMenuExpanded) return false if (SHOULD_OVERRIDE_EDUCATION_CONDITIONS) return true val focusAppPackageName = val focusAppPackageName = captionState.runningTaskInfo.topActivityInfo?.packageName ?: return false captionState.runningTaskInfo.topActivityInfo?.packageName ?: return false val windowingEducationProto = appHandleEducationDatastoreRepository.windowingEducationProto() val windowingEducationProto = appHandleEducationDatastoreRepository.windowingEducationProto() Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +30 −2 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.desktopmode.education package com.android.wm.shell.desktopmode.education import android.os.SystemProperties import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import android.platform.test.flag.junit.SetFlagsRule Loading Loading @@ -50,6 +51,7 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Rule import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Mock import org.mockito.Mock import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.any Loading @@ -70,7 +72,10 @@ class AppHandleEducationControllerTest : ShellTestCase() { @JvmField @JvmField @Rule @Rule val extendedMockitoRule = val extendedMockitoRule = ExtendedMockitoRule.Builder(this).mockStatic(DesktopModeStatus::class.java).build()!! ExtendedMockitoRule.Builder(this) .mockStatic(DesktopModeStatus::class.java) .mockStatic(SystemProperties::class.java) .build()!! @JvmField @Rule val setFlagsRule = SetFlagsRule() @JvmField @Rule val setFlagsRule = SetFlagsRule() private lateinit var educationController: AppHandleEducationController private lateinit var educationController: AppHandleEducationController Loading Loading @@ -187,6 +192,29 @@ class AppHandleEducationControllerTest : ShellTestCase() { verify(mockTooltipController, never()).showEducationTooltip(any(), any()) verify(mockTooltipController, never()).showEducationTooltip(any(), any()) } } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun overridePrerequisite_educationViewedAlready_shouldCallShowEducationTooltip() = testScope.runTest { // App handle is visible but education has been viewed before. But as we are overriding // prerequisite conditions, we should show education tooltip. // Mark education viewed. testDataStoreFlow.value = createWindowingEducationProto(educationViewedTimestampMillis = 123L) val systemPropertiesKey = "persist.desktop_windowing_app_handle_education_override_conditions" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())) .thenReturn(true) setShouldShowAppHandleEducation(true) // Simulate app handle visible. testCaptionStateFlow.value = createAppHandleState(isHandleMenuExpanded = false) // Wait for first tooltip to showup. waitForBufferDelay() verify(mockTooltipController, times(1)).showEducationTooltip(any(), any()) } @Test @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_appHandleExpanded_shouldMarkFeatureViewed() = fun init_appHandleExpanded_shouldMarkFeatureViewed() = Loading Loading @@ -454,7 +482,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { .thenReturn(shouldShowAppHandleEducation) .thenReturn(shouldShowAppHandleEducation) /** /** * Class under test waits for some seconds before showing education, simulate advance time before * Class under test waits for some time before showing education, simulate advance time before * verifying or moving forward * verifying or moving forward */ */ private fun TestScope.waitForBufferDelay() { private fun TestScope.waitForBufferDelay() { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt +31 −2 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.wm.shell.desktopmode.education import android.app.usage.UsageStats import android.app.usage.UsageStats import android.app.usage.UsageStatsManager import android.app.usage.UsageStatsManager import android.content.Context import android.content.Context import android.os.SystemProperties import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner import android.testing.TestableContext import android.testing.TestableContext import android.testing.TestableResources import android.testing.TestableResources import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.wm.shell.R import com.android.wm.shell.R import com.android.wm.shell.ShellTestCase import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository Loading @@ -35,18 +37,26 @@ import com.google.common.truth.Truth.assertThat import kotlin.Int.Companion.MAX_VALUE import kotlin.Int.Companion.MAX_VALUE import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyLong import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations import org.mockito.kotlin.eq import org.mockito.kotlin.whenever /** Tests of [AppHandleEducationFilter] /** Tests of [AppHandleEducationFilter] Usage: atest AppHandleEducationFilterTest */ * Usage: atest AppHandleEducationFilterTest */ @SmallTest @SmallTest @RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class) @kotlinx.coroutines.ExperimentalCoroutinesApi class AppHandleEducationFilterTest : ShellTestCase() { class AppHandleEducationFilterTest : ShellTestCase() { @JvmField @Rule val extendedMockitoRule = ExtendedMockitoRule.Builder(this).mockStatic(SystemProperties::class.java).build()!! @Mock private lateinit var datastoreRepository: AppHandleEducationDatastoreRepository @Mock private lateinit var datastoreRepository: AppHandleEducationDatastoreRepository @Mock private lateinit var mockUsageStatsManager: UsageStatsManager @Mock private lateinit var mockUsageStatsManager: UsageStatsManager private lateinit var educationFilter: AppHandleEducationFilter private lateinit var educationFilter: AppHandleEducationFilter Loading Loading @@ -209,4 +219,23 @@ class AppHandleEducationFilterTest : ShellTestCase() { // We should not show app handle education if app menu is expanded // We should not show app handle education if app menu is expanded assertThat(result).isFalse() assertThat(result).isFalse() } } @Test fun shouldShowAppHandleEducation_overridePrerequisite_returnsTrue() = runTest { // Simulate that gmail app has been launched twice before, minimum app launch count is 3, hence // #shouldShowAppHandleEducation should return false. But as we are overriding prerequisite // conditions, #shouldShowAppHandleEducation should return true. testableResources.addOverride(R.integer.desktop_windowing_education_min_app_launch_count, 3) val systemPropertiesKey = "persist.desktop_windowing_app_handle_education_override_conditions" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())).thenReturn(true) val windowingEducationProto = createWindowingEducationProto( appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 2), appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE) `when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto) val result = educationFilter.shouldShowAppHandleEducation(createAppHandleState()) assertThat(result).isTrue() } } }