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

Commit 279357e3 authored by Chris Göllner's avatar Chris Göllner Committed by Android (Google) Code Review
Browse files

Merge "[Status Bar] Bottom margin command" into main

parents c7cb41b1 8d6a7750
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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

import android.view.Surface
import android.view.Surface.Rotation
import com.android.systemui.statusbar.commandline.ParseableCommand
import com.android.systemui.statusbar.commandline.Type
import java.io.PrintWriter

class StatusBarInsetsCommand(
    private val callback: Callback,
) : ParseableCommand(NAME) {

    val bottomMargin: BottomMarginCommand? by subCommand(BottomMarginCommand())

    override fun execute(pw: PrintWriter) {
        callback.onExecute(command = this, pw)
    }

    interface Callback {
        fun onExecute(command: StatusBarInsetsCommand, printWriter: PrintWriter)
    }

    companion object {
        const val NAME = "status-bar-insets"
    }
}

class BottomMarginCommand : ParseableCommand(NAME) {

    private val rotationDegrees: Int? by
        param(
            longName = "rotation",
            shortName = "r",
            description = "For which rotation the margin should be set. One of 0, 90, 180, 270",
            valueParser = Type.Int,
        )

    @Rotation
    val rotationValue: Int?
        get() = ROTATION_DEGREES_TO_VALUE_MAPPING[rotationDegrees]

    val marginBottomDp: Float? by
        param(
            longName = "margin",
            shortName = "m",
            description = "Margin amount, in dp. Can be a fractional value, such as 10.5",
            valueParser = Type.Float,
        )

    override fun execute(pw: PrintWriter) {
        // Not needed for a subcommand
    }

    companion object {
        const val NAME = "bottom-margin"
        private val ROTATION_DEGREES_TO_VALUE_MAPPING =
            mapOf(
                0 to Surface.ROTATION_0,
                90 to Surface.ROTATION_90,
                180 to Surface.ROTATION_180,
                270 to Surface.ROTATION_270,
            )

        val ROTATION_DEGREES_OPTIONS: Set<Int> = ROTATION_DEGREES_TO_VALUE_MAPPING.keys
    }
}
+46 −1
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ import com.android.systemui.util.leak.RotationUtils.Rotation
import com.android.systemui.util.leak.RotationUtils.getExactRotation
import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation
import com.android.app.tracing.traceSection
import com.android.systemui.BottomMarginCommand
import com.android.systemui.StatusBarInsetsCommand
import com.android.systemui.statusbar.commandline.CommandRegistry
import java.io.PrintWriter
import java.lang.Math.max
import javax.inject.Inject
@@ -64,7 +67,8 @@ import javax.inject.Inject
class StatusBarContentInsetsProvider @Inject constructor(
    val context: Context,
    val configurationController: ConfigurationController,
    val dumpManager: DumpManager
    val dumpManager: DumpManager,
    val commandRegistry: CommandRegistry,
) : CallbackController<StatusBarContentInsetsChangedListener>,
        ConfigurationController.ConfigurationListener,
        Dumpable {
@@ -80,6 +84,13 @@ class StatusBarContentInsetsProvider @Inject constructor(
    init {
        configurationController.addCallback(this)
        dumpManager.registerDumpable(TAG, this)
        commandRegistry.registerCommand(StatusBarInsetsCommand.NAME) {
            StatusBarInsetsCommand(object : StatusBarInsetsCommand.Callback {
                override fun onExecute(command: StatusBarInsetsCommand, printWriter: PrintWriter) {
                    executeCommand(command, printWriter)
                }
            })
        }
    }

    override fun addCallback(listener: StatusBarContentInsetsChangedListener) {
@@ -271,8 +282,41 @@ class StatusBarContentInsetsProvider @Inject constructor(
                statusBarContentHeight)
    }

    private fun executeCommand(command: StatusBarInsetsCommand, printWriter: PrintWriter) {
        command.bottomMargin?.let { executeBottomMarginCommand(it, printWriter) }
    }

    private fun executeBottomMarginCommand(command: BottomMarginCommand, printWriter: PrintWriter) {
        val rotation = command.rotationValue
        if (rotation == null) {
            printWriter.println(
                    "Rotation should be one of ${BottomMarginCommand.ROTATION_DEGREES_OPTIONS}"
            )
            return
        }
        val marginBottomDp = command.marginBottomDp
        if (marginBottomDp == null) {
            printWriter.println("Margin bottom not set.")
            return
        }
        setBottomMarginOverride(rotation, marginBottomDp)
    }

    private val marginBottomOverrides = mutableMapOf<Int, Int>()

    private fun setBottomMarginOverride(rotation: Int, marginBottomDp: Float) {
        insetsCache.evictAll()
        val marginBottomPx = (marginBottomDp * context.resources.displayMetrics.density).toInt()
        marginBottomOverrides[rotation] = marginBottomPx
        notifyInsetsChanged()
    }

    @Px
    private fun getBottomAlignedMargin(targetRotation: Int, resources: Resources): Int {
        val override = marginBottomOverrides[targetRotation]
        if (override != null) {
            return override
        }
        val dimenRes =
                when (targetRotation) {
                    Surface.ROTATION_0 -> R.dimen.status_bar_bottom_aligned_margin_rotation_0
@@ -294,6 +338,7 @@ class StatusBarContentInsetsProvider @Inject constructor(
            pw.println("$key -> $rect")
        }
        pw.println(insetsCache)
        pw.println("Bottom margin overrides: $marginBottomOverrides")
    }

    private fun getCacheKey(
+7 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.view.DisplayCutout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.leak.RotationUtils
import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
@@ -31,6 +32,7 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
import com.android.systemui.util.leak.RotationUtils.Rotation
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertTrue
@@ -39,7 +41,6 @@ import org.junit.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations

@SmallTest
@@ -556,7 +557,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    fun testDisplayChanged_returnsUpdatedInsets() {
        // GIVEN: get insets on the first display and switch to the second display
        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
            mock(DumpManager::class.java))
            mock<DumpManager>(), mock<CommandRegistry>())

        configuration.windowConfiguration.setMaxBounds(Rect(0, 0, 1080, 2160))
        val firstDisplayInsets = provider.getStatusBarContentAreaForRotation(ROTATION_NONE)
@@ -575,7 +576,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
        // GIVEN: get insets on the first display, switch to the second display,
        // get insets and switch back
        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
            mock(DumpManager::class.java))
            mock<DumpManager>(), mock<CommandRegistry>())

        configuration.windowConfiguration.setMaxBounds(Rect(0, 0, 1080, 2160))
        val firstDisplayInsetsFirstCall = provider
@@ -601,7 +602,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
        configuration.windowConfiguration.setMaxBounds(0, 0, 100, 100)
        configurationController.onConfigurationChanged(configuration)
        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
                mock(DumpManager::class.java))
                mock<DumpManager>(), mock<CommandRegistry>())
        val listener = object : StatusBarContentInsetsChangedListener {
            var triggered = false

@@ -623,7 +624,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    fun onDensityOrFontScaleChanged_listenerNotified() {
        configuration.densityDpi = 12
        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
                mock(DumpManager::class.java))
                mock<DumpManager>(), mock<CommandRegistry>())
        val listener = object : StatusBarContentInsetsChangedListener {
            var triggered = false

@@ -644,7 +645,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    @Test
    fun onThemeChanged_listenerNotified() {
        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
                mock(DumpManager::class.java))
                mock<DumpManager>(), mock<CommandRegistry>())
        val listener = object : StatusBarContentInsetsChangedListener {
            var triggered = false