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

Commit 4e0bac82 authored by Michal Brzezinski's avatar Michal Brzezinski
Browse files

Moving media player in split shade mode on the lockscreen to the left side

Bug: 181882240
Test: manual
Change-Id: Ib75869971168b3a514b961262ee8a02659f8ae74
parent 6b095216
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -20,12 +20,14 @@
<!-- This is a view that shows general status information in Keyguard. -->
<com.android.keyguard.KeyguardStatusView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/keyguard_status_view"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal|top">
    systemui:layout_constraintStart_toStartOf="parent"
    systemui:layout_constraintEnd_toEndOf="parent"
    systemui:layout_constraintTop_toTopOf="parent"
    android:layout_width="0dp"
    android:layout_height="wrap_content">
    <LinearLayout
        android:id="@+id/status_view_container"
        android:layout_width="match_parent"
@@ -70,5 +72,11 @@
            android:letterSpacing="0.05"
            android:ellipsize="marquee"
            android:singleLine="true" />
        <FrameLayout
            android:id="@+id/status_view_media_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/qs_media_padding"
            />
    </LinearLayout>
</com.android.keyguard.KeyguardStatusView>
+4 −4
Original line number Diff line number Diff line
@@ -37,10 +37,6 @@
        android:layout_height="match_parent"
        android:layout_width="match_parent" />

    <include
        layout="@layout/keyguard_status_view"
        android:visibility="gone" />

    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
        android:layout_width="match_parent"
        android:layout_height="match_parent"
@@ -49,6 +45,10 @@
        android:clipToPadding="false"
        android:clipChildren="false">

        <include
            layout="@layout/keyguard_status_view"
            android:visibility="gone"/>

        <include layout="@layout/dock_info_overlay" />

        <FrameLayout
+8 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import androidx.core.graphics.ColorUtils;

import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,6 +45,7 @@ import java.io.PrintWriter;
 * - keyguard clock
 * - logout button (on certain managed devices)
 * - owner information (if set)
 * - media player (split shade mode only)
 */
public class KeyguardStatusView extends GridLayout {
    private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -60,6 +62,7 @@ public class KeyguardStatusView extends GridLayout {
    private KeyguardSliceView mKeyguardSlice;
    private Runnable mPendingMarqueeStart;
    private Handler mHandler;
    private View mMediaHostContainer;

    private float mDarkAmount = 0;
    private int mTextColor;
@@ -148,6 +151,8 @@ public class KeyguardStatusView extends GridLayout {
        mKeyguardSlice.setContentChangeListener(this::onSliceContentChanged);
        onSliceContentChanged();

        mMediaHostContainer = findViewById(R.id.status_view_media_container);

        updateOwnerInfo();
        updateDark();
    }
@@ -223,6 +228,9 @@ public class KeyguardStatusView extends GridLayout {
        }
        mDarkAmount = darkAmount;
        mClockView.setDarkAmount(darkAmount);
        if (mMediaHostContainer.getVisibility() != View.GONE) {
            CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
        }
        updateDark();
    }

+85 −16
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.media

import android.view.View
import android.view.ViewGroup
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.dagger.MediaModule.KEYGUARD
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -29,8 +30,8 @@ import javax.inject.Inject
import javax.inject.Named

/**
 * A class that controls the media notifications on the lock screen, handles its visibility and
 * is responsible for the embedding of he media experience.
 * Controls the media notifications on the lock screen, handles its visibility and placement -
 * switches media player positioning between split pane container vs single pane container
 */
@SysUISingleton
class KeyguardMediaController @Inject constructor(
@@ -43,46 +44,114 @@ class KeyguardMediaController @Inject constructor(
    init {
        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
            override fun onStateChanged(newState: Int) {
                updateVisibility()
                refreshMediaPosition()
            }

            override fun onDozingChanged(isDozing: Boolean) {
                if (!isDozing) {
                    mediaHost.visible = true
                    refreshMediaPosition()
                }
            }
        })
    }

    var visibilityChangedListener: ((Boolean) -> Unit)? = null
    var view: MediaHeaderView? = null

    /**
     * single pane media container placed at the top of the notifications list
     */
    var singlePaneContainer: MediaHeaderView? = null
        private set
    private var splitShadeContainer: ViewGroup? = null
    private var useSplitShadeContainer: () -> Boolean = { false }

    /**
     * Attach this controller to a media view, initializing its state
     * Attaches media container in single pane mode, situated at the top of the notifications list
     */
    fun attach(mediaView: MediaHeaderView) {
        view = mediaView
    fun attachSinglePaneContainer(mediaView: MediaHeaderView?) {
        singlePaneContainer = mediaView
        // First let's set the desired state that we want for this host
        mediaHost.addVisibilityChangeListener { updateVisibility() }
        mediaHost.expansion = 0.0f
        mediaHost.expansion = MediaHostState.COLLAPSED
        mediaHost.showsOnlyActiveMedia = true
        mediaHost.falsingProtectionNeeded = true

        // Let's now initialize this view, which also creates the host view for us.
        mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
        mediaView.setContentView(mediaHost.hostView)
        // Required to show it for the first time, afterwards visibility is managed automatically
        mediaHost.visible = true
        mediaHost.addVisibilityChangeListener { visible ->
            refreshMediaPosition()
            if (visible) {
                mediaHost.hostView.layoutParams.apply {
                    height = ViewGroup.LayoutParams.WRAP_CONTENT
                    width = ViewGroup.LayoutParams.MATCH_PARENT
                }
            }
        }
        refreshMediaPosition()
    }

        // Ensure the visibility is correct
        updateVisibility()
    /**
     * Attaches media container in split shade mode, situated to the left of notifications
     */
    fun attachSplitShadeContainer(container: ViewGroup, useContainer: () -> Boolean) {
        splitShadeContainer = container
        useSplitShadeContainer = useContainer
    }

    private fun updateVisibility() {
    fun refreshMediaPosition() {
        val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
                statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
        // mediaHost.visible required for proper animations handling
        val shouldBeVisible = mediaHost.visible &&
                !bypassController.bypassEnabled &&
                keyguardOrUserSwitcher &&
                notifLockscreenUserManager.shouldShowLockscreenNotifications()
        val previousVisibility = view?.visibility ?: View.GONE
        val newVisibility = if (shouldBeVisible) View.VISIBLE else View.GONE
        if (shouldBeVisible) {
            showMediaPlayer()
        } else {
            hideMediaPlayer()
        }
    }

    private fun showMediaPlayer() {
        if (useSplitShadeContainer()) {
            showMediaPlayer(
                    activeContainer = splitShadeContainer,
                    inactiveContainer = singlePaneContainer)
        } else {
            showMediaPlayer(
                    activeContainer = singlePaneContainer,
                    inactiveContainer = splitShadeContainer)
        }
    }

    private fun showMediaPlayer(activeContainer: ViewGroup?, inactiveContainer: ViewGroup?) {
        if (inactiveContainer?.childCount == 1) {
            inactiveContainer.removeAllViews()
        }
        // might be called a few times for the same view, no need to add hostView again
        if (activeContainer?.childCount == 0) {
            activeContainer.addView(mediaHost.hostView)
        }
        setVisibility(activeContainer, View.VISIBLE)
        setVisibility(inactiveContainer, View.GONE)
    }

    private fun hideMediaPlayer() {
        if (useSplitShadeContainer()) {
            setVisibility(splitShadeContainer, View.GONE)
        } else {
            setVisibility(singlePaneContainer, View.GONE)
        }
    }

    private fun setVisibility(view: ViewGroup?, newVisibility: Int) {
        val previousVisibility = view?.visibility
        view?.visibility = newVisibility
        if (previousVisibility != newVisibility) {
            visibilityChangedListener?.invoke(shouldBeVisible)
            visibilityChangedListener?.invoke(newVisibility == View.VISIBLE)
        }
    }
}
 No newline at end of file
+8 −3
Original line number Diff line number Diff line
@@ -264,15 +264,20 @@ class MediaHost constructor(
 */
interface MediaHostState {

    companion object {
        const val EXPANDED: Float = 1.0f
        const val COLLAPSED: Float = 0.0f
    }

    /**
     * The last measurement input that this state was measured with. Infers with and height of
     * The last measurement input that this state was measured with. Infers width and height of
     * the players.
     */
    var measurementInput: MeasurementInput?

    /**
     * The expansion of the player, 0 for fully collapsed (up to 3 actions), 1 for fully expanded
     * (up to 5 actions.)
     * The expansion of the player, [COLLAPSED] for fully collapsed (up to 3 actions),
     * [EXPANDED] for fully expanded (up to 5 actions).
     */
    var expansion: Float

Loading