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

Commit 47acb582 authored by Anton Potapov's avatar Anton Potapov
Browse files

Add window configuration for the new Volume Dialog

Flag: com.android.systemui.volume_redesign
Test: passes presubmits
Bug: 369994090
Change-Id: I43e2245d189c7e8448fd0f5c9d162d05dd8562ef
parent a90ea9c8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -540,6 +540,7 @@
    <!-- Overridden by values-television/styles.xml with tv-specific settings -->
    <style name="volume_dialog_theme" parent="Theme.SystemUI">
        <item name="android:windowIsFloating">true</item>
        <item name="android:showWhenLocked">true</item>
    </style>

    <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"/>
+33 −0
Original line number Diff line number Diff line
@@ -14,21 +14,20 @@
 * limitations under the License.
 */

package com.android.systemui.volume.dialog
package com.android.systemui.statusbar.policy

import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.ContextThemeWrapper
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
import javax.inject.Inject
import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onStart

class NewVolumeDialog @Inject constructor(@Application context: Context) :
    Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.volume_dialog)
    }
/** [DevicePostureController.getDevicePosture] as a [Flow]. */
@DevicePostureInt
fun DevicePostureController.devicePosture(): Flow<Int> =
    conflatedCallbackFlow {
            val callback = DevicePostureController.Callback { posture -> trySend(posture) }
            addCallback(callback)
            awaitClose { removeCallback(callback) }
        }
        .onStart { emit(devicePosture) }
+0 −67
Original line number Diff line number Diff line
/*
 * 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.volume.dialog

import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.plugins.VolumeDialog
import com.android.systemui.volume.dialog.dagger.VolumeDialogComponent
import com.android.systemui.volume.dialog.dagger.VolumeDialogPluginComponent
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch

class NewVolumeDialogPlugin
@Inject
constructor(
    @Application private val applicationCoroutineScope: CoroutineScope,
    private val volumeDialogPluginComponentFactory: VolumeDialogPluginComponent.Factory,
) : VolumeDialog {

    private var volumeDialogPluginComponent: VolumeDialogPluginComponent? = null
    private var job: Job? = null

    override fun init(windowType: Int, callback: VolumeDialog.Callback?) {
        job =
            applicationCoroutineScope.launch {
                coroutineScope {
                    volumeDialogPluginComponent = volumeDialogPluginComponentFactory.create(this)
                }
            }
    }

    private fun showDialog() {
        val volumeDialogPluginComponent =
            volumeDialogPluginComponent ?: error("Creating dialog before init was called")
        volumeDialogPluginComponent.coroutineScope().launch {
            coroutineScope {
                val volumeDialogComponent: VolumeDialogComponent =
                    volumeDialogPluginComponent.volumeDialogComponentFactory().create(this)
                with(volumeDialogComponent.volumeDialog()) {
                    setOnDismissListener { volumeDialogComponent.coroutineScope().cancel() }
                    show()
                }
            }
        }
    }

    override fun destroy() {
        job?.cancel()
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -22,13 +22,16 @@ import android.os.Bundle
import android.view.ContextThemeWrapper
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.ui.binder.VolumeDialogBinder
import javax.inject.Inject

class VolumeDialog @Inject constructor(@Application context: Context) :
class VolumeDialog
@Inject
constructor(@Application context: Context, private val dialogBinder: VolumeDialogBinder) :
    Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.volume_dialog)
        dialogBinder.bind(this)
    }
}
+86 −0
Original line number Diff line number Diff line
/*
 * 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.volume.dialog.ui.binder

import android.app.Dialog
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.lifecycle.lifecycleScope
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogGravityViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

@VolumeDialogScope
class VolumeDialogBinder
@Inject
constructor(
    @VolumeDialog private val coroutineScope: CoroutineScope,
    private val volumeDialogViewBinder: VolumeDialogViewBinder,
    private val gravityViewModel: VolumeDialogGravityViewModel,
) {

    fun bind(dialog: Dialog) {
        with(dialog) {
            setupWindow(window!!)
            dialog.setContentView(R.layout.volume_dialog)

            val volumeDialogView: View = dialog.requireViewById(R.id.volume_dialog_container)
            volumeDialogView.repeatWhenAttached {
                lifecycleScope.launch { volumeDialogViewBinder.bind(volumeDialogView) }
            }
        }
    }

    /** Configures [Window] for the [Dialog]. */
    private fun setupWindow(window: Window) =
        with(window) {
            clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
            addFlags(
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
                    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
            )
            addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)

            requestFeature(Window.FEATURE_NO_TITLE)
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
            setWindowAnimations(-1)
            setFormat(PixelFormat.TRANSLUCENT)

            attributes =
                attributes.apply {
                    title = "VolumeDialog" // Not the same as Window#setTitle
                }
            setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)

            gravityViewModel.dialogGravity.onEach { window.setGravity(it) }.launchIn(coroutineScope)
        }
}
Loading