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

Commit 1e345178 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I5b86508e,I01cd3be5,I5f21d737,Ibae88dbf into tm-qpr-dev

* changes:
  [Media TTT] Put package error logs in the log buffer with all the other logs.
  [Media TTT] Also log the package name on each state change.
  [Media TTT] Ignore the FAR_FROM_RECEIVER event if we're in the succeeded state.
  [Chipbar] Remove #setIcon from TemporaryViewDisplayController and put it in MediaTttUtils instead.
parents 7eb3933a ab8f9513
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -28,28 +28,41 @@ class MediaTttLogger(
    private val deviceTypeTag: String,
    private val buffer: LogBuffer
){
    private val bufferTag = BASE_TAG + deviceTypeTag

    /** Logs a change in the chip state for the given [mediaRouteId]. */
    fun logStateChange(stateName: String, mediaRouteId: String) {
    fun logStateChange(stateName: String, mediaRouteId: String, packageName: String?) {
        buffer.log(
            BASE_TAG + deviceTypeTag,
            bufferTag,
            LogLevel.DEBUG,
            {
                str1 = stateName
                str2 = mediaRouteId
                str3 = packageName
            },
            { "State changed to $str1 for ID=$str2" }
            { "State changed to $str1 for ID=$str2 package=$str3" }
        )
    }

    /** Logs that we removed the chip for the given [reason]. */
    fun logChipRemoval(reason: String) {
        buffer.log(
            BASE_TAG + deviceTypeTag,
            bufferTag,
            LogLevel.DEBUG,
            { str1 = reason },
            { "Chip removed due to $str1" }
        )
    }

    /** Logs that we couldn't find information for [packageName]. */
    fun logPackageNotFound(packageName: String) {
        buffer.log(
            bufferTag,
            LogLevel.DEBUG,
            { str1 = packageName },
            { "Package $str1 could not be found" }
        )
    }
}

private const val BASE_TAG = "MediaTtt"
+107 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.media.taptotransfer.common

import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import com.android.internal.widget.CachingIconView
import com.android.settingslib.Utils
import com.android.systemui.R

/** Utility methods for media tap-to-transfer. */
class MediaTttUtils {
    companion object {
        /**
         * Returns the information needed to display the icon.
         *
         * The information will either contain app name and icon of the app playing media, or a
         * default name and icon if we can't find the app name/icon.
         *
         * @param appPackageName the package name of the app playing the media.
         * @param logger the logger to use for any errors.
         */
        fun getIconInfoFromPackageName(
            context: Context,
            appPackageName: String?,
            logger: MediaTttLogger
        ): IconInfo {
            if (appPackageName != null) {
                try {
                    val contentDescription =
                        context.packageManager
                            .getApplicationInfo(
                                appPackageName,
                                PackageManager.ApplicationInfoFlags.of(0)
                            )
                            .loadLabel(context.packageManager)
                            .toString()
                    return IconInfo(
                        contentDescription,
                        drawable = context.packageManager.getApplicationIcon(appPackageName),
                        isAppIcon = true
                    )
                } catch (e: PackageManager.NameNotFoundException) {
                    logger.logPackageNotFound(appPackageName)
                }
            }
            return IconInfo(
                contentDescription =
                    context.getString(R.string.media_output_dialog_unknown_launch_app_name),
                drawable =
                    context.resources.getDrawable(R.drawable.ic_cast).apply {
                        this.setTint(
                            Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)
                        )
                    },
                isAppIcon = false
            )
        }

        /**
         * Sets an icon to be displayed by the given view.
         *
         * @param iconSize the size in pixels that the icon should be. If null, the size of
         * [appIconView] will not be adjusted.
         */
        fun setIcon(
            appIconView: CachingIconView,
            icon: Drawable,
            iconContentDescription: CharSequence,
            iconSize: Int? = null,
        ) {
            iconSize?.let { size ->
                val lp = appIconView.layoutParams
                lp.width = size
                lp.height = size
                appIconView.layoutParams = lp
            }

            appIconView.contentDescription = iconContentDescription
            appIconView.setImageDrawable(icon)
        }
    }
}

data class IconInfo(
    val contentDescription: String,
    val drawable: Drawable,
    /**
     * True if [drawable] is the app's icon, and false if [drawable] is some generic default icon.
     */
    val isAppIcon: Boolean
)
+21 −16
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttUtils
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
@@ -107,7 +108,7 @@ class MediaTttChipControllerReceiver @Inject constructor(
    ) {
        val chipState: ChipStateReceiver? = ChipStateReceiver.getReceiverStateFromId(displayState)
        val stateName = chipState?.name ?: "Invalid"
        logger.logStateChange(stateName, routeInfo.id)
        logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName)

        if (chipState == null) {
            Log.e(RECEIVER_TAG, "Unhandled MediaTransferReceiverState $displayState")
@@ -137,13 +138,26 @@ class MediaTttChipControllerReceiver @Inject constructor(

    override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) {
        super.updateView(newInfo, currentView)
        val iconName = setIcon(
                currentView,
                newInfo.routeInfo.clientPackageName,
                newInfo.appIconDrawableOverride,
                newInfo.appNameOverride

        val iconInfo = MediaTttUtils.getIconInfoFromPackageName(
            context, newInfo.routeInfo.clientPackageName, logger
        )
        val iconDrawable = newInfo.appIconDrawableOverride ?: iconInfo.drawable
        val iconContentDescription = newInfo.appNameOverride ?: iconInfo.contentDescription
        val iconSize = context.resources.getDimensionPixelSize(
            if (iconInfo.isAppIcon) {
                R.dimen.media_ttt_icon_size_receiver
            } else {
                R.dimen.media_ttt_generic_icon_size_receiver
            }
        )

        MediaTttUtils.setIcon(
            currentView.requireViewById(R.id.app_icon),
            iconDrawable,
            iconContentDescription,
            iconSize,
        )
        currentView.contentDescription = iconName
    }

    override fun animateViewIn(view: ViewGroup) {
@@ -161,15 +175,6 @@ class MediaTttChipControllerReceiver @Inject constructor(
        startRipple(view.requireViewById(R.id.ripple))
    }

    override fun getIconSize(isAppIcon: Boolean): Int? =
        context.resources.getDimensionPixelSize(
            if (isAppIcon) {
                R.dimen.media_ttt_icon_size_receiver
            } else {
                R.dimen.media_ttt_generic_icon_size_receiver
            }
        )

    /** Returns the amount that the chip will be translated by in its intro animation. */
    private fun getTranslationAmount(): Int {
        return context.resources.getDimensionPixelSize(R.dimen.media_ttt_receiver_vert_translation)
+14 −11
Original line number Diff line number Diff line
@@ -34,8 +34,7 @@ import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
 * @property stateInt the integer from [StatusBarManager] corresponding with this state.
 * @property stringResId the res ID of the string that should be displayed in the chip. Null if the
 *   state should not have the chip be displayed.
 * @property isMidTransfer true if the state represents that a transfer is currently ongoing.
 * @property isTransferFailure true if the state represents that the transfer has failed.
 * @property transferStatus the transfer status that the chip state represents.
 * @property timeout the amount of time this chip should display on the screen before it times out
 *   and disappears.
 */
@@ -43,8 +42,7 @@ enum class ChipStateSender(
    @StatusBarManager.MediaTransferSenderState val stateInt: Int,
    val uiEvent: UiEventLogger.UiEventEnum,
    @StringRes val stringResId: Int?,
    val isMidTransfer: Boolean = false,
    val isTransferFailure: Boolean = false,
    val transferStatus: TransferStatus,
    val timeout: Long = DEFAULT_TIMEOUT_MILLIS
) {
    /**
@@ -56,6 +54,7 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST,
        R.string.media_move_closer_to_start_cast,
        transferStatus = TransferStatus.NOT_STARTED,
    ),

    /**
@@ -68,6 +67,7 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST,
        R.string.media_move_closer_to_end_cast,
        transferStatus = TransferStatus.NOT_STARTED,
    ),

    /**
@@ -78,7 +78,7 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED,
        R.string.media_transfer_playing_different_device,
        isMidTransfer = true,
        transferStatus = TransferStatus.IN_PROGRESS,
        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
    ),

@@ -90,7 +90,7 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
        R.string.media_transfer_playing_this_device,
        isMidTransfer = true,
        transferStatus = TransferStatus.IN_PROGRESS,
        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
    ),

@@ -100,7 +100,8 @@ enum class ChipStateSender(
    TRANSFER_TO_RECEIVER_SUCCEEDED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED,
        R.string.media_transfer_playing_different_device
        R.string.media_transfer_playing_different_device,
        transferStatus = TransferStatus.SUCCEEDED,
    ) {
        override fun undoClickListener(
            controllerSender: MediaTttChipControllerSender,
@@ -135,7 +136,8 @@ enum class ChipStateSender(
    TRANSFER_TO_THIS_DEVICE_SUCCEEDED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
        R.string.media_transfer_playing_this_device
        R.string.media_transfer_playing_this_device,
        transferStatus = TransferStatus.SUCCEEDED,
    ) {
        override fun undoClickListener(
            controllerSender: MediaTttChipControllerSender,
@@ -169,7 +171,7 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED,
        R.string.media_transfer_failed,
        isTransferFailure = true
        transferStatus = TransferStatus.FAILED,
    ),

    /** A state representing that a transfer back to this device has failed. */
@@ -177,14 +179,15 @@ enum class ChipStateSender(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED,
        R.string.media_transfer_failed,
        isTransferFailure = true
        transferStatus = TransferStatus.FAILED,
    ),

    /** A state representing that this device is far away from any receiver device. */
    FAR_FROM_RECEIVER(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER,
        stringResId = null
        stringResId = null,
        transferStatus = TransferStatus.TOO_FAR,
    );

    /**
+21 −9
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.animation.ViewHierarchyAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttUtils
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason
@@ -94,7 +95,7 @@ class MediaTttChipControllerSender @Inject constructor(
    ) {
        val chipState: ChipStateSender? = ChipStateSender.getSenderStateFromId(displayState)
        val stateName = chipState?.name ?: "Invalid"
        logger.logStateChange(stateName, routeInfo.id)
        logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName)

        if (chipState == null) {
            Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState")
@@ -118,7 +119,14 @@ class MediaTttChipControllerSender @Inject constructor(
        val chipState = newInfo.state

        // App icon
        val iconName = setIcon(currentView, newInfo.routeInfo.clientPackageName)
        val iconInfo = MediaTttUtils.getIconInfoFromPackageName(
            context, newInfo.routeInfo.clientPackageName, logger
        )
        MediaTttUtils.setIcon(
            currentView.requireViewById(R.id.app_icon),
            iconInfo.drawable,
            iconInfo.contentDescription
        )

        // Text
        val otherDeviceName = newInfo.routeInfo.name.toString()
@@ -127,7 +135,7 @@ class MediaTttChipControllerSender @Inject constructor(

        // Loading
        currentView.requireViewById<View>(R.id.loading).visibility =
            chipState.isMidTransfer.visibleIfTrue()
            (chipState.transferStatus == TransferStatus.IN_PROGRESS).visibleIfTrue()

        // Undo
        val undoView = currentView.requireViewById<View>(R.id.undo)
@@ -139,12 +147,12 @@ class MediaTttChipControllerSender @Inject constructor(

        // Failure
        currentView.requireViewById<View>(R.id.failure_icon).visibility =
            chipState.isTransferFailure.visibleIfTrue()
            (chipState.transferStatus == TransferStatus.FAILED).visibleIfTrue()

        // For accessibility
        currentView.requireViewById<ViewGroup>(
                R.id.media_ttt_sender_chip_inner
        ).contentDescription = "$iconName $chipText"
        ).contentDescription = "${iconInfo.contentDescription} $chipText"
    }

    override fun animateViewIn(view: ViewGroup) {
@@ -162,10 +170,14 @@ class MediaTttChipControllerSender @Inject constructor(
    }

    override fun removeView(removalReason: String) {
        // Don't remove the chip if we're mid-transfer since the user should still be able to
        // see the status of the transfer. (But do remove it if it's finally timed out.)
        if (info?.state?.isMidTransfer == true &&
                removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT) {
        // Don't remove the chip if we're in progress or succeeded, since the user should still be
        // able to see the status of the transfer. (But do remove it if it's finally timed out.)
        val transferStatus = info?.state?.transferStatus
        if (
            (transferStatus == TransferStatus.IN_PROGRESS ||
                transferStatus == TransferStatus.SUCCEEDED) &&
            removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT
        ) {
            return
        }
        super.removeView(removalReason)
Loading