SetArcTransmissionStateAction.java revision 63a2e0696ce2a04fbe0f1f00cfe9c93189f944da
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.HdmiCec; 20import android.hardware.hdmi.HdmiCecMessage; 21import android.util.Slog; 22 23/** 24 * Feature action that handles enabling/disabling of ARC transmission channel. 25 * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver. 26 * If it fails or it gets <Terminate ARC>, TV just disables ARC. 27 */ 28final class SetArcTransmissionStateAction extends FeatureAction { 29 private static final String TAG = "SetArcTransmissionStateAction"; 30 31 // State in which the action sent <Rerpot Arc Initiated> and 32 // is waiting for time out. If it receives <Feature Abort> within timeout 33 // ARC should be disabled. 34 private static final int STATE_WAITING_TIMEOUT = 1; 35 36 private final boolean mEnabled; 37 private final int mAvrAddress; 38 39 /** 40 * @Constructor 41 * 42 * @param service an instance of {@link HdmiControlService} 43 * @param sourceAddress logical address to be used as source address 44 * @param enabled whether to enable ARC Transmission channel 45 */ 46 SetArcTransmissionStateAction(HdmiControlService service, int sourceAddress, int avrAddress, 47 boolean enabled) { 48 super(service, sourceAddress); 49 HdmiUtils.verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV); 50 HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM); 51 mAvrAddress = avrAddress; 52 mEnabled = enabled; 53 } 54 55 @Override 56 boolean start() { 57 if (mEnabled) { 58 sendReportArcInitiated(); 59 } else { 60 setArcStatus(false); 61 finish(); 62 } 63 return true; 64 } 65 66 private void sendReportArcInitiated() { 67 HdmiCecMessage command = 68 HdmiCecMessageBuilder.buildReportArcInitiated(mSourceAddress, mAvrAddress); 69 sendCommand(command, new HdmiControlService.SendMessageCallback() { 70 @Override 71 public void onSendCompleted(int error) { 72 if (error == HdmiControlService.SEND_RESULT_SUCCESS) { 73 // Enable ARC status immediately after sending <Report Arc Initiated>. 74 // If AVR responds with <Feature Abort>, disable ARC status again. 75 // This is different from spec that says that turns ARC status to 76 // "Enabled" if <Report ARC Initiated> is acknowledged and no 77 // <Feature Abort> is received. 78 // But implemented this way to save the time having to wait for 79 // <Feature Abort>. 80 setArcStatus(true); 81 // If succeeds to send <Report ARC Initiated>, wait general timeout 82 // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 83 mState = STATE_WAITING_TIMEOUT; 84 addTimer(mState, TIMEOUT_MS); 85 } else { 86 // If fails to send <Report ARC Initiated>, disable ARC and 87 // send <Report ARC Terminated> directly. 88 setArcStatus(false); 89 finish(); 90 } 91 } 92 }); 93 } 94 95 private void setArcStatus(boolean enabled) { 96 boolean wasEnabled = mService.setArcStatus(enabled); 97 Slog.i(TAG, "Change arc status [old:" + wasEnabled + " ,new:" + enabled); 98 99 // If enabled before and set to "disabled" and send <Report Arc Terminated> to 100 // av reciever. 101 if (!enabled && wasEnabled) { 102 sendCommand( 103 HdmiCecMessageBuilder.buildReportArcTerminated(mSourceAddress, mAvrAddress)); 104 } 105 } 106 107 @Override 108 boolean processCommand(HdmiCecMessage cmd) { 109 if (mState != STATE_WAITING_TIMEOUT) { 110 return false; 111 } 112 113 int opcode = cmd.getOpcode(); 114 if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) { 115 setArcStatus(false); 116 } 117 finish(); 118 return true; 119 } 120 121 @Override 122 void handleTimerEvent(int state) { 123 if (mState != state || mState != STATE_WAITING_TIMEOUT) { 124 return; 125 } 126 // Expire timeout for <Feature Abort>. 127 finish(); 128 } 129} 130