SetArcTransmissionStateAction.java revision 5fba96df30b6b50b3cb9fe1d783320b1cc3bd6ea
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.hdmi; 18 19import android.hardware.hdmi.HdmiCecDeviceInfo; 20import android.util.Slog; 21 22/** 23 * Feature action that handles enabling/disabling of ARC transmission channel. 24 * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver. 25 * If it fails or it gets <Terminate ARC>, TV just disables ARC. 26 */ 27final class SetArcTransmissionStateAction extends FeatureAction { 28 private static final String TAG = "SetArcTransmissionStateAction"; 29 30 // State in which the action sent <Rerpot Arc Initiated> and 31 // is waiting for time out. If it receives <Feature Abort> within timeout 32 // ARC should be disabled. 33 private static final int STATE_WAITING_TIMEOUT = 1; 34 35 private final boolean mEnabled; 36 private final int mAvrAddress; 37 38 /** 39 * @Constructor 40 * 41 * @param source {@link HdmiCecLocalDevice} instance 42 * @param enabled whether to enable ARC Transmission channel 43 */ 44 SetArcTransmissionStateAction(HdmiCecLocalDevice source, int avrAddress, 45 boolean enabled) { 46 super(source); 47 HdmiUtils.verifyAddressType(getSourceAddress(), HdmiCecDeviceInfo.DEVICE_TV); 48 HdmiUtils.verifyAddressType(avrAddress, HdmiCecDeviceInfo.DEVICE_AUDIO_SYSTEM); 49 mAvrAddress = avrAddress; 50 mEnabled = enabled; 51 } 52 53 @Override 54 boolean start() { 55 if (mEnabled) { 56 sendReportArcInitiated(); 57 } else { 58 setArcStatus(false); 59 finish(); 60 } 61 return true; 62 } 63 64 private void sendReportArcInitiated() { 65 HdmiCecMessage command = 66 HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress); 67 sendCommand(command, new HdmiControlService.SendMessageCallback() { 68 @Override 69 public void onSendCompleted(int error) { 70 if (error == Constants.SEND_RESULT_SUCCESS) { 71 // Enable ARC status immediately after sending <Report Arc Initiated>. 72 // If AVR responds with <Feature Abort>, disable ARC status again. 73 // This is different from spec that says that turns ARC status to 74 // "Enabled" if <Report ARC Initiated> is acknowledged and no 75 // <Feature Abort> is received. 76 // But implemented this way to save the time having to wait for 77 // <Feature Abort>. 78 setArcStatus(true); 79 // If succeeds to send <Report ARC Initiated>, wait general timeout 80 // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 81 mState = STATE_WAITING_TIMEOUT; 82 addTimer(mState, HdmiConfig.TIMEOUT_MS); 83 } else { 84 // If fails to send <Report ARC Initiated>, disable ARC and 85 // send <Report ARC Terminated> directly. 86 setArcStatus(false); 87 finish(); 88 } 89 } 90 }); 91 } 92 93 private void setArcStatus(boolean enabled) { 94 boolean wasEnabled = tv().setArcStatus(enabled); 95 Slog.i(TAG, "Change arc status [old:" + wasEnabled + " ,new:" + enabled); 96 97 // If enabled before and set to "disabled" and send <Report Arc Terminated> to 98 // av reciever. 99 if (!enabled && wasEnabled) { 100 sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(), 101 mAvrAddress)); 102 } 103 } 104 105 @Override 106 boolean processCommand(HdmiCecMessage cmd) { 107 if (mState != STATE_WAITING_TIMEOUT) { 108 return false; 109 } 110 111 int opcode = cmd.getOpcode(); 112 if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 113 setArcStatus(false); 114 } 115 finish(); 116 return true; 117 } 118 119 @Override 120 void handleTimerEvent(int state) { 121 if (mState != state || mState != STATE_WAITING_TIMEOUT) { 122 return; 123 } 124 // Expire timeout for <Feature Abort>. 125 finish(); 126 } 127} 128