Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/WorkSerializer.kt +15 −5 Original line number Original line Diff line number Diff line Loading @@ -26,10 +26,20 @@ import kotlinx.coroutines.channels.ChannelResult import kotlinx.coroutines.launch import kotlinx.coroutines.launch /** /** * A queue that executes coroutines sequentially in a First-In, First-Out (FIFO) order. * Serializes the execution of suspendable work, ensuring that tasks are processed * sequentially in a First-In, First-Out (FIFO) order. * * * @param scope The [CoroutineScope] the queue will use to launch its worker. Cancelling this scope * This class is useful for managing operations that need to be executed one after another, * will terminate the queue. * preventing race conditions and ensuring a predictable order of execution. It uses a * [Channel] to queue incoming work and a single worker coroutine to process the queue. * * @param scope The [CoroutineScope] the serializer will use to launch its worker coroutine. * Cancelling this scope will terminate the queue and stop all processing. * @param capacity The number of elements that can be buffered in the channel. * See [Channel] for options like [Channel.UNLIMITED], [Channel.BUFFERED], etc. * Defaults to [Channel.UNLIMITED]. * @param overflowStrategy The action to take when the buffer is full. See [BufferOverflow]. * Defaults to [BufferOverflow.SUSPEND]. */ */ class WorkSerializer( class WorkSerializer( scope: CoroutineScope, scope: CoroutineScope, Loading Loading @@ -73,7 +83,7 @@ class WorkSerializer( if (result.isFailure) { if (result.isFailure) { ProtoLog.w( ProtoLog.w( WM_SHELL, WM_SHELL, "Failed to post work to CoroutineQueue %s", "Failed to post work to WorkSerializer %s", result.exceptionOrNull()?.stackTraceToString() result.exceptionOrNull()?.stackTraceToString() ) ) } } Loading @@ -86,6 +96,6 @@ class WorkSerializer( fun close() = channel.close() fun close() = channel.close() fun onUndeliveredElement() { fun onUndeliveredElement() { ProtoLog.w(WM_SHELL, "An element in CoroutineQueue was undelivered") ProtoLog.w(WM_SHELL, "An element in WorkSerializer was undelivered") } } } } No newline at end of file libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -1437,6 +1437,7 @@ public abstract class WMShellModule { DesktopPersistentRepository desktopPersistentRepository, DesktopPersistentRepository desktopPersistentRepository, DesktopRepositoryInitializer desktopRepositoryInitializer, DesktopRepositoryInitializer desktopRepositoryInitializer, @ShellMainThread CoroutineScope mainScope, @ShellMainThread CoroutineScope mainScope, @ShellBackgroundThread CoroutineScope bgScope, UserManager userManager, UserManager userManager, DesktopState desktopState, DesktopState desktopState, DesktopConfig desktopConfig DesktopConfig desktopConfig Loading @@ -1444,7 +1445,7 @@ public abstract class WMShellModule { return new DesktopUserRepositories(shellInit, shellController, return new DesktopUserRepositories(shellInit, shellController, desktopPersistentRepository, desktopPersistentRepository, desktopRepositoryInitializer, desktopRepositoryInitializer, mainScope, userManager, desktopState, desktopConfig); mainScope, bgScope, userManager, desktopState, desktopConfig); } } @WMSingleton @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ class DesktopUserRepositories( private val persistentRepository: DesktopPersistentRepository, private val persistentRepository: DesktopPersistentRepository, private val repositoryInitializer: DesktopRepositoryInitializer, private val repositoryInitializer: DesktopRepositoryInitializer, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val bgCoroutineScope: CoroutineScope, private val userManager: UserManager, private val userManager: UserManager, desktopState: DesktopState, desktopState: DesktopState, desktopConfig: DesktopConfig, desktopConfig: DesktopConfig, Loading @@ -65,6 +66,7 @@ class DesktopUserRepositories( ?: DesktopRepository( ?: DesktopRepository( persistentRepository, persistentRepository, mainCoroutineScope, mainCoroutineScope, bgCoroutineScope, userId, userId, desktopConfig, desktopConfig, ) ) Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/DesktopRepository.kt +6 −1 Original line number Original line Diff line number Diff line Loading @@ -30,9 +30,11 @@ import androidx.core.util.forEach import androidx.core.util.valueIterator import androidx.core.util.valueIterator import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.wm.shell.common.WorkSerializer import com.android.wm.shell.desktopmode.DisplayDeskState import com.android.wm.shell.desktopmode.DisplayDeskState import com.android.wm.shell.desktopmode.data.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.data.persistence.DesktopPersistentRepository import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopConfig import com.android.wm.shell.shared.desktopmode.DesktopConfig import java.io.PrintWriter import java.io.PrintWriter Loading @@ -45,6 +47,7 @@ import kotlinx.coroutines.launch class DesktopRepository( class DesktopRepository( private val persistentRepository: DesktopPersistentRepository, private val persistentRepository: DesktopPersistentRepository, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellBackgroundThread private val bgCoroutineScope: CoroutineScope, val userId: Int, val userId: Int, val desktopConfig: DesktopConfig, val desktopConfig: DesktopConfig, ) { ) { Loading @@ -62,6 +65,8 @@ class DesktopRepository( private val activeTasksListeners = ArraySet<ActiveTasksListener>() private val activeTasksListeners = ArraySet<ActiveTasksListener>() private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>() private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>() private val persistentUpdateQueue = WorkSerializer(bgCoroutineScope) /* Tracks corner/caption regions of desktop tasks, used to determine gesture exclusion. */ /* Tracks corner/caption regions of desktop tasks, used to determine gesture exclusion. */ private val desktopExclusionRegions = SparseArray<Region>() private val desktopExclusionRegions = SparseArray<Region>() Loading Loading @@ -1172,7 +1177,7 @@ class DesktopRepository( return return } } if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { mainCoroutineScope.launch { persistentUpdateQueue.post { try { try { logD("updatePersistentRepository user=%d display=%d", userId, displayId) logD("updatePersistentRepository user=%d display=%d", userId, displayId) persistentRepository.addOrUpdateRepository(userId, desks) persistentRepository.addOrUpdateRepository(userId, desks) Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.setMain import kotlinx.coroutines.test.setMain import org.junit.After import org.junit.After import org.junit.Before import org.junit.Before Loading Loading @@ -127,6 +128,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { persistentRepository, persistentRepository, repositoryInitializer, repositoryInitializer, testScope, testScope, TestScope(), userManager, userManager, desktopState, desktopState, desktopConfig, desktopConfig, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/WorkSerializer.kt +15 −5 Original line number Original line Diff line number Diff line Loading @@ -26,10 +26,20 @@ import kotlinx.coroutines.channels.ChannelResult import kotlinx.coroutines.launch import kotlinx.coroutines.launch /** /** * A queue that executes coroutines sequentially in a First-In, First-Out (FIFO) order. * Serializes the execution of suspendable work, ensuring that tasks are processed * sequentially in a First-In, First-Out (FIFO) order. * * * @param scope The [CoroutineScope] the queue will use to launch its worker. Cancelling this scope * This class is useful for managing operations that need to be executed one after another, * will terminate the queue. * preventing race conditions and ensuring a predictable order of execution. It uses a * [Channel] to queue incoming work and a single worker coroutine to process the queue. * * @param scope The [CoroutineScope] the serializer will use to launch its worker coroutine. * Cancelling this scope will terminate the queue and stop all processing. * @param capacity The number of elements that can be buffered in the channel. * See [Channel] for options like [Channel.UNLIMITED], [Channel.BUFFERED], etc. * Defaults to [Channel.UNLIMITED]. * @param overflowStrategy The action to take when the buffer is full. See [BufferOverflow]. * Defaults to [BufferOverflow.SUSPEND]. */ */ class WorkSerializer( class WorkSerializer( scope: CoroutineScope, scope: CoroutineScope, Loading Loading @@ -73,7 +83,7 @@ class WorkSerializer( if (result.isFailure) { if (result.isFailure) { ProtoLog.w( ProtoLog.w( WM_SHELL, WM_SHELL, "Failed to post work to CoroutineQueue %s", "Failed to post work to WorkSerializer %s", result.exceptionOrNull()?.stackTraceToString() result.exceptionOrNull()?.stackTraceToString() ) ) } } Loading @@ -86,6 +96,6 @@ class WorkSerializer( fun close() = channel.close() fun close() = channel.close() fun onUndeliveredElement() { fun onUndeliveredElement() { ProtoLog.w(WM_SHELL, "An element in CoroutineQueue was undelivered") ProtoLog.w(WM_SHELL, "An element in WorkSerializer was undelivered") } } } } No newline at end of file
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -1437,6 +1437,7 @@ public abstract class WMShellModule { DesktopPersistentRepository desktopPersistentRepository, DesktopPersistentRepository desktopPersistentRepository, DesktopRepositoryInitializer desktopRepositoryInitializer, DesktopRepositoryInitializer desktopRepositoryInitializer, @ShellMainThread CoroutineScope mainScope, @ShellMainThread CoroutineScope mainScope, @ShellBackgroundThread CoroutineScope bgScope, UserManager userManager, UserManager userManager, DesktopState desktopState, DesktopState desktopState, DesktopConfig desktopConfig DesktopConfig desktopConfig Loading @@ -1444,7 +1445,7 @@ public abstract class WMShellModule { return new DesktopUserRepositories(shellInit, shellController, return new DesktopUserRepositories(shellInit, shellController, desktopPersistentRepository, desktopPersistentRepository, desktopRepositoryInitializer, desktopRepositoryInitializer, mainScope, userManager, desktopState, desktopConfig); mainScope, bgScope, userManager, desktopState, desktopConfig); } } @WMSingleton @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ class DesktopUserRepositories( private val persistentRepository: DesktopPersistentRepository, private val persistentRepository: DesktopPersistentRepository, private val repositoryInitializer: DesktopRepositoryInitializer, private val repositoryInitializer: DesktopRepositoryInitializer, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val bgCoroutineScope: CoroutineScope, private val userManager: UserManager, private val userManager: UserManager, desktopState: DesktopState, desktopState: DesktopState, desktopConfig: DesktopConfig, desktopConfig: DesktopConfig, Loading @@ -65,6 +66,7 @@ class DesktopUserRepositories( ?: DesktopRepository( ?: DesktopRepository( persistentRepository, persistentRepository, mainCoroutineScope, mainCoroutineScope, bgCoroutineScope, userId, userId, desktopConfig, desktopConfig, ) ) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/DesktopRepository.kt +6 −1 Original line number Original line Diff line number Diff line Loading @@ -30,9 +30,11 @@ import androidx.core.util.forEach import androidx.core.util.valueIterator import androidx.core.util.valueIterator import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.wm.shell.common.WorkSerializer import com.android.wm.shell.desktopmode.DisplayDeskState import com.android.wm.shell.desktopmode.DisplayDeskState import com.android.wm.shell.desktopmode.data.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.data.persistence.DesktopPersistentRepository import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopConfig import com.android.wm.shell.shared.desktopmode.DesktopConfig import java.io.PrintWriter import java.io.PrintWriter Loading @@ -45,6 +47,7 @@ import kotlinx.coroutines.launch class DesktopRepository( class DesktopRepository( private val persistentRepository: DesktopPersistentRepository, private val persistentRepository: DesktopPersistentRepository, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellMainThread private val mainCoroutineScope: CoroutineScope, @ShellBackgroundThread private val bgCoroutineScope: CoroutineScope, val userId: Int, val userId: Int, val desktopConfig: DesktopConfig, val desktopConfig: DesktopConfig, ) { ) { Loading @@ -62,6 +65,8 @@ class DesktopRepository( private val activeTasksListeners = ArraySet<ActiveTasksListener>() private val activeTasksListeners = ArraySet<ActiveTasksListener>() private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>() private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>() private val persistentUpdateQueue = WorkSerializer(bgCoroutineScope) /* Tracks corner/caption regions of desktop tasks, used to determine gesture exclusion. */ /* Tracks corner/caption regions of desktop tasks, used to determine gesture exclusion. */ private val desktopExclusionRegions = SparseArray<Region>() private val desktopExclusionRegions = SparseArray<Region>() Loading Loading @@ -1172,7 +1177,7 @@ class DesktopRepository( return return } } if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { mainCoroutineScope.launch { persistentUpdateQueue.post { try { try { logD("updatePersistentRepository user=%d display=%d", userId, displayId) logD("updatePersistentRepository user=%d display=%d", userId, displayId) persistentRepository.addOrUpdateRepository(userId, desks) persistentRepository.addOrUpdateRepository(userId, desks) Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.setMain import kotlinx.coroutines.test.setMain import org.junit.After import org.junit.After import org.junit.Before import org.junit.Before Loading Loading @@ -127,6 +128,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { persistentRepository, persistentRepository, repositoryInitializer, repositoryInitializer, testScope, testScope, TestScope(), userManager, userManager, desktopState, desktopState, desktopConfig, desktopConfig, Loading