Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6436573 authored by Lyn Han's avatar Lyn Han Committed by Android (Google) Code Review
Browse files

Merge "Add FSI view binder and wm config" into tm-qpr-dev

parents d5a4b9e5 092a6647
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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
+99 −0
Original line number Diff line number Diff line
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)
    }
}
+75 −0
Original line number Diff line number Diff line
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
        }
    }
}