summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/AndroidManifest.xml11
-rw-r--r--packages/SystemUI/res/drawable/controls_dialog_bg.xml21
-rw-r--r--packages/SystemUI/res/layout/controls_detail_dialog.xml7
-rw-r--r--packages/SystemUI/res/layout/controls_fullscreen.xml (renamed from packages/SystemUI/res/layout/controls_in_dialog.xml)5
-rw-r--r--packages/SystemUI/res/layout/controls_with_favorites.xml15
-rw-r--r--packages/SystemUI/res/values/styles.xml38
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt86
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt91
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt37
20 files changed, 255 insertions, 257 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e847ac8ef5e7..e0097df62078 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -751,6 +751,17 @@
android:visibleToInstantApps="true">
</activity>
+ <activity android:name=".controls.ui.ControlsActivity"
+ android:label="@string/quick_controls_title"
+ android:theme="@style/Theme.ControlsActivity"
+ android:excludeFromRecents="true"
+ android:showWhenLocked="true"
+ android:showForAllUsers="true"
+ android:launchMode="singleInstance"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:visibleToInstantApps="true">
+ </activity>
+
<receiver android:name=".controls.management.ControlsRequestReceiver"
android:exported="true">
<intent-filter>
diff --git a/packages/SystemUI/res/drawable/controls_dialog_bg.xml b/packages/SystemUI/res/drawable/controls_dialog_bg.xml
deleted file mode 100644
index 1ccb176b8689..000000000000
--- a/packages/SystemUI/res/drawable/controls_dialog_bg.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2021 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?android:attr/colorBackground" />
- <corners android:radius="@dimen/notification_corner_radius" />
-</shape>
diff --git a/packages/SystemUI/res/layout/controls_detail_dialog.xml b/packages/SystemUI/res/layout/controls_detail_dialog.xml
index ee5315ad782f..28fc86372092 100644
--- a/packages/SystemUI/res/layout/controls_detail_dialog.xml
+++ b/packages/SystemUI/res/layout/controls_detail_dialog.xml
@@ -20,8 +20,8 @@
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginTop="@dimen/controls_activity_view_top_offset"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:background="@android:color/black">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -30,7 +30,7 @@
<ImageView
android:id="@+id/control_detail_close"
android:contentDescription="@string/accessibility_desc_close"
- android:src="@drawable/ic_close"
+ android:src="@drawable/ic_arrow_back"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:tint="@color/control_primary_text"
android:layout_width="48dp"
@@ -56,7 +56,6 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
- android:background="@android:color/black"
android:orientation="vertical" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_in_dialog.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index 983999f9a5f8..1b2d2e2e9c89 100644
--- a/packages/SystemUI/res/layout/controls_in_dialog.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -20,11 +20,8 @@
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginVertical="@dimen/controls_activity_view_top_offset"
- android:layout_marginHorizontal="@dimen/controls_activity_view_side_offset"
- android:padding="8dp"
android:orientation="vertical"
- android:background="@drawable/controls_dialog_bg">
+ android:background="@android:color/black">
<com.android.systemui.globalactions.MinHeightScrollView
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index b060afdc18e3..9d011482d011 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -25,8 +25,21 @@
<!-- make sure the header stays centered in the layout by adding a spacer -->
<Space
+ android:id="@+id/controls_spacer"
android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="1dp" />
+ android:layout_height="1dp"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/controls_close"
+ android:contentDescription="@string/accessibility_desc_close"
+ android:src="@drawable/ic_close"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:tint="@color/control_primary_text"
+ android:layout_width="@dimen/controls_header_menu_size"
+ android:layout_height="@dimen/controls_header_menu_size"
+ android:padding="12dp"
+ android:visibility="gone" />
<!-- need to keep this outer view in order to have a correctly sized anchor
for the dropdown menu, as well as dropdown background in the right place -->
<LinearLayout
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3c48548cc0fe..fb885cb3fdbe 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -649,6 +649,16 @@
<item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
</style>
+ <style name="Theme.ControlsActivity" parent="@android:style/Theme.DeviceDefault.NoActionBar">
+ <item name="android:windowActivityTransitions">true</item>
+ <item name="android:windowContentTransitions">false</item>
+ <item name="android:windowIsTranslucent">false</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowAnimationStyle">@null</item>
+ <item name="android:statusBarColor">@*android:color/transparent</item>
+ <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
+ </style>
+
<style name="Theme.CreateUser" parent="@style/Theme.SystemUI">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#33000000</item>
@@ -660,30 +670,12 @@
<item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
</style>
- <style name="Theme.SystemUI.Dialog.Control.DetailPanel" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
- <item name="android:windowAnimationStyle">@style/Animation.Bottomsheet</item>
- <item name="android:windowFullscreen">true</item>
- <item name="android:windowIsFloating">false</item>
- <item name="android:windowBackground">@null</item>
- <item name="android:backgroundDimEnabled">true</item>
- </style>
-
- <style name="Animation.Bottomsheet">
- <item name="android:windowEnterAnimation">@anim/bottomsheet_in</item>
- <item name="android:windowExitAnimation">@anim/bottomsheet_out</item>
- </style>
-
- <style name="Theme.SystemUI.Dialog.Control.LockScreen" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
- <item name="android:windowAnimationStyle">@style/Animation.ControlDialog</item>
- <item name="android:windowFullscreen">true</item>
+ <style name="Theme.SystemUI.Dialog.Control.DetailPanel" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
+ <item name="android:windowFullscreen">false</item>
<item name="android:windowIsFloating">false</item>
- <item name="android:windowBackground">@null</item>
- <item name="android:backgroundDimEnabled">true</item>
- </style>
-
- <style name="Animation.ControlDialog">
- <item name="android:windowEnterAnimation">@*android:anim/dialog_enter</item>
- <item name="android:windowExitAnimation">@*android:anim/dialog_exit</item>
+ <item name="android:windowBackground">@android:color/black</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
</style>
<style name="Control" />
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index fbdeb30d3911..ed625de9dce8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -31,6 +31,7 @@ import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.management.ControlsRequestDialog
import com.android.systemui.controls.ui.ControlActionCoordinator
import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
+import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.controls.ui.ControlsUiControllerImpl
import com.android.systemui.dagger.SysUISingleton
@@ -113,4 +114,9 @@ abstract class ControlsModule {
abstract fun provideControlsRequestDialog(
activity: ControlsRequestDialog
): Activity
+
+ @Binds
+ @IntoMap
+ @ClassKey(ControlsActivity::class)
+ abstract fun provideControlsActivity(activity: ControlsActivity): Activity
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index fc89783018bc..7dd1d28170b2 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -32,7 +32,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo
-import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.settings.CurrentUserTracker
@@ -112,7 +112,11 @@ class ControlsEditingActivity @Inject constructor(
if (backToGlobalActions) {
globalActionsComponent.handleShowGlobalActionsMenu()
} else {
- ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+ val i = Intent().apply {
+ component = ComponentName(applicationContext, ControlsActivity::class.java)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ startActivity(i)
}
animateExitAndFinish()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 2d647a907b17..309901443393 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -40,7 +40,7 @@ import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.TooltipManager
import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo
-import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.globalactions.GlobalActionsComponent
@@ -352,7 +352,11 @@ class ControlsFavoritingActivity @Inject constructor(
if (backToGlobalActions) {
globalActionsComponent.handleShowGlobalActionsMenu()
} else {
- ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+ val i = Intent().apply {
+ component = ComponentName(applicationContext, ControlsActivity::class.java)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ startActivity(i)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index d5e41d031eac..fa1c41f01e6c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -32,7 +32,7 @@ import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.controller.ControlsController
-import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -116,7 +116,11 @@ class ControlsProviderSelectorActivity @Inject constructor(
if (backToGlobalActions) {
globalActionsComponent.handleShowGlobalActionsMenu()
} else {
- ControlsDialog(applicationContext, broadcastDispatcher).show(uiController)
+ val i = Intent().apply {
+ component = ComponentName(applicationContext, ControlsActivity::class.java)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ startActivity(i)
}
animateExitAndFinish()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
index d06568a7caf9..0db15e83fc93 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -16,6 +16,7 @@
package com.android.systemui.controls.ui
+import android.content.Context
import android.service.controls.Control
/**
@@ -24,8 +25,8 @@ import android.service.controls.Control
*/
interface ControlActionCoordinator {
- // Handle actions launched from GlobalActionsDialog or ControlDialog
- var startedFromGlobalActions: Boolean
+ // If launched from an Activity, continue within this stack
+ var activityContext: Context?
/**
* Close any dialogs which may have been open
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 6b300f4e07e4..58a5981845c7 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@ package com.android.systemui.controls.ui
import android.annotation.MainThread
import android.app.Dialog
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -60,7 +61,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
private var pendingAction: Action? = null
private var actionsInProgress = mutableSetOf<String>()
- override var startedFromGlobalActions: Boolean = true
+ override var activityContext: Context? = null
companion object {
private const val RESPONSE_TIMEOUT_IN_MILLIS = 3000L
@@ -83,7 +84,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
bouncerOrRun(createAction(cvh.cws.ci.controlId, {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
if (cvh.usePanel()) {
- showDialog(cvh, control.getAppIntent().getIntent())
+ showDetail(cvh, control.getAppIntent().getIntent())
} else {
cvh.action(CommandAction(templateId))
}
@@ -109,7 +110,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
// Long press snould only be called when there is valid control state, otherwise ignore
cvh.cws.control?.let {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- showDialog(cvh, it.getAppIntent().getIntent())
+ showDetail(cvh, it.getAppIntent().getIntent())
}
}, false /* blockable */))
}
@@ -151,10 +152,16 @@ class ControlActionCoordinatorImpl @Inject constructor(
activityStarter.dismissKeyguardThenExecute({
Log.d(ControlsUiController.TAG, "Device unlocked, invoking controls action")
if (closeDialog) {
- if (startedFromGlobalActions) {
+ activityContext?.let {
+ val i = Intent().apply {
+ component = ComponentName(context, ControlsActivity::class.java)
+ addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ putExtra(ControlsUiController.BACK_TO_GLOBAL_ACTIONS, false)
+ }
+ it.startActivity(i)
+ } ?: run {
globalActionsComponent.handleShowGlobalActionsMenu()
- } else {
- ControlsDialog(context, broadcastDispatcher).show(lazyUiController.get())
}
} else {
action.invoke()
@@ -170,9 +177,9 @@ class ControlActionCoordinatorImpl @Inject constructor(
bgExecutor.execute { vibrator.vibrate(effect) }
}
- private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
+ private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
bgExecutor.execute {
- val activities: List<ResolveInfo> = cvh.context.packageManager.queryIntentActivities(
+ val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
intent,
PackageManager.MATCH_DEFAULT_ONLY
)
@@ -180,8 +187,8 @@ class ControlActionCoordinatorImpl @Inject constructor(
uiExecutor.execute {
// make sure the intent is valid before attempting to open the dialog
if (activities.isNotEmpty() && taskViewFactory.isPresent) {
- taskViewFactory.get().create(cvh.context, uiExecutor, {
- dialog = DetailDialog(cvh, it, intent).also {
+ taskViewFactory.get().create(context, uiExecutor, {
+ dialog = DetailDialog(activityContext, it, intent, cvh).also {
it.setOnDismissListener { _ -> dialog = null }
it.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
new file mode 100644
index 000000000000..a35b792ac7f1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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.controls.ui
+
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowInsets
+import android.view.WindowInsets.Type
+
+import com.android.systemui.R
+import com.android.systemui.controls.management.ControlsAnimations
+import com.android.systemui.util.LifecycleActivity
+import javax.inject.Inject
+
+/**
+ * Displays Device Controls inside an activity
+ */
+class ControlsActivity @Inject constructor(
+ private val uiController: ControlsUiController
+) : LifecycleActivity() {
+
+ private lateinit var parent: ViewGroup
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.controls_fullscreen)
+
+ requireViewById<ViewGroup>(R.id.control_detail_root).apply {
+ setOnApplyWindowInsetsListener {
+ v: View, insets: WindowInsets ->
+ v.apply {
+ val l = getPaddingLeft()
+ val t = getPaddingTop()
+ val r = getPaddingRight()
+ setPadding(l, t, r, insets.getInsets(Type.systemBars()).bottom)
+ }
+
+ WindowInsets.CONSUMED
+ }
+ }
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+ parent.alpha = 0f
+ uiController.show(parent, { animateExitAndFinish() }, this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ ControlsAnimations.enterAnimation(parent).start()
+ }
+
+ override fun onBackPressed() {
+ animateExitAndFinish()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ uiController.hide()
+ }
+
+ private fun animateExitAndFinish() {
+ ControlsAnimations.exitAnimation(parent, { finish() }).start()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt
deleted file mode 100644
index 537334aeb2f7..000000000000
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialog.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2021 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.controls.ui
-
-import android.app.Dialog
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowManager
-
-import com.android.systemui.Interpolators
-import com.android.systemui.R
-import com.android.systemui.broadcast.BroadcastDispatcher
-import javax.inject.Inject
-
-/**
- * Show the controls space inside a dialog, as from the lock screen.
- */
-class ControlsDialog @Inject constructor(
- thisContext: Context,
- val broadcastDispatcher: BroadcastDispatcher
-) : Dialog(thisContext, R.style.Theme_SystemUI_Dialog_Control_LockScreen) {
-
- private val receiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- val action = intent.getAction()
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- dismiss()
- }
- }
- }
-
- init {
- window.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)
- window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
- or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
-
- setContentView(R.layout.controls_in_dialog)
-
- requireViewById<ViewGroup>(R.id.control_detail_root).apply {
- setOnClickListener { dismiss() }
- (getParent() as View).setOnClickListener { dismiss() }
- }
- }
-
- fun show(
- controller: ControlsUiController
- ): ControlsDialog {
- super.show()
-
- val vg = requireViewById<ViewGroup>(com.android.systemui.R.id.global_actions_controls)
- vg.alpha = 0f
- controller.show(vg, { dismiss() }, false /* startedFromGlobalActions */)
-
- vg.animate()
- .alpha(1f)
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
- .setDuration(300)
-
- val filter = IntentFilter()
- filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
- broadcastDispatcher.registerReceiver(receiver, filter)
-
- return this
- }
-
- override fun dismiss() {
- broadcastDispatcher.unregisterReceiver(receiver)
-
- if (!isShowing()) return
-
- super.dismiss()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 20bdf609357e..f86948ee8957 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -17,6 +17,7 @@
package com.android.systemui.controls.ui
import android.content.ComponentName
+import android.content.Context
import android.service.controls.Control
import android.service.controls.actions.ControlAction
import android.view.ViewGroup
@@ -30,7 +31,7 @@ interface ControlsUiController {
public const val BACK_TO_GLOBAL_ACTIONS = "back_to_global_actions"
}
- fun show(parent: ViewGroup, onDismiss: Runnable, startedFromGlobalActions: Boolean)
+ fun show(parent: ViewGroup, onDismiss: Runnable, activityContext: Context?)
fun hide()
/**
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index c94d85aa58c4..0f7f48ff951a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -148,7 +148,7 @@ class ControlsUiControllerImpl @Inject constructor (
override fun show(
parent: ViewGroup,
onDismiss: Runnable,
- startedFromGlobalActions: Boolean
+ activityContext: Context?
) {
Log.d(ControlsUiController.TAG, "show()")
this.parent = parent
@@ -156,7 +156,7 @@ class ControlsUiControllerImpl @Inject constructor (
hidden = false
retainCache = false
- controlActionCoordinator.startedFromGlobalActions = startedFromGlobalActions
+ controlActionCoordinator.activityContext = activityContext
allStructures = controlsController.get().getFavorites()
selectedStructure = loadPreference(allStructures)
@@ -193,7 +193,7 @@ class ControlsUiControllerImpl @Inject constructor (
controlViewsById.clear()
controlsById.clear()
- show(parent, onDismiss, controlActionCoordinator.startedFromGlobalActions)
+ show(parent, onDismiss, controlActionCoordinator.activityContext)
val showAnim = ObjectAnimator.ofFloat(parent, "alpha", 0.0f, 1.0f)
showAnim.setInterpolator(DecelerateInterpolator(1.0f))
showAnim.setDuration(FADE_IN_MILLIS)
@@ -268,7 +268,7 @@ class ControlsUiControllerImpl @Inject constructor (
intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
intent.putExtra(
ControlsUiController.BACK_TO_GLOBAL_ACTIONS,
- controlActionCoordinator.startedFromGlobalActions
+ controlActionCoordinator.activityContext == null
)
onDismiss.run()
@@ -392,6 +392,17 @@ class ControlsUiControllerImpl @Inject constructor (
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.controls_with_favorites, parent, true)
+ if (controlActionCoordinator.activityContext == null) {
+ parent.requireViewById<View>(R.id.controls_spacer).apply {
+ visibility = View.VISIBLE
+ }
+ } else {
+ parent.requireViewById<ImageView>(R.id.controls_close).apply {
+ setOnClickListener { _: View -> onDismiss.run() }
+ visibility = View.VISIBLE
+ }
+ }
+
val maxColumns = findMaxColumns()
val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup
@@ -502,6 +513,8 @@ class ControlsUiControllerImpl @Inject constructor (
override fun hide() {
hidden = true
+ controlActionCoordinator.activityContext = null
+
closeDialogs(true)
controlsController.get().unsubscribe()
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 020694d89fce..9c788df362de 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -22,8 +22,8 @@ import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName
+import android.content.Context
import android.content.Intent
-import android.provider.Settings
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
@@ -35,18 +35,20 @@ import com.android.systemui.R
import com.android.wm.shell.TaskView
/**
- * A dialog that provides an {@link ActivityView}, allowing the application to provide
+ * A dialog that provides an {@link TaskView}, allowing the application to provide
* additional information and actions pertaining to a {@link android.service.controls.Control}.
* The activity being launched is specified by {@link android.service.controls.Control#getAppIntent}.
*/
class DetailDialog(
- val cvh: ControlViewHolder,
- val activityView: TaskView,
- val intent: Intent
-) : Dialog(cvh.context, R.style.Theme_SystemUI_Dialog_Control_DetailPanel) {
-
+ val activityContext: Context?,
+ val taskView: TaskView,
+ val intent: Intent,
+ val cvh: ControlViewHolder
+) : Dialog(
+ activityContext ?: cvh.context,
+ R.style.Theme_SystemUI_Dialog_Control_DetailPanel
+) {
companion object {
- private const val PANEL_TOP_OFFSET = "systemui.controls_panel_top_offset"
/*
* Indicate to the activity that it is being rendered in a bottomsheet, and they
* should optimize the layout for a smaller space.
@@ -71,10 +73,19 @@ class DetailDialog(
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
- activityView.startActivity(
- PendingIntent.getActivity(context, 0, launchIntent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
- null, ActivityOptions.makeBasic())
+ val options = activityContext?.let {
+ ActivityOptions.makeCustomAnimation(
+ it,
+ 0 /* enterResId */,
+ 0 /* exitResId */
+ )
+ } ?: ActivityOptions.makeBasic()
+ taskView.startActivity(
+ PendingIntent.getActivity(context, 0, launchIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
+ null,
+ options
+ )
}
override fun onTaskRemovalStarted(taskId: Int) {
@@ -92,7 +103,10 @@ class DetailDialog(
}
init {
- window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
+ if (activityContext == null) {
+ window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
+ }
+
// To pass touches to the task inside TaskView.
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
@@ -100,7 +114,7 @@ class DetailDialog(
setContentView(R.layout.controls_detail_dialog)
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
- addView(activityView)
+ addView(taskView)
}
requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -120,48 +134,34 @@ class DetailDialog(
// consume all insets to achieve slide under effect
window.getDecorView().setOnApplyWindowInsetsListener {
- _: View, insets: WindowInsets ->
- activityView.apply {
+ v: View, insets: WindowInsets ->
+ taskView.apply {
val l = getPaddingLeft()
val t = getPaddingTop()
val r = getPaddingRight()
setPadding(l, t, r, insets.getInsets(Type.systemBars()).bottom)
}
- WindowInsets.CONSUMED
- }
-
- requireViewById<ViewGroup>(R.id.control_detail_root).apply {
- // use flag only temporarily for testing
- val resolver = cvh.context.contentResolver
- val defaultOffsetInPx = cvh.context.resources
- .getDimensionPixelSize(R.dimen.controls_activity_view_top_offset)
- val offsetInPx = Settings.Secure.getInt(resolver, PANEL_TOP_OFFSET, defaultOffsetInPx)
-
- val lp = getLayoutParams() as ViewGroup.MarginLayoutParams
- lp.topMargin = offsetInPx
- setLayoutParams(lp)
+ val l = v.getPaddingLeft()
+ val b = v.getPaddingBottom()
+ val r = v.getPaddingRight()
+ v.setPadding(l, insets.getInsets(Type.systemBars()).top, r, b)
- setOnClickListener { dismiss() }
- (getParent() as View).setOnClickListener { dismiss() }
+ WindowInsets.CONSUMED
}
if (ScreenDecorationsUtils.supportsRoundedCornersOnWindows(context.getResources())) {
val cornerRadius = context.resources
.getDimensionPixelSize(R.dimen.controls_activity_view_corner_radius)
- activityView.setCornerRadius(cornerRadius.toFloat())
+ taskView.setCornerRadius(cornerRadius.toFloat())
}
- }
-
- override fun show() {
- activityView.setListener(cvh.uiExecutor, stateCallback)
- super.show()
+ taskView.setListener(cvh.uiExecutor, stateCallback)
}
override fun dismiss() {
if (!isShowing()) return
- activityView.release()
+ taskView.release()
super.dismiss()
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1f67276bfbae..461a7303c184 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -2220,7 +2220,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private void showControls(ControlsUiController controller) {
mControlsUiController = controller;
mControlsUiController.show(mControlsView, this::dismissForControlsActivity,
- true /* startedFromGlobalActions */);
+ null /* activityContext */);
}
private boolean isWalletViewAvailable() {
@@ -2449,7 +2449,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
});
if (mControlsUiController != null) {
mControlsUiController.show(mControlsView, this::dismissForControlsActivity,
- true /* startedFromGlobalActions */);
+ null /* activityContext */);
}
mBackgroundDrawable.setAlpha(0);
@@ -2625,7 +2625,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mGlobalActionsLayout.updateList();
if (mControlsUiController != null) {
mControlsUiController.show(mControlsView, this::dismissForControlsActivity,
- true /* startedFromGlobalActions */);
+ null /* activityContext */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index 3b9f5dc8ea03..257d6a7abda1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.tiles
+import android.content.ComponentName
import android.content.Intent
import android.os.Handler
import android.os.Looper
@@ -27,7 +28,8 @@ import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE
import com.android.systemui.controls.management.ControlsListingController
-import com.android.systemui.controls.ui.ControlsDialog
+import com.android.systemui.controls.ui.ControlsActivity
+import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -40,7 +42,6 @@ import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.util.settings.GlobalSettings
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
-import javax.inject.Provider
class DeviceControlsTile @Inject constructor(
host: QSHost,
@@ -52,7 +53,6 @@ class DeviceControlsTile @Inject constructor(
qsLogger: QSLogger,
private val controlsComponent: ControlsComponent,
private val featureFlags: FeatureFlags,
- private val dialogProvider: Provider<ControlsDialog>,
globalSettings: GlobalSettings
) : QSTileImpl<QSTile.State>(
host,
@@ -72,7 +72,6 @@ class DeviceControlsTile @Inject constructor(
private var hasControlsApps = AtomicBoolean(false)
private val intent = Intent(Settings.ACTION_DEVICE_CONTROLS_SETTINGS)
- private var controlsDialog: ControlsDialog? = null
private val icon = ResourceIcon.get(R.drawable.ic_device_light)
private val listingCallback = object : ControlsListingController.ControlsListingCallback {
@@ -102,27 +101,19 @@ class DeviceControlsTile @Inject constructor(
}
override fun handleDestroy() {
- dismissDialog()
super.handleDestroy()
}
- private fun createDialog() {
- if (controlsDialog?.isShowing != true) {
- controlsDialog = dialogProvider.get()
- }
- }
-
- private fun dismissDialog() {
- controlsDialog?.dismiss()?.also {
- controlsDialog = null
- }
- }
-
override fun handleClick() {
if (state.state == Tile.STATE_ACTIVE) {
mUiHandler.post {
- createDialog()
- controlsDialog?.show(controlsComponent.getControlsUiController().get())
+ mHost.collapsePanels()
+ val i = Intent().apply {
+ component = ComponentName(mContext, ControlsActivity::class.java)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ putExtra(ControlsUiController.BACK_TO_GLOBAL_ACTIONS, false)
+ }
+ mContext.startActivity(i)
}
}
}
@@ -133,9 +124,6 @@ class DeviceControlsTile @Inject constructor(
state.contentDescription = state.label
state.icon = icon
if (controlsComponent.isEnabled() && hasControlsApps.get()) {
- if (controlsDialog == null) {
- mUiHandler.post(this::createDialog)
- }
if (controlsComponent.getVisibility() == AVAILABLE) {
state.state = Tile.STATE_ACTIVE
state.secondaryLabel = ""
@@ -146,7 +134,6 @@ class DeviceControlsTile @Inject constructor(
state.stateDescription = state.secondaryLabel
} else {
state.state = Tile.STATE_UNAVAILABLE
- dismissDialog()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index ccd9548b269f..9363b24817e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -17,6 +17,8 @@
package com.android.systemui.qs.tiles
import android.os.Handler
+import android.content.Context
+import android.content.Intent
import android.provider.Settings
import android.service.quicksettings.Tile
import android.testing.AndroidTestingRunner
@@ -30,7 +32,6 @@ import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.management.ControlsListingController
-import com.android.systemui.controls.ui.ControlsDialog
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -50,7 +51,9 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.doNothing
import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -80,8 +83,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
private lateinit var controlsController: ControlsController
@Mock
private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var controlsDialog: ControlsDialog
private lateinit var globalSettings: GlobalSettings
@Mock
private lateinit var serviceInfo: ControlsServiceInfo
@@ -95,6 +96,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
private lateinit var tile: DeviceControlsTile
private lateinit var secureSettings: SecureSettings
+ private lateinit var spiedContext: Context
private var featureEnabled = true
@Before
@@ -103,7 +105,9 @@ class DeviceControlsTileTest : SysuiTestCase() {
testableLooper = TestableLooper.get(this)
secureSettings = FakeSettings()
- `when`(qsHost.context).thenReturn(mContext)
+ spiedContext = spy(mContext)
+ doNothing().`when`(spiedContext).startActivity(any(Intent::class.java))
+ `when`(qsHost.context).thenReturn(spiedContext)
`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
`when`(controlsController.available).thenReturn(true)
`when`(controlsComponent.isEnabled()).thenReturn(true)
@@ -276,7 +280,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile.click()
testableLooper.processAllMessages()
- verify(controlsDialog, never()).show(any(ControlsUiController::class.java))
+ verify(spiedContext, never()).startActivity(any(Intent::class.java))
}
@Test
@@ -293,7 +297,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile.click()
testableLooper.processAllMessages()
- verify(controlsDialog).show(controlsUiController)
+ verify(spiedContext).startActivity(any(Intent::class.java))
}
@Test
@@ -311,25 +315,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile.click()
testableLooper.processAllMessages()
- verify(controlsDialog, never()).show(any(ControlsUiController::class.java))
- }
-
- @Test
- fun testDialogDismissedOnDestroy() {
- verify(controlsListingController).observe(
- any(LifecycleOwner::class.java),
- capture(listingCallbackCaptor)
- )
-
- listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
- testableLooper.processAllMessages()
-
- tile.click()
- testableLooper.processAllMessages()
-
- tile.destroy()
- testableLooper.processAllMessages()
- verify(controlsDialog).dismiss()
+ verify(spiedContext, never()).startActivity(any(Intent::class.java))
}
private fun createTile(): DeviceControlsTile {
@@ -343,7 +329,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
qsLogger,
controlsComponent,
featureFlags,
- { controlsDialog },
globalSettings
)
}