summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt75
3 files changed, 181 insertions, 0 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 4db77abacd69..8012dea643fb 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -43,6 +43,7 @@ import com.android.systemui.shortcut.ShortcutKeyDispatcher
import com.android.systemui.statusbar.notification.fsi.FsiChromeRepo
import com.android.systemui.statusbar.notification.InstantAppNotifier
import com.android.systemui.statusbar.notification.fsi.FsiChromeViewModelFactory
+import com.android.systemui.statusbar.notification.fsi.FsiChromeViewBinder
import com.android.systemui.statusbar.phone.KeyguardLiftController
import com.android.systemui.stylus.StylusUsiPowerStartable
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -93,6 +94,12 @@ abstract class SystemUICoreStartableModule {
@ClassKey(FsiChromeViewModelFactory::class)
abstract fun bindFSIChromeWindowViewModel(sysui: FsiChromeViewModelFactory): CoreStartable
+ /** Inject into FsiChromeWindowBinder. */
+ @Binds
+ @IntoMap
+ @ClassKey(FsiChromeViewBinder::class)
+ abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable
+
/** Inject into GarbageMonitor.Service. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
new file mode 100644
index 000000000000..1a3927ba9b06
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
@@ -0,0 +1,99 @@
+package com.android.systemui.statusbar.notification.fsi
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.WindowManager
+import com.android.systemui.CoreStartable
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+@SysUISingleton
+class FsiChromeViewBinder
+@Inject
+constructor(
+ val context: Context,
+ val windowManager: WindowManager,
+ val viewModelFactory: FsiChromeViewModelFactory,
+ val layoutInflater: LayoutInflater,
+ val centralSurfaces: CentralSurfaces,
+ @Main val mainExecutor: Executor,
+ @Application val scope: CoroutineScope,
+) : CoreStartable {
+
+ companion object {
+ private const val classTag = "FsiChromeViewBinder"
+ }
+
+ private val fsiChromeView =
+ layoutInflater.inflate(R.layout.fsi_chrome_view, null /* root */, false /* attachToRoot */)
+ as FsiChromeView
+
+ var addedToWindowManager = false
+ var cornerRadius: Int = context.resources.getDimensionPixelSize(
+ R.dimen.notification_corner_radius)
+
+ override fun start() {
+ val methodTag = "start"
+ log("$classTag $methodTag ")
+
+ scope.launch {
+ log("$classTag $methodTag launch ")
+ viewModelFactory.viewModelFlow.collect { vm -> updateForViewModel(vm) }
+ }
+ }
+
+ private fun updateForViewModel(vm: FsiChromeViewModel?) {
+ val methodTag = "updateForViewModel"
+
+ if (vm == null) {
+ log("$classTag $methodTag viewModel is null, removing from window manager")
+
+ if (addedToWindowManager) {
+ windowManager.removeView(fsiChromeView)
+ addedToWindowManager = false
+ }
+ return
+ }
+
+ bindViewModel(vm, windowManager)
+
+ if (addedToWindowManager) {
+ log("$classTag $methodTag already addedToWindowManager")
+ } else {
+ windowManager.addView(fsiChromeView, FsiTaskViewConfig.getWmLayoutParams("PackageName"))
+ addedToWindowManager = true
+ }
+ }
+
+ private fun bindViewModel(
+ vm: FsiChromeViewModel,
+ windowManager: WindowManager,
+ ) {
+ log("$classTag bindViewModel")
+
+ fsiChromeView.appIconImageView.setImageDrawable(vm.appIcon)
+ fsiChromeView.appNameTextView.text = vm.appName
+
+ fsiChromeView.dismissButton.setOnClickListener { vm.onDismiss() }
+ fsiChromeView.fullscreenButton.setOnClickListener { vm.onFullscreen() }
+
+ vm.taskView.cornerRadius = cornerRadius.toFloat()
+ vm.taskView.startActivity(
+ vm.fsi,
+ FsiTaskViewConfig.getFillInIntent(),
+ FsiTaskViewConfig.getActivityOptions(context, windowManager),
+ FsiTaskViewConfig.getLaunchBounds(windowManager)
+ )
+
+ log("$classTag bindViewModel started taskview activity")
+ fsiChromeView.addView(vm.taskView)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
new file mode 100644
index 000000000000..034ab56d5a65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
@@ -0,0 +1,75 @@
+package com.android.systemui.statusbar.notification.fsi
+
+import android.app.ActivityOptions
+import android.content.Context
+import android.content.Intent
+import android.graphics.PixelFormat
+import android.graphics.Rect
+import android.os.Binder
+import android.view.ViewGroup
+import android.view.WindowManager
+
+/**
+ * Config for adding the FsiChromeView window to WindowManager and starting the FSI activity.
+ */
+class FsiTaskViewConfig {
+
+ companion object {
+
+ private const val classTag = "FsiTaskViewConfig"
+
+ fun getWmLayoutParams(packageName: String): WindowManager.LayoutParams {
+ val params: WindowManager.LayoutParams?
+ params =
+ WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
+ WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
+ PixelFormat.TRANSLUCENT
+ )
+ params.setTrustedOverlay()
+ params.fitInsetsTypes = 0
+ params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+ params.token = Binder()
+ params.packageName = packageName
+ params.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ params.privateFlags =
+ params.privateFlags or WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
+ return params
+ }
+
+ fun getFillInIntent(): Intent {
+ val fillInIntent = Intent()
+ fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+ fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ // FLAG_ACTIVITY_NEW_TASK is auto-applied because
+ // we're starting the FSI activity from a non-Activity context
+ return fillInIntent
+ }
+
+ fun getLaunchBounds(windowManager: WindowManager): Rect {
+ // TODO(b/243421660) check this works for non-resizeable activity
+ return Rect()
+ }
+
+ fun getActivityOptions(context: Context, windowManager: WindowManager): ActivityOptions {
+ // Custom options so there is no activity transition animation
+ val options =
+ ActivityOptions.makeCustomAnimation(context, 0 /* enterResId */, 0 /* exitResId */)
+
+ options.taskAlwaysOnTop = true
+
+ options.pendingIntentLaunchFlags =
+ Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
+ Intent.FLAG_ACTIVITY_NEW_TASK
+
+ options.launchBounds = getLaunchBounds(windowManager)
+ return options
+ }
+ }
+}