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

Commit 21804484 authored by Shubang Lu's avatar Shubang Lu Committed by Android (Google) Code Review
Browse files

Merge "Add ArcInitiationActionFromAvr"

parents c132a051 81170dac
Loading
Loading
Loading
Loading
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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;

/**
 * Feature action that handles Audio Return Channel initiated by AVR devices.
 */
public class ArcInitiationActionFromAvr extends HdmiCecFeatureAction {
    // TODO(shubang): add tests

    // State in which waits for ARC response.
    private static final int STATE_WAITING_FOR_INITIATE_ARC_RESPONSE = 1;
    private static final int STATE_ARC_INITIATED = 2;

    // the required maximum response time specified in CEC 9.2
    private static final int TIMEOUT_MS = 1000;

    ArcInitiationActionFromAvr(HdmiCecLocalDevice source) {
        super(source);
    }

    @Override
    boolean start() {
        audioSystem().setArcStatus(true);
        mState = STATE_WAITING_FOR_INITIATE_ARC_RESPONSE;
        addTimer(mState, TIMEOUT_MS);
        sendInitiateArc();
        return true;
    }

    @Override
    boolean processCommand(HdmiCecMessage cmd) {
        if (mState != STATE_WAITING_FOR_INITIATE_ARC_RESPONSE) {
            return false;
        }
        switch (cmd.getOpcode()) {
            case Constants.MESSAGE_FEATURE_ABORT:
            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
                audioSystem().setArcStatus(false);
                finish();
                return true;
            case Constants.MESSAGE_REPORT_ARC_INITIATED:
                mState = STATE_ARC_INITIATED;
                finish();
                return true;
        }
        return false;
    }

    @Override
    void handleTimerEvent(int state) {
        if (mState != state) {
            return;
        }

        switch (mState) {
            case STATE_WAITING_FOR_INITIATE_ARC_RESPONSE:
                handleInitiateArcTimeout();
                break;
        }
    }

    protected void sendInitiateArc() {
        sendCommand(HdmiCecMessageBuilder.buildInitiateArc(getSourceAddress(), Constants.ADDR_TV),
                result -> {
                    if (result != SendMessageResult.SUCCESS) {
                        audioSystem().setArcStatus(false);
                        finish();
                    }
                });
    }

    private void handleInitiateArcTimeout() {
        HdmiLogger.debug("handleInitiateArcTimeout");
        audioSystem().setArcStatus(false);
        finish();
    }

}
+39 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONT

import android.hardware.hdmi.HdmiDeviceInfo;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.SystemProperties;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -45,6 +46,11 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice {

    private boolean mTvSystemAudioModeSupport;

    // Whether ARC is available or not. "true" means that ARC is established between TV and
    // AVR as audio receiver.
    @ServiceThreadOnly
    private boolean mArcEstablished = false;

    protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) {
        super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
        mSystemAudioControlFeatureEnabled = true;
@@ -256,6 +262,39 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice {
        return true;
    }

    @ServiceThreadOnly
    void setArcStatus(boolean enabled) {
        // TODO(shubang): add tests
        assertRunOnServiceThread();

        HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled);
        // 1. Enable/disable ARC circuit.
        enableAudioReturnChannel(enabled);
        // 2. Notify arc status to audio service.
        notifyArcStatusToAudioService(enabled);
        // 3. Update arc status;
        mArcEstablished = enabled;
    }

    /**
     * Switch hardware ARC circuit in the system.
     */
    @ServiceThreadOnly
    private void enableAudioReturnChannel(boolean enabled) {
        assertRunOnServiceThread();
        mService.enableAudioReturnChannel(
                SystemProperties.getInt(
                        Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, 0),
                enabled);
    }

    private void notifyArcStatusToAudioService(boolean enabled) {
        // Note that we don't set any name to ARC.
        mService.getAudioManager().setWiredDeviceConnectionState(
                AudioSystem.DEVICE_IN_HDMI,
                enabled ? 1 : 0, "", "");
    }

    private void reportAudioStatus(HdmiCecMessage message) {
        assertRunOnServiceThread();