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

Commit 2d869ca2 authored by Paul Colța's avatar Paul Colța Committed by Android (Google) Code Review
Browse files

Merge "HDMI: Retry sending source changing CEC messages if they fail"

parents d278ca17 b5b89048
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -286,6 +286,17 @@ public class HdmiCecMessageBuilder {
        return HdmiCecMessage.build(src, dest, Constants.MESSAGE_TEXT_VIEW_ON);
    }

    /**
     * Build <Image View On> command.
     *
     * @param src source address of command
     * @param dest destination address of command
     * @return newly created {@link HdmiCecMessage}
     */
    static HdmiCecMessage buildImageViewOn(int src, int dest) {
        return HdmiCecMessage.build(src, dest, Constants.MESSAGE_IMAGE_VIEW_ON);
    }

    /**
     * Build <Request Active Source> command.
     *
+26 −1
Original line number Diff line number Diff line
@@ -1529,8 +1529,33 @@ public class HdmiControlService extends SystemService {
    @ServiceThreadOnly
    void sendCecCommand(HdmiCecMessage command) {
        assertRunOnServiceThread();
        switch (command.getOpcode()) {
            case Constants.MESSAGE_ACTIVE_SOURCE:
            case Constants.MESSAGE_IMAGE_VIEW_ON:
            case Constants.MESSAGE_INACTIVE_SOURCE:
            case Constants.MESSAGE_ROUTING_CHANGE:
            case Constants.MESSAGE_SET_STREAM_PATH:
            case Constants.MESSAGE_TEXT_VIEW_ON:
                sendCecCommandWithRetries(command);
                break;
            default:
                sendCecCommand(command, null);
        }
    }

    /**
     * Create a {@link SendCecCommandAction} that will retry to send the CEC message in case it
     * fails.
     * @param command that has to be sent in the CEC bus.
     */
    @ServiceThreadOnly
    public void sendCecCommandWithRetries(HdmiCecMessage command) {
        assertRunOnServiceThread();
        HdmiCecLocalDevice localDevice = getAllCecLocalDevices().get(0);
        if (localDevice != null) {
            localDevice.addAndStartAction(new SendCecCommandAction(localDevice, command));
        }
    }

    /**
     * Send <Feature Abort> command on the given CEC message if possible.
+78 −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.server.hdmi;

import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.util.Slog;

import com.android.server.hdmi.HdmiControlService.SendMessageCallback;

/**
 * Action that sends a CEC command. If the message fails to be sent, it tries again for
 * RETRANSMISSION_COUNT times.
 */
public class SendCecCommandAction extends HdmiCecFeatureAction {
    private static final String TAG = "SendCecCommandAction";
    private static final int RETRANSMISSION_COUNT = 2;
    private static final int STATE_WAIT_FOR_RESEND_COMMAND = 1;
    static final int SEND_COMMAND_RETRY_MS = 300;

    private final HdmiCecMessage mCommand;
    private int mRetransmissionCount = 0;
    private final SendMessageCallback mCallback = new SendMessageCallback(){
        @Override
        public void onSendCompleted(int result) {
            if (result != SendMessageResult.SUCCESS
                    && mRetransmissionCount++ < RETRANSMISSION_COUNT) {
                mState = STATE_WAIT_FOR_RESEND_COMMAND;
                addTimer(mState, SEND_COMMAND_RETRY_MS);
            } else {
                finish();
            }
        }
    };

    SendCecCommandAction(HdmiCecLocalDevice source, HdmiCecMessage command) {
        super(source);
        mCommand = command;
    }

    @Override
    boolean start() {
        Slog.d(TAG, "SendCecCommandAction started");
        sendCommand(mCommand, mCallback);
        return true;
    }

    @Override
    void handleTimerEvent(int state) {
        if (mState != state) {
            Slog.w(TAG, "Timeout in invalid state:[Expected:" + mState + ", Actual:" + state
                    + "]");
            return;
        }
        if (mState == STATE_WAIT_FOR_RESEND_COMMAND) {
            Slog.d(TAG, "sendCecCommand failed, retry");
            sendCommand(mCommand, mCallback);
        }
    }

    @Override
    boolean processCommand(HdmiCecMessage command) {
        return false;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -118,6 +118,11 @@ public class DeviceSelectActionFromPlaybackTest {
                    boolean isPowerStandbyOrTransient() {
                        return false;
                    }

                    @Override
                    boolean isPowerStandby() {
                        return false;
                    }
                };


+5 −0
Original line number Diff line number Diff line
@@ -127,6 +127,11 @@ public class DeviceSelectActionFromTvTest {
                    boolean isPowerStandbyOrTransient() {
                        return false;
                    }

                    @Override
                    boolean isPowerStandby() {
                        return false;
                    }
                };


Loading