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

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

Merge changes Ibb968d5c,I38521e9a

* changes:
  [Media TTT] Add the #transferToReceiverTriggered callback.
  [Media TTT] Don't use futures for determining whether a transfer has succeeded or not.
parents c11852d4 60bb228f
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -60,6 +60,18 @@ interface IDeviceSenderCallback {
    oneway void closeToReceiverToEndCast(
        in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);

    /**
     * Invoke to notify System UI that a media transfer from this device (the sender) to a receiver
     * device has been started.
     *
     * Important notes:
     *   - This callback is for *starting* a cast. It should be used when this device is currently
     *     playing media locally and the media has started being transferred to the receiver device
     *     instead.
     */
    oneway void transferToReceiverTriggered(
        in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);

    /**
     * Invoke to notify System UI that the attempted transfer has failed.
     *
+4 −13
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@ import android.content.Context;
import android.view.WindowManager;

import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
@@ -33,10 +31,8 @@ import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerR
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender;
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderService;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.util.concurrency.DelayableExecutor;

import java.util.Optional;
import java.util.concurrent.Executor;

import javax.inject.Named;

@@ -89,14 +85,11 @@ public interface MediaModule {
    static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender(
            MediaTttFlags mediaTttFlags,
            Context context,
            WindowManager windowManager,
            @Main Executor mainExecutor,
            @Background Executor backgroundExecutor) {
            WindowManager windowManager) {
        if (!mediaTttFlags.isMediaTttEnabled()) {
            return Optional.empty();
        }
        return Optional.of(new MediaTttChipControllerSender(
                context, windowManager, mainExecutor, backgroundExecutor));
        return Optional.of(new MediaTttChipControllerSender(context, windowManager));
    }

    /** */
@@ -120,8 +113,7 @@ public interface MediaModule {
            CommandRegistry commandRegistry,
            Context context,
            MediaTttChipControllerSender mediaTttChipControllerSender,
            MediaTttChipControllerReceiver mediaTttChipControllerReceiver,
            @Main DelayableExecutor mainExecutor) {
            MediaTttChipControllerReceiver mediaTttChipControllerReceiver) {
        if (!mediaTttFlags.isMediaTttEnabled()) {
            return Optional.empty();
        }
@@ -130,8 +122,7 @@ public interface MediaModule {
                        commandRegistry,
                        context,
                        mediaTttChipControllerSender,
                        mediaTttChipControllerReceiver,
                        mainExecutor));
                        mediaTttChipControllerReceiver));
    }

    /** Inject into MediaTttSenderService. */
+9 −23
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver
import com.android.systemui.media.taptotransfer.receiver.ChipStateReceiver
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender
@@ -36,15 +35,13 @@ import com.android.systemui.media.taptotransfer.sender.MediaTttSenderService
import com.android.systemui.media.taptotransfer.sender.MoveCloserToEndCast
import com.android.systemui.media.taptotransfer.sender.MoveCloserToStartCast
import com.android.systemui.media.taptotransfer.sender.TransferFailed
import com.android.systemui.media.taptotransfer.sender.TransferInitiated
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverTriggered
import com.android.systemui.media.taptotransfer.sender.TransferSucceeded
import com.android.systemui.shared.mediattt.DeviceInfo
import com.android.systemui.shared.mediattt.IDeviceSenderCallback
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.concurrency.DelayableExecutor
import java.io.PrintWriter
import java.util.concurrent.FutureTask
import javax.inject.Inject

/**
@@ -57,7 +54,6 @@ class MediaTttCommandLineHelper @Inject constructor(
    private val context: Context,
    private val mediaTttChipControllerSender: MediaTttChipControllerSender,
    private val mediaTttChipControllerReceiver: MediaTttChipControllerReceiver,
    @Main private val mainExecutor: DelayableExecutor,
) {
    private var senderCallback: IDeviceSenderCallback? = null
    private val senderServiceConnection = SenderServiceConnection()
@@ -97,22 +93,13 @@ class MediaTttCommandLineHelper @Inject constructor(
                        senderCallback.closeToReceiverToEndCast(mediaInfo, otherDeviceInfo)
                    }
                }

                // TODO(b/203800643): Migrate other commands to invoke the service instead of the
                //   controller.
                TRANSFER_INITIATED_COMMAND_NAME -> {
                    val futureTask = FutureTask { fakeUndoRunnable }
                    mediaTttChipControllerSender.displayChip(
                        TransferInitiated(
                            appIconDrawable,
                            APP_ICON_CONTENT_DESCRIPTION,
                            otherDeviceName,
                            futureTask
                        )
                    )
                    mainExecutor.executeDelayed({ futureTask.run() }, FUTURE_WAIT_TIME)

                TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME -> {
                    runOnService { senderCallback ->
                        senderCallback.transferToReceiverTriggered(mediaInfo, otherDeviceInfo)
                    }
                }
                // TODO(b/203800643): Migrate this command to invoke the service instead of the
                //   controller.
                TRANSFER_SUCCEEDED_COMMAND_NAME -> {
                    mediaTttChipControllerSender.displayChip(
                        TransferSucceeded(
@@ -132,7 +119,7 @@ class MediaTttCommandLineHelper @Inject constructor(
                    pw.println("Chip type must be one of " +
                            "$MOVE_CLOSER_TO_START_CAST_COMMAND_NAME, " +
                            "$MOVE_CLOSER_TO_END_CAST_COMMAND_NAME, " +
                            "$TRANSFER_INITIATED_COMMAND_NAME, " +
                            "$TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME, " +
                            "$TRANSFER_SUCCEEDED_COMMAND_NAME, " +
                            TRANSFER_FAILED_COMMAND_NAME
                    )
@@ -242,12 +229,11 @@ val MOVE_CLOSER_TO_START_CAST_COMMAND_NAME = MoveCloserToStartCast::class.simple
@VisibleForTesting
val MOVE_CLOSER_TO_END_CAST_COMMAND_NAME = MoveCloserToEndCast::class.simpleName!!
@VisibleForTesting
val TRANSFER_INITIATED_COMMAND_NAME = TransferInitiated::class.simpleName!!
val TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME = TransferToReceiverTriggered::class.simpleName!!
@VisibleForTesting
val TRANSFER_SUCCEEDED_COMMAND_NAME = TransferSucceeded::class.simpleName!!
@VisibleForTesting
val TRANSFER_FAILED_COMMAND_NAME = TransferFailed::class.simpleName!!

private const val FUTURE_WAIT_TIME = 2000L
private const val APP_ICON_CONTENT_DESCRIPTION = "Fake media app icon"
private const val TAG = "MediaTapToTransferCli"
+4 −10
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.graphics.drawable.Drawable
import androidx.annotation.StringRes
import com.android.systemui.R
import com.android.systemui.media.taptotransfer.common.MediaTttChipState
import java.util.concurrent.Future

/**
 * A class that stores all the information necessary to display the media tap-to-transfer chip on
@@ -72,18 +71,13 @@ class MoveCloserToEndCast(
)

/**
 * A state representing that a transfer has been initiated (but not completed).
 *
 * @property future a future that will be resolved when the transfer has either succeeded or failed.
 *   If the transfer succeeded, the future can optionally return an undo runnable (see
 *   [TransferSucceeded.undoRunnable]). [MediaTttChipControllerSender] is responsible for transitioning
 *   the chip to the [TransferSucceeded] state if the future resolves successfully.
 * A state representing that a transfer to the receiver device has been initiated (but not
 * completed).
 */
class TransferInitiated(
class TransferToReceiverTriggered(
    appIconDrawable: Drawable,
    appIconContentDescription: String,
    otherDeviceName: String,
    val future: Future<Runnable?>
    otherDeviceName: String
) : ChipStateSender(
    appIconDrawable,
    appIconContentDescription,
+1 −49
Original line number Diff line number Diff line
@@ -23,11 +23,7 @@ import android.view.WindowManager
import android.widget.TextView
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import javax.inject.Inject

/**
@@ -38,8 +34,6 @@ import javax.inject.Inject
class MediaTttChipControllerSender @Inject constructor(
    context: Context,
    windowManager: WindowManager,
    @Main private val mainExecutor: Executor,
    @Background private val backgroundExecutor: Executor,
) : MediaTttChipControllerCommon<ChipStateSender>(
    context, windowManager, R.layout.media_ttt_chip
) {
@@ -55,7 +49,7 @@ class MediaTttChipControllerSender @Inject constructor(
        }

        // Loading
        val showLoading = chipState is TransferInitiated
        val showLoading = chipState is TransferToReceiverTriggered
        currentChipView.requireViewById<View>(R.id.loading).visibility =
            if (showLoading) { View.VISIBLE } else { View.GONE }

@@ -77,47 +71,5 @@ class MediaTttChipControllerSender @Inject constructor(
        val showFailure = chipState is TransferFailed
        currentChipView.requireViewById<View>(R.id.failure_icon).visibility =
            if (showFailure) { View.VISIBLE } else { View.GONE }

        // Future handling
        if (chipState is TransferInitiated) {
            addFutureCallback(chipState)
        }
    }

    /**
     * Adds the appropriate callbacks to [chipState.future] so that we update the chip correctly
     * when the future resolves.
     */
    private fun addFutureCallback(chipState: TransferInitiated) {
        // Listen to the future on a background thread so we don't occupy the main thread while we
        // wait for it to complete.
        backgroundExecutor.execute {
            try {
                val undoRunnable = chipState.future.get(TRANSFER_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                // Make UI changes on the main thread
                mainExecutor.execute {
                    displayChip(
                        TransferSucceeded(
                            chipState.appIconDrawable,
                            chipState.appIconContentDescription,
                            chipState.otherDeviceName,
                            undoRunnable
                        )
                    )
    }
            } catch (ex: Exception) {
                mainExecutor.execute {
                    displayChip(
                        TransferFailed(
                            chipState.appIconDrawable,
                            chipState.appIconContentDescription,
                            chipState.otherDeviceName,
                        )
                    )
}
            }
        }
    }
}

private const val TRANSFER_TIMEOUT_SECONDS = 10L
Loading