Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +18 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ import com.android.wm.shell.desktopmode.education.AppHandleEducationController; import com.android.wm.shell.desktopmode.education.AppHandleEducationFilter; import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository; import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository; import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer; import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializerImpl; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.draganddrop.GlobalDragListener; import com.android.wm.shell.freeform.FreeformComponents; Loading Loading @@ -909,8 +911,12 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, DesktopPersistentRepository desktopPersistentRepository, @ShellMainThread CoroutineScope mainScope) { return new DesktopRepository(context, shellInit, desktopPersistentRepository, mainScope); DesktopRepositoryInitializer desktopRepositoryInitializer, @ShellMainThread CoroutineScope mainScope ) { return new DesktopRepository(context, shellInit, desktopPersistentRepository, desktopRepositoryInitializer, mainScope); } @WMSingleton Loading Loading @@ -1057,6 +1063,16 @@ public abstract class WMShellModule { return new DesktopPersistentRepository(context, bgScope); } @WMSingleton @Provides static DesktopRepositoryInitializer provideDesktopRepositoryInitializer( Context context, DesktopPersistentRepository desktopPersistentRepository, @ShellMainThread CoroutineScope mainScope) { return new DesktopRepositoryInitializerImpl(context, desktopPersistentRepository, mainScope); } // // Drag and drop // Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +3 −27 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ import androidx.core.util.valueIterator import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopTaskState import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus Loading @@ -46,6 +46,7 @@ class DesktopRepository ( private val context: Context, shellInit: ShellInit, private val persistentRepository: DesktopPersistentRepository, private val repositoryInitializer: DesktopRepositoryInitializer, @ShellMainThread private val mainCoroutineScope: CoroutineScope, ){ Loading Loading @@ -120,32 +121,7 @@ class DesktopRepository ( } private fun initRepoFromPersistentStorage() { if (!Flags.enableDesktopWindowingPersistence()) return // TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized mainCoroutineScope.launch { val desktop = persistentRepository.readDesktop() ?: return@launch val maxTasks = DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 } ?: desktop.zOrderedTasksCount var visibleTasksCount = 0 desktop.zOrderedTasksList // Reverse it so we initialize the repo from bottom to top. .reversed() .mapNotNull { taskId -> desktop.tasksByTaskIdMap[taskId] } .forEach { task -> if (task.desktopTaskState == DesktopTaskState.VISIBLE && visibleTasksCount < maxTasks ) { visibleTasksCount++ addTask(desktop.displayId, task.taskId, isVisible = false) } else { addTask(desktop.displayId, task.taskId, isVisible = false) minimizeTask(desktop.displayId, task.taskId) } } } repositoryInitializer.initialize(this) } /** Adds [activeTasksListener] to be notified of updates to active tasks. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode.persistence import com.android.wm.shell.desktopmode.DesktopRepository /** Interface for initializing the [DesktopRepository]. */ fun interface DesktopRepositoryInitializer { fun initialize(repository: DesktopRepository) } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode.persistence import android.content.Context import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch /** * Initializes the [DesktopRepository] from the [DesktopPersistentRepository]. * * This class is responsible for reading the [DesktopPersistentRepository] and initializing the * [DesktopRepository] with the tasks that previously existed in desktop. */ class DesktopRepositoryInitializerImpl( private val context: Context, private val persistentRepository: DesktopPersistentRepository, @ShellMainThread private val mainCoroutineScope: CoroutineScope, ) : DesktopRepositoryInitializer { override fun initialize(repository: DesktopRepository) { if (!Flags.enableDesktopWindowingPersistence()) return // TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized mainCoroutineScope.launch { val desktop = persistentRepository.readDesktop() ?: return@launch val maxTasks = DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 } ?: desktop.zOrderedTasksCount var visibleTasksCount = 0 desktop.zOrderedTasksList // Reverse it so we initialize the repo from bottom to top. .reversed() .mapNotNull { taskId -> desktop.tasksByTaskIdMap[taskId] } .forEach { task -> if (task.desktopTaskState == DesktopTaskState.VISIBLE && visibleTasksCount < maxTasks ) { visibleTasksCount++ repository.addTask(desktop.displayId, task.taskId, isVisible = false) } else { repository.addTask(desktop.displayId, task.taskId, isVisible = false) repository.minimizeTask(desktop.displayId, task.taskId) } } } } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +10 −2 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreef import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.persistence.Desktop import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions Loading @@ -50,10 +51,10 @@ import junit.framework.Assert.assertEquals import junit.framework.Assert.assertTrue import kotlin.test.assertNotNull import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.setMain Loading Loading @@ -94,6 +95,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { @Mock lateinit var resizeTransitionHandler: ToggleResizeDesktopTaskTransitionHandler @Mock lateinit var taskStackListener: TaskStackListenerImpl @Mock lateinit var persistentRepository: DesktopPersistentRepository @Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer private lateinit var mockitoSession: StaticMockitoSession private lateinit var handler: DesktopActivityOrientationChangeHandler Loading @@ -116,7 +118,13 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) shellInit = spy(ShellInit(testExecutor)) taskRepository = DesktopRepository(context, shellInit, persistentRepository, testScope) DesktopRepository( context, shellInit, persistentRepository, repositoryInitializer, testScope ) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } whenever(runBlocking { persistentRepository.readDesktop(any(), any()) }).thenReturn( Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +18 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ import com.android.wm.shell.desktopmode.education.AppHandleEducationController; import com.android.wm.shell.desktopmode.education.AppHandleEducationFilter; import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository; import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository; import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer; import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializerImpl; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.draganddrop.GlobalDragListener; import com.android.wm.shell.freeform.FreeformComponents; Loading Loading @@ -909,8 +911,12 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, DesktopPersistentRepository desktopPersistentRepository, @ShellMainThread CoroutineScope mainScope) { return new DesktopRepository(context, shellInit, desktopPersistentRepository, mainScope); DesktopRepositoryInitializer desktopRepositoryInitializer, @ShellMainThread CoroutineScope mainScope ) { return new DesktopRepository(context, shellInit, desktopPersistentRepository, desktopRepositoryInitializer, mainScope); } @WMSingleton Loading Loading @@ -1057,6 +1063,16 @@ public abstract class WMShellModule { return new DesktopPersistentRepository(context, bgScope); } @WMSingleton @Provides static DesktopRepositoryInitializer provideDesktopRepositoryInitializer( Context context, DesktopPersistentRepository desktopPersistentRepository, @ShellMainThread CoroutineScope mainScope) { return new DesktopRepositoryInitializerImpl(context, desktopPersistentRepository, mainScope); } // // Drag and drop // Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +3 −27 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ import androidx.core.util.valueIterator import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopTaskState import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus Loading @@ -46,6 +46,7 @@ class DesktopRepository ( private val context: Context, shellInit: ShellInit, private val persistentRepository: DesktopPersistentRepository, private val repositoryInitializer: DesktopRepositoryInitializer, @ShellMainThread private val mainCoroutineScope: CoroutineScope, ){ Loading Loading @@ -120,32 +121,7 @@ class DesktopRepository ( } private fun initRepoFromPersistentStorage() { if (!Flags.enableDesktopWindowingPersistence()) return // TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized mainCoroutineScope.launch { val desktop = persistentRepository.readDesktop() ?: return@launch val maxTasks = DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 } ?: desktop.zOrderedTasksCount var visibleTasksCount = 0 desktop.zOrderedTasksList // Reverse it so we initialize the repo from bottom to top. .reversed() .mapNotNull { taskId -> desktop.tasksByTaskIdMap[taskId] } .forEach { task -> if (task.desktopTaskState == DesktopTaskState.VISIBLE && visibleTasksCount < maxTasks ) { visibleTasksCount++ addTask(desktop.displayId, task.taskId, isVisible = false) } else { addTask(desktop.displayId, task.taskId, isVisible = false) minimizeTask(desktop.displayId, task.taskId) } } } repositoryInitializer.initialize(this) } /** Adds [activeTasksListener] to be notified of updates to active tasks. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode.persistence import com.android.wm.shell.desktopmode.DesktopRepository /** Interface for initializing the [DesktopRepository]. */ fun interface DesktopRepositoryInitializer { fun initialize(repository: DesktopRepository) }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode.persistence import android.content.Context import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch /** * Initializes the [DesktopRepository] from the [DesktopPersistentRepository]. * * This class is responsible for reading the [DesktopPersistentRepository] and initializing the * [DesktopRepository] with the tasks that previously existed in desktop. */ class DesktopRepositoryInitializerImpl( private val context: Context, private val persistentRepository: DesktopPersistentRepository, @ShellMainThread private val mainCoroutineScope: CoroutineScope, ) : DesktopRepositoryInitializer { override fun initialize(repository: DesktopRepository) { if (!Flags.enableDesktopWindowingPersistence()) return // TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized mainCoroutineScope.launch { val desktop = persistentRepository.readDesktop() ?: return@launch val maxTasks = DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 } ?: desktop.zOrderedTasksCount var visibleTasksCount = 0 desktop.zOrderedTasksList // Reverse it so we initialize the repo from bottom to top. .reversed() .mapNotNull { taskId -> desktop.tasksByTaskIdMap[taskId] } .forEach { task -> if (task.desktopTaskState == DesktopTaskState.VISIBLE && visibleTasksCount < maxTasks ) { visibleTasksCount++ repository.addTask(desktop.displayId, task.taskId, isVisible = false) } else { repository.addTask(desktop.displayId, task.taskId, isVisible = false) repository.minimizeTask(desktop.displayId, task.taskId) } } } } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +10 −2 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreef import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.persistence.Desktop import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions Loading @@ -50,10 +51,10 @@ import junit.framework.Assert.assertEquals import junit.framework.Assert.assertTrue import kotlin.test.assertNotNull import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.setMain Loading Loading @@ -94,6 +95,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { @Mock lateinit var resizeTransitionHandler: ToggleResizeDesktopTaskTransitionHandler @Mock lateinit var taskStackListener: TaskStackListenerImpl @Mock lateinit var persistentRepository: DesktopPersistentRepository @Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer private lateinit var mockitoSession: StaticMockitoSession private lateinit var handler: DesktopActivityOrientationChangeHandler Loading @@ -116,7 +118,13 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) shellInit = spy(ShellInit(testExecutor)) taskRepository = DesktopRepository(context, shellInit, persistentRepository, testScope) DesktopRepository( context, shellInit, persistentRepository, repositoryInitializer, testScope ) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } whenever(runBlocking { persistentRepository.readDesktop(any(), any()) }).thenReturn( Loading