summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto14
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt29
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt12
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt12
8 files changed, 79 insertions, 66 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
index e01c448be8e5..de9c79ab34fd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
@@ -82,9 +82,9 @@ class AppHandleEducationController(
runIfEducationFeatureEnabled {
applicationCoroutineScope.launch {
// Central block handling the app handle's educational flow end-to-end.
- isEducationViewedFlow()
- .flatMapLatest { isEducationViewed ->
- if (isEducationViewed) {
+ isAppHandleHintViewedFlow()
+ .flatMapLatest { isAppHandleHintViewed ->
+ if (isAppHandleHintViewed) {
// If the education is viewed then return emptyFlow() that completes immediately.
// This will help us to not listen to [captionHandleStateFlow] after the education
// has been viewed already.
@@ -106,12 +106,12 @@ class AppHandleEducationController(
showEducation(captionState, tooltipColorScheme)
// After showing first tooltip, mark education as viewed
- appHandleEducationDatastoreRepository.updateEducationViewedTimestampMillis(true)
+ appHandleEducationDatastoreRepository.updateAppHandleHintViewedTimestampMillis(true)
}
}
applicationCoroutineScope.launch {
- if (isFeatureUsed()) return@launch
+ if (isAppHandleHintUsed()) return@launch
windowDecorCaptionHandleRepository.captionStateFlow
.filter { captionState ->
captionState is CaptionState.AppHandle && captionState.isHandleMenuExpanded
@@ -119,8 +119,8 @@ class AppHandleEducationController(
.take(1)
.flowOn(backgroundDispatcher)
.collect {
- // If user expands app handle, mark user has used the feature
- appHandleEducationDatastoreRepository.updateFeatureUsedTimestampMillis(true)
+ // If user expands app handle, mark user has used the app handle hint
+ appHandleEducationDatastoreRepository.updateAppHandleHintUsedTimestampMillis(true)
}
}
}
@@ -323,25 +323,25 @@ class AppHandleEducationController(
}
/**
- * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in
+ * Listens to the changes to [WindowingEducationProto#hasAppHandleHintViewedTimestampMillis()] in
* 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.
+ * it will always emit app handle hint has not been viewed yet.
*/
- private fun isEducationViewedFlow(): Flow<Boolean> =
+ private fun isAppHandleHintViewedFlow(): Flow<Boolean> =
appHandleEducationDatastoreRepository.dataStoreFlow
.map { preferences ->
- preferences.hasEducationViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS
+ preferences.hasAppHandleHintViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS
}
.distinctUntilChanged()
/**
- * Listens to the changes to [WindowingEducationProto#hasFeatureUsedTimestampMillis()] in
+ * Listens to the changes to [WindowingEducationProto#hasAppHandleHintUsedTimestampMillis()] in
* datastore proto object.
*/
- private suspend fun isFeatureUsed(): Boolean =
- appHandleEducationDatastoreRepository.dataStoreFlow.first().hasFeatureUsedTimestampMillis()
+ private suspend fun isAppHandleHintUsed(): Boolean =
+ appHandleEducationDatastoreRepository.dataStoreFlow.first().hasAppHandleHintUsedTimestampMillis()
private fun getSize(@DimenRes resourceId: Int): Int {
if (resourceId == Resources.ID_NULL) return 0
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt
index 144370d76060..7a7829334fb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt
@@ -54,8 +54,8 @@ class AppHandleEducationFilter(
return isFocusAppInAllowlist(focusAppPackageName) &&
!isOtherEducationShowing() &&
hasSufficientTimeSinceSetup() &&
- !isEducationViewedBefore(windowingEducationProto) &&
- !isFeatureUsedBefore(windowingEducationProto) &&
+ !isAppHandleHintViewedBefore(windowingEducationProto) &&
+ !isAppHandleHintUsedBefore(windowingEducationProto) &&
hasMinAppUsage(windowingEducationProto, focusAppPackageName)
}
@@ -76,11 +76,11 @@ class AppHandleEducationFilter(
convertIntegerResourceToDuration(
R.integer.desktop_windowing_education_required_time_since_setup_seconds)
- private fun isEducationViewedBefore(windowingEducationProto: WindowingEducationProto): Boolean =
- windowingEducationProto.hasEducationViewedTimestampMillis()
+ private fun isAppHandleHintViewedBefore(windowingEducationProto: WindowingEducationProto): Boolean =
+ windowingEducationProto.hasAppHandleHintViewedTimestampMillis()
- private fun isFeatureUsedBefore(windowingEducationProto: WindowingEducationProto): Boolean =
- windowingEducationProto.hasFeatureUsedTimestampMillis()
+ private fun isAppHandleHintUsedBefore(windowingEducationProto: WindowingEducationProto): Boolean =
+ windowingEducationProto.hasAppHandleHintUsedTimestampMillis()
private suspend fun hasMinAppUsage(
windowingEducationProto: WindowingEducationProto,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt
index d21b208df482..5e0c0007e2eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt
@@ -71,32 +71,34 @@ constructor(private val dataStore: DataStore<WindowingEducationProto>) {
suspend fun windowingEducationProto(): WindowingEducationProto = dataStoreFlow.first()
/**
- * Updates [WindowingEducationProto.educationViewedTimestampMillis_] field in datastore with
- * current timestamp if [isViewed] is true, if not then clears the field.
+ * Updates [WindowingEducationProto.appHandleHintViewedTimestampMillis_] field
+ * in datastore with current timestamp if [isViewed] is true, if not then
+ * clears the field.
*/
- suspend fun updateEducationViewedTimestampMillis(isViewed: Boolean) {
+ suspend fun updateAppHandleHintViewedTimestampMillis(isViewed: Boolean) {
dataStore.updateData { preferences ->
if (isViewed) {
preferences
.toBuilder()
- .setEducationViewedTimestampMillis(System.currentTimeMillis())
+ .setAppHandleHintViewedTimestampMillis(System.currentTimeMillis())
.build()
} else {
- preferences.toBuilder().clearEducationViewedTimestampMillis().build()
+ preferences.toBuilder().clearAppHandleHintViewedTimestampMillis().build()
}
}
}
/**
- * Updates [WindowingEducationProto.featureUsedTimestampMillis_] field in datastore with current
- * timestamp if [isViewed] is true, if not then clears the field.
+ * Updates [WindowingEducationProto.appHandleHintUsedTimestampMillis_] field
+ * in datastore with current timestamp if [isViewed] is true, if not then
+ * clears the field.
*/
- suspend fun updateFeatureUsedTimestampMillis(isViewed: Boolean) {
+ suspend fun updateAppHandleHintUsedTimestampMillis(isViewed: Boolean) {
dataStore.updateData { preferences ->
if (isViewed) {
- preferences.toBuilder().setFeatureUsedTimestampMillis(System.currentTimeMillis()).build()
+ preferences.toBuilder().setAppHandleHintUsedTimestampMillis(System.currentTimeMillis()).build()
} else {
- preferences.toBuilder().clearFeatureUsedTimestampMillis().build()
+ preferences.toBuilder().clearAppHandleHintUsedTimestampMillis().build()
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto
index 4cddd01ee96b..0c4d562b8d55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto
@@ -22,9 +22,19 @@ option java_multiple_files = true;
// Desktop Windowing education data
message WindowingEducationProto {
// Timestamp in milliseconds of when the education was last viewed.
- optional int64 education_viewed_timestamp_millis = 1;
+ optional int64 education_viewed_timestamp_millis = 1 [deprecated=true];
// Timestamp in milliseconds of when the feature was last used.
- optional int64 feature_used_timestamp_millis = 2;
+ optional int64 feature_used_timestamp_millis = 2 [deprecated=true];
+
+ // Timestamp in milliseconds of when the app handle hint was last viewed.
+ optional int64 app_handle_hint_viewed_timestamp_millis = 5;
+ // Timestamp in milliseconds of when the app handle hint was last used.
+ optional int64 app_handle_hint_used_timestamp_millis = 6;
+ // Timestamp in milliseconds of when the enter desktop mode hint was last viewed.
+ optional int64 enter_desktop_mode_hint_viewed_timestamp_millis = 7;
+ // Timestamp in milliseconds of when the exit desktop mode hint was last viewed.
+ optional int64 exit_desktop_mode_hint_viewed_timestamp_millis = 8;
+
oneof education_data {
// Fields specific to app handle education
AppHandleEducation app_handle_education = 3;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
index d94186c8284e..9c00c0cee8b1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
@@ -175,13 +175,13 @@ class AppHandleEducationControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
- fun init_educationViewedAlready_shouldNotCallShowEducationTooltip() =
+ fun init_appHandleHintViewedAlready_shouldNotCallShowEducationTooltip() =
testScope.runTest {
- // App handle is visible but education has been viewed before. Should not show education
- // tooltip.
- // Mark education viewed.
+ // App handle is visible but app handle hint has been viewed before,
+ // should not show education tooltip.
+ // Mark app handle hint viewed.
testDataStoreFlow.value =
- createWindowingEducationProto(educationViewedTimestampMillis = 123L)
+ createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L)
setShouldShowAppHandleEducation(true)
// Simulate app handle visible.
@@ -194,13 +194,14 @@ class AppHandleEducationControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
- fun overridePrerequisite_educationViewedAlready_shouldCallShowEducationTooltip() =
+ fun overridePrerequisite_appHandleHintViewedAlready_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.
+ // App handle is visible but app handle hint has been viewed before.
+ // But as we are overriding prerequisite conditions, we should show app
+ // handle tooltip.
+ // Mark app handle hint viewed.
testDataStoreFlow.value =
- createWindowingEducationProto(educationViewedTimestampMillis = 123L)
+ createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L)
val systemPropertiesKey =
"persist.desktop_windowing_app_handle_education_override_conditions"
whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean()))
@@ -217,7 +218,7 @@ class AppHandleEducationControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
- fun init_appHandleExpanded_shouldMarkFeatureViewed() =
+ fun init_appHandleExpanded_shouldMarkAppHandleHintUsed() =
testScope.runTest {
setShouldShowAppHandleEducation(false)
@@ -226,12 +227,12 @@ class AppHandleEducationControllerTest : ShellTestCase() {
// Wait for some time before verifying
waitForBufferDelay()
- verify(mockDataStoreRepository, times(1)).updateFeatureUsedTimestampMillis(eq(true))
+ verify(mockDataStoreRepository, times(1)).updateAppHandleHintUsedTimestampMillis(eq(true))
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
- fun init_showFirstTooltip_shouldMarkEducationViewed() =
+ fun init_showFirstTooltip_shouldMarkAppHandleHintViewed() =
testScope.runTest {
// App handle is visible. Should show education tooltip.
setShouldShowAppHandleEducation(true)
@@ -241,7 +242,7 @@ class AppHandleEducationControllerTest : ShellTestCase() {
// Wait for first tooltip to showup.
waitForBufferDelay()
- verify(mockDataStoreRepository, times(1)).updateEducationViewedTimestampMillis(eq(true))
+ verify(mockDataStoreRepository, times(1)).updateAppHandleHintViewedTimestampMillis(eq(true))
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt
index c2865441d7a6..963890d1caa4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt
@@ -81,8 +81,8 @@ class AppHandleEducationDatastoreRepositoryTest {
runTest(StandardTestDispatcher()) {
val windowingEducationProto =
createWindowingEducationProto(
- educationViewedTimestampMillis = 123L,
- featureUsedTimestampMillis = 124L,
+ appHandleHintViewedTimestampMillis = 123L,
+ appHandleHintUsedTimestampMillis = 124L,
appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 2),
appUsageStatsLastUpdateTimestampMillis = 125L)
testDatastore.updateData { windowingEducationProto }
@@ -110,20 +110,20 @@ class AppHandleEducationDatastoreRepositoryTest {
}
@Test
- fun updateEducationViewedTimestampMillis_updatesDatastoreProto() =
+ fun updateAppHandleHintViewedTimestampMillis_updatesDatastoreProto() =
runTest(StandardTestDispatcher()) {
- datastoreRepository.updateEducationViewedTimestampMillis(true)
+ datastoreRepository.updateAppHandleHintViewedTimestampMillis(true)
- val result = testDatastore.data.first().hasEducationViewedTimestampMillis()
+ val result = testDatastore.data.first().hasAppHandleHintViewedTimestampMillis()
assertThat(result).isEqualTo(true)
}
@Test
- fun updateFeatureUsedTimestampMillis_updatesDatastoreProto() =
+ fun updateAppHandleHintUsedTimestampMillis_updatesDatastoreProto() =
runTest(StandardTestDispatcher()) {
- datastoreRepository.updateFeatureUsedTimestampMillis(true)
+ datastoreRepository.updateAppHandleHintUsedTimestampMillis(true)
- val result = testDatastore.data.first().hasFeatureUsedTimestampMillis()
+ val result = testDatastore.data.first().hasAppHandleHintUsedTimestampMillis()
assertThat(result).isEqualTo(true)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt
index a3e74e8aed5d..e5edd69155b5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt
@@ -134,12 +134,12 @@ class AppHandleEducationFilterTest : ShellTestCase() {
}
@Test
- fun shouldShowAppHandleEducation_educationViewedBefore_returnsFalse() = runTest {
- // Education has been viewed before, hence #shouldShowAppHandleEducation should return false
+ fun shouldShowAppHandleEducation_appHandleHintViewedBefore_returnsFalse() = runTest {
+ // App handle hint has been viewed before, hence #shouldShowAppHandleEducation should return false
val windowingEducationProto =
createWindowingEducationProto(
appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 4),
- educationViewedTimestampMillis = 123L,
+ appHandleHintViewedTimestampMillis = 123L,
appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE)
`when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto)
@@ -149,12 +149,12 @@ class AppHandleEducationFilterTest : ShellTestCase() {
}
@Test
- fun shouldShowAppHandleEducation_featureUsedBefore_returnsFalse() = runTest {
- // Feature has been used before, hence #shouldShowAppHandleEducation should return false
+ fun shouldShowAppHandleEducation_appHandleHintUsedBefore_returnsFalse() = runTest {
+ // App handle hint has been used before, hence #shouldShowAppHandleEducation should return false
val windowingEducationProto =
createWindowingEducationProto(
appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 4),
- featureUsedTimestampMillis = 123L,
+ appHandleHintUsedTimestampMillis = 123L,
appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE)
`when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt
index 99e82959fcd6..b9d91e7895db 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt
@@ -78,18 +78,18 @@ fun createTaskInfo(
* Any fields without corresponding parameters will retain their default values.
*/
fun createWindowingEducationProto(
- educationViewedTimestampMillis: Long? = null,
- featureUsedTimestampMillis: Long? = null,
+ appHandleHintViewedTimestampMillis: Long? = null,
+ appHandleHintUsedTimestampMillis: Long? = null,
appUsageStats: Map<String, Int>? = null,
appUsageStatsLastUpdateTimestampMillis: Long? = null
): WindowingEducationProto =
WindowingEducationProto.newBuilder()
.apply {
- if (educationViewedTimestampMillis != null) {
- setEducationViewedTimestampMillis(educationViewedTimestampMillis)
+ if (appHandleHintViewedTimestampMillis != null) {
+ setAppHandleHintViewedTimestampMillis(appHandleHintViewedTimestampMillis)
}
- if (featureUsedTimestampMillis != null) {
- setFeatureUsedTimestampMillis(featureUsedTimestampMillis)
+ if (appHandleHintUsedTimestampMillis != null) {
+ setAppHandleHintUsedTimestampMillis(appHandleHintUsedTimestampMillis)
}
setAppHandleEducation(
createAppHandleEducationProto(appUsageStats, appUsageStatsLastUpdateTimestampMillis))