Add FSI view binder and wm config
Bug: 243421660 Test: visual Change-Id: I39ede9bc83ebd6710ff4441282dc2072165c7521
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user