summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ats Jenk <atsjenk@google.com> 2022-12-06 11:08:46 -0800
committer Ats Jenk <atsjenk@google.com> 2022-12-08 17:43:17 -0800
commite57c2641312bc7b0a6cac2fbe2a13c12c06bc112 (patch)
treed76f4b7cb534b811ec6953d3ac4d14fdf1e2b7a4
parent5e432142561a06ee8dcdf492afe2c0754a3626b4 (diff)
Create controller for desktop prototype 2
Create the controller class, set up dagger. Ensure controller is not initialized when flag is off. Bug: 260645044 Test: atest DesktopTasksControllerTest Change-Id: I0435e07a22e379f403ae5d1b23f39a67a12e8a6d
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt116
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt98
5 files changed, 259 insertions, 2 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index c743582c3264..09f5cf1d31e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -61,6 +61,7 @@ import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
+import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
import com.android.wm.shell.draganddrop.DragAndDropController;
@@ -677,7 +678,11 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static Optional<DesktopMode> provideDesktopMode(
- Optional<DesktopModeController> desktopModeController) {
+ Optional<DesktopModeController> desktopModeController,
+ Optional<DesktopTasksController> desktopTasksController) {
+ if (DesktopModeStatus.isProto2Enabled()) {
+ return desktopTasksController.map(DesktopTasksController::asDesktopMode);
+ }
return desktopModeController.map(DesktopModeController::asDesktopMode);
}
@@ -700,6 +705,23 @@ public abstract class WMShellBaseModule {
@BindsOptionalOf
@DynamicOverride
+ abstract DesktopTasksController optionalDesktopTasksController();
+
+ @WMSingleton
+ @Provides
+ static Optional<DesktopTasksController> providesDesktopTasksController(
+ @DynamicOverride Optional<Lazy<DesktopTasksController>> desktopTasksController) {
+ // Use optional-of-lazy for the dependency that this provider relies on.
+ // Lazy ensures that this provider will not be the cause the dependency is created
+ // when it will not be returned due to the condition below.
+ if (DesktopModeStatus.isProto2Enabled()) {
+ return desktopTasksController.map(Lazy::get);
+ }
+ return Optional.empty();
+ }
+
+ @BindsOptionalOf
+ @DynamicOverride
abstract DesktopModeTaskRepository optionalDesktopModeTaskRepository();
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 6be83054ae59..8a6fe437e652 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -50,6 +50,7 @@ import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
+import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.freeform.FreeformTaskListener;
@@ -616,6 +617,22 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
@DynamicOverride
+ static DesktopTasksController provideDesktopTasksController(
+ Context context,
+ ShellInit shellInit,
+ ShellController shellController,
+ ShellTaskOrganizer shellTaskOrganizer,
+ Transitions transitions,
+ @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
+ @ShellMainThread ShellExecutor mainExecutor
+ ) {
+ return new DesktopTasksController(context, shellInit, shellController, shellTaskOrganizer,
+ transitions, desktopModeTaskRepository, mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
+ @DynamicOverride
static DesktopModeTaskRepository provideDesktopModeTaskRepository() {
return new DesktopModeTaskRepository();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 67f4a1914c49..055949fd8c89 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -70,9 +70,13 @@ public class DesktopModeStatus {
* @return {@code true} if active
*/
public static boolean isActive(Context context) {
- if (!IS_SUPPORTED) {
+ if (!isAnyEnabled()) {
return false;
}
+ if (isProto2Enabled()) {
+ // Desktop mode is always active in prototype 2
+ return true;
+ }
try {
int result = Settings.System.getIntForUser(context.getContentResolver(),
Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
new file mode 100644
index 000000000000..736aa7e9aeca
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 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
+
+import android.content.Context
+import androidx.annotation.BinderThread
+import com.android.internal.protolog.common.ProtoLog
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.common.ExternalInterfaceBinder
+import com.android.wm.shell.common.RemoteCallable
+import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.common.annotations.ExternalThread
+import com.android.wm.shell.common.annotations.ShellMainThread
+import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.sysui.ShellController
+import com.android.wm.shell.sysui.ShellInit
+import com.android.wm.shell.sysui.ShellSharedConstants
+import com.android.wm.shell.transition.Transitions
+import java.util.concurrent.Executor
+
+/** Handles moving tasks in and out of desktop */
+class DesktopTasksController(
+ private val context: Context,
+ shellInit: ShellInit,
+ private val shellController: ShellController,
+ private val shellTaskOrganizer: ShellTaskOrganizer,
+ private val transitions: Transitions,
+ private val desktopModeTaskRepository: DesktopModeTaskRepository,
+ @ShellMainThread private val mainExecutor: ShellExecutor
+) : RemoteCallable<DesktopTasksController> {
+
+ private val desktopMode: DesktopModeImpl
+
+ init {
+ desktopMode = DesktopModeImpl()
+ if (DesktopModeStatus.isProto2Enabled()) {
+ shellInit.addInitCallback({ onInit() }, this)
+ }
+ }
+
+ private fun onInit() {
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
+ shellController.addExternalInterface(
+ ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE,
+ { createExternalInterface() },
+ this
+ )
+ }
+
+ override fun getContext(): Context {
+ return context
+ }
+
+ override fun getRemoteCallExecutor(): ShellExecutor {
+ return mainExecutor
+ }
+
+ /** Creates a new instance of the external interface to pass to another process. */
+ private fun createExternalInterface(): ExternalInterfaceBinder {
+ return IDesktopModeImpl(this)
+ }
+
+ /** Get connection interface between sysui and shell */
+ fun asDesktopMode(): DesktopMode {
+ return desktopMode
+ }
+
+ /**
+ * Adds a listener to find out about changes in the visibility of freeform tasks.
+ *
+ * @param listener the listener to add.
+ * @param callbackExecutor the executor to call the listener on.
+ */
+ fun addListener(listener: VisibleTasksListener, callbackExecutor: Executor) {
+ desktopModeTaskRepository.addVisibleTasksListener(listener, callbackExecutor)
+ }
+
+ /** The interface for calls from outside the shell, within the host process. */
+ @ExternalThread
+ private inner class DesktopModeImpl : DesktopMode {
+ override fun addListener(listener: VisibleTasksListener, callbackExecutor: Executor) {
+ mainExecutor.execute {
+ this@DesktopTasksController.addListener(listener, callbackExecutor)
+ }
+ }
+ }
+
+ /** The interface for calls from outside the host process. */
+ @BinderThread
+ private class IDesktopModeImpl(private var controller: DesktopTasksController?) :
+ IDesktopMode.Stub(), ExternalInterfaceBinder {
+ /** Invalidates this instance, preventing future calls from updating the controller. */
+ override fun invalidate() {
+ controller = null
+ }
+
+ override fun showDesktopApps() {
+ // TODO
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
new file mode 100644
index 000000000000..15155f80247b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 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
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.dx.mockito.inline.extended.ExtendedMockito.never
+import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestShellExecutor
+import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.sysui.ShellController
+import com.android.wm.shell.sysui.ShellInit
+import com.android.wm.shell.transition.Transitions
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.any
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class DesktopTasksControllerTest : ShellTestCase() {
+
+ @Mock
+ lateinit var testExecutor: ShellExecutor
+ @Mock
+ lateinit var shellController: ShellController
+ @Mock
+ lateinit var shellTaskOrganizer: ShellTaskOrganizer
+ @Mock
+ lateinit var transitions: Transitions
+
+ lateinit var mockitoSession: StaticMockitoSession
+ lateinit var controller: DesktopTasksController
+ lateinit var shellInit: ShellInit
+ lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
+
+ @Before
+ fun setUp() {
+ mockitoSession = mockitoSession().mockStatic(DesktopModeStatus::class.java).startMocking()
+ whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(true)
+
+ shellInit = Mockito.spy(ShellInit(testExecutor))
+ desktopModeTaskRepository = DesktopModeTaskRepository()
+
+ controller = createController()
+
+ shellInit.init()
+ }
+
+ private fun createController(): DesktopTasksController {
+ return DesktopTasksController(context, shellInit, shellController,
+ shellTaskOrganizer, transitions, desktopModeTaskRepository, TestShellExecutor())
+ }
+
+ @After
+ fun tearDown() {
+ mockitoSession.finishMocking()
+ }
+
+ @Test
+ fun instantiate_addInitCallback() {
+ verify(shellInit).addInitCallback(any(), any<DesktopTasksController>())
+ }
+
+ @Test
+ fun instantiate_flagOff_doNotAddInitCallback() {
+ whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(false)
+ clearInvocations(shellInit)
+
+ createController()
+
+ verify(shellInit, never()).addInitCallback(any(), any<DesktopTasksController>())
+ }
+} \ No newline at end of file