summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java)38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt21
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt31
7 files changed, 278 insertions, 22 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt
new file mode 100644
index 000000000000..0b0b1e45d604
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.platform.test.annotations.EnableFlags
+import android.view.Display.DEFAULT_DISPLAY
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.display.data.repository.displayRepository
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+class MultiDisplayAutoHideControllerStoreTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos().useUnconfinedTestDispatcher()
+ private val testScope = kosmos.testScope
+ private val fakeDisplayRepository = kosmos.displayRepository
+
+ // Lazy so that @EnableFlags has time to run before underTest is instantiated.
+ private val underTest by lazy { kosmos.multiDisplayAutoHideControllerStore }
+
+ @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) }
+
+ @Test
+ fun beforeDisplayRemoved_doesNotStopInstances() =
+ testScope.runTest {
+ val instance = underTest.forDisplay(DEFAULT_DISPLAY)
+
+ verify(instance, never()).stop()
+ }
+
+ @Test
+ fun displayRemoved_stopsInstance() =
+ testScope.runTest {
+ val instance = underTest.forDisplay(DEFAULT_DISPLAY)
+
+ fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY)
+
+ verify(instance).stop()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index d3d2c5872a01..45933e5549f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -27,6 +27,8 @@ import com.android.systemui.log.LogBufferFactory
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.data.StatusBarDataLayerModule
import com.android.systemui.statusbar.data.repository.LightBarControllerStore
+import com.android.systemui.statusbar.phone.AutoHideController
+import com.android.systemui.statusbar.phone.AutoHideControllerImpl
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProviderImpl
@@ -79,6 +81,8 @@ interface StatusBarModule {
implFactory: StatusBarWindowControllerImpl.Factory
): StatusBarWindowController.Factory
+ @Binds @SysUISingleton fun autoHideController(impl: AutoHideControllerImpl): AutoHideController
+
companion object {
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt
new file mode 100644
index 000000000000..636e1c45bc81
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.content.Context
+import android.view.MotionEvent
+import com.android.systemui.statusbar.AutoHideUiElement
+import java.io.PrintWriter
+
+/**
+ * Controls the auto-hide behavior of system bars (status bar, navigation bar).
+ *
+ * This interface provides methods to manage the auto-hide schedule of system bars, allowing them to
+ * be shown or hidden.
+ */
+interface AutoHideController {
+ /**
+ * Sets a [AutoHideUiElement] status bar that should be controlled by the [AutoHideController].
+ */
+ fun setStatusBar(element: AutoHideUiElement)
+
+ /**
+ * Sets a [AutoHideUiElement] navigation bar that should be controlled by the
+ * [AutoHideController].
+ */
+ fun setNavigationBar(element: AutoHideUiElement)
+
+ /** Resumes the auto-hide behavior that was previously suspended. */
+ fun resumeSuspendedAutoHide()
+
+ /** Suspends the auto-hide behavior. */
+ fun suspendAutoHide()
+
+ /** Schedules or cancels auto hide behavior based on current system bar state. */
+ fun touchAutoHide()
+
+ /** Hides system bars on user touch if the interaction requires them to be hidden. */
+ fun checkUserAutoHide(event: MotionEvent)
+
+ /** Called when work should stop and resources should be released. */
+ fun stop()
+
+ /** Dumps the current state of the [AutoHideController] */
+ fun dump(pw: PrintWriter)
+
+ /** Injectable factory for creating a [AutoHideController]. */
+ interface Factory {
+ /** Create an [AutoHideController] */
+ fun create(context: Context): AutoHideController
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerImpl.java
index 1358cfd3e8da..4fbfbb254064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -28,7 +28,6 @@ import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.AutoHideUiElement;
@@ -36,9 +35,7 @@ import java.io.PrintWriter;
import javax.inject.Inject;
-/** A controller to control all auto-hide things. Also see {@link AutoHideUiElement}. */
-@SysUISingleton
-public class AutoHideController {
+public class AutoHideControllerImpl implements AutoHideController {
private static final String TAG = "AutoHideController";
private static final int AUTO_HIDE_TIMEOUT_MS = 2250;
private static final int USER_AUTO_HIDE_TIMEOUT_MS = 350;
@@ -61,7 +58,7 @@ public class AutoHideController {
};
@Inject
- public AutoHideController(Context context,
+ public AutoHideControllerImpl(Context context,
@Main Handler handler,
IWindowManager iWindowManager) {
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -70,18 +67,12 @@ public class AutoHideController {
mDisplayId = context.getDisplayId();
}
- /**
- * Sets a {@link AutoHideUiElement} status bar that should be controlled by the
- * {@link AutoHideController}.
- */
+ @Override
public void setStatusBar(AutoHideUiElement element) {
mStatusBar = element;
}
- /**
- * Sets a {@link AutoHideUiElement} navigation bar that should be controlled by the
- * {@link AutoHideController}.
- */
+ @Override
public void setNavigationBar(AutoHideUiElement element) {
mNavigationBar = element;
}
@@ -102,6 +93,7 @@ public class AutoHideController {
}
}
+ @Override
public void resumeSuspendedAutoHide() {
if (mAutoHideSuspended) {
scheduleAutoHide();
@@ -112,6 +104,7 @@ public class AutoHideController {
}
}
+ @Override
public void suspendAutoHide() {
mHandler.removeCallbacks(mAutoHide);
Runnable checkBarModesRunnable = getCheckBarModesRunnable();
@@ -121,7 +114,7 @@ public class AutoHideController {
mAutoHideSuspended = isAnyTransientBarShown();
}
- /** Schedules or cancels auto hide behavior based on current system bar state. */
+ @Override
public void touchAutoHide() {
// update transient bar auto hide
if (isAnyTransientBarShown()) {
@@ -156,6 +149,7 @@ public class AutoHideController {
FLAG_CONTENT_CONTROLS);
}
+ @Override
public void checkUserAutoHide(MotionEvent event) {
boolean shouldHide = isAnyTransientBarShown()
&& event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
@@ -196,6 +190,12 @@ public class AutoHideController {
return false;
}
+ @Override
+ public void stop() {
+ mHandler.removeCallbacks(mAutoHide);
+ }
+
+ @Override
public void dump(@NonNull PrintWriter pw) {
pw.println("AutoHideController:");
pw.println("\tmAutoHideSuspended=" + mAutoHideSuspended);
@@ -205,10 +205,7 @@ public class AutoHideController {
pw.println("\tgetUserAutoHideTimeout=" + getUserAutoHideTimeout());
}
- /**
- * Injectable factory for creating a {@link AutoHideController}.
- */
- public static class Factory {
+ public static class Factory implements AutoHideController.Factory {
private final Handler mHandler;
private final IWindowManager mIWindowManager;
@@ -219,8 +216,9 @@ public class AutoHideController {
}
/** Create an {@link AutoHideController} */
+ @Override
public AutoHideController create(Context context) {
- return new AutoHideController(context, mHandler, mIWindowManager);
+ return new AutoHideControllerImpl(context, mHandler, mIWindowManager);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt
new file mode 100644
index 000000000000..744f96918eef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.display.data.repository.DisplayRepository
+import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
+import com.android.systemui.display.data.repository.PerDisplayStore
+import com.android.systemui.display.data.repository.PerDisplayStoreImpl
+import com.android.systemui.display.data.repository.SingleDisplayStore
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+
+/** Provides per display instances of [AutoHideController] */
+interface AutoHideControllerStore : PerDisplayStore<AutoHideController>
+
+@SysUISingleton
+class MultiDisplayAutoHideControllerStore
+@Inject
+constructor(
+ @Background backgroundApplicationScope: CoroutineScope,
+ displayRepository: DisplayRepository,
+ private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
+ private val autoHideControllerFactory: AutoHideControllerImpl.Factory,
+) :
+ AutoHideControllerStore,
+ PerDisplayStoreImpl<AutoHideController>(backgroundApplicationScope, displayRepository) {
+
+ init {
+ StatusBarConnectedDisplays.assertInNewMode()
+ }
+
+ override fun createInstanceForDisplay(displayId: Int): AutoHideController {
+ val displayWindowProperties =
+ displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR)
+ return autoHideControllerFactory.create(displayWindowProperties.context)
+ }
+
+ override suspend fun onDisplayRemovalAction(instance: AutoHideController) {
+ instance.stop()
+ }
+
+ override val instanceClass = AutoHideController::class.java
+}
+
+@SysUISingleton
+class SingleDisplayAutoHideControllerStore
+@Inject
+constructor(defaultController: AutoHideController) :
+ AutoHideControllerStore,
+ PerDisplayStore<AutoHideController> by SingleDisplayStore(defaultController) {
+
+ init {
+ StatusBarConnectedDisplays.assertInLegacyMode()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
index e1cdc58de8ad..a62776c03bb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
@@ -35,7 +35,12 @@ import com.android.systemui.statusbar.data.repository.PrivacyDotViewControllerSt
import com.android.systemui.statusbar.data.repository.PrivacyDotWindowControllerStoreModule
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
import com.android.systemui.statusbar.events.PrivacyDotViewControllerModule
+import com.android.systemui.statusbar.phone.AutoHideController
+import com.android.systemui.statusbar.phone.AutoHideControllerImpl
+import com.android.systemui.statusbar.phone.AutoHideControllerStore
import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks
+import com.android.systemui.statusbar.phone.MultiDisplayAutoHideControllerStore
+import com.android.systemui.statusbar.phone.SingleDisplayAutoHideControllerStore
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStore
import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStoreImpl
@@ -75,6 +80,9 @@ interface StatusBarPhoneModule {
@Binds fun statusBarInitializer(@Default impl: StatusBarInitializerImpl): StatusBarInitializer
+ @Binds
+ fun autoHideControllerFactory(impl: AutoHideControllerImpl.Factory): AutoHideController.Factory
+
companion object {
/** Binds {@link StatusBarInitializer} as a {@link CoreStartable}. */
@Provides
@@ -172,5 +180,18 @@ interface StatusBarPhoneModule {
singleDisplayStoreLazy.get()
}
}
+
+ @Provides
+ @SysUISingleton
+ fun autoHideStore(
+ singleDisplayLazy: Lazy<SingleDisplayAutoHideControllerStore>,
+ multiDisplayLazy: Lazy<MultiDisplayAutoHideControllerStore>,
+ ): AutoHideControllerStore {
+ return if (StatusBarConnectedDisplays.isEnabled) {
+ multiDisplayLazy.get()
+ } else {
+ singleDisplayLazy.get()
+ }
+ }
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt
index 090ce31bd43c..951ae59ebcf1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt
@@ -16,9 +16,36 @@
package com.android.systemui.statusbar.phone
+import android.content.Context
+import android.os.Handler
+import android.view.IWindowManager
+import com.android.systemui.display.data.repository.displayRepository
+import com.android.systemui.display.data.repository.fakeDisplayWindowPropertiesRepository
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.kosmos.applicationCoroutineScope
+import org.mockito.Mockito.mock
-val Kosmos.mockAutoHideController by Kosmos.Fixture { mock<AutoHideController>() }
+val Kosmos.mockAutoHideController: AutoHideController by
+ Kosmos.Fixture { mock(AutoHideController::class.java) }
var Kosmos.autoHideController by Kosmos.Fixture { mockAutoHideController }
+
+val Kosmos.fakeAutoHideControllerFactory by Kosmos.Fixture { FakeAutoHideControllerFactory() }
+
+val Kosmos.multiDisplayAutoHideControllerStore by
+ Kosmos.Fixture {
+ MultiDisplayAutoHideControllerStore(
+ applicationCoroutineScope,
+ displayRepository,
+ fakeDisplayWindowPropertiesRepository,
+ fakeAutoHideControllerFactory,
+ )
+ }
+
+class FakeAutoHideControllerFactory :
+ AutoHideControllerImpl.Factory(mock(Handler::class.java), mock(IWindowManager::class.java)) {
+
+ override fun create(context: Context): AutoHideControllerImpl {
+ return mock(AutoHideControllerImpl::class.java)
+ }
+}