SetArcTransmissionStateAction.java revision 3ecdd832c77483c909fbf90d17d0e6d97ca365ee
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 source {@link HdmiCecLocalDevice} instance 43 * @param enabled whether to enable ARC Transmission channel 44 */ 45 SetArcTransmissionStateAction(HdmiCecLocalDevice source, int avrAddress, 46 boolean enabled) { 47 super(source); 48 HdmiUtils.verifyAddressType(getSourceAddress(), HdmiCec.DEVICE_TV); 49 HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM); 50 mAvrAddress = avrAddress; 51 mEnabled = enabled; 52 } 53 54 @Override 55 boolean start() { 56 if (mEnabled) { 57 sendReportArcInitiated(); 58 } else { 59 setArcStatus(false); 60 finish(); 61 } 62 return true; 63 } 64 65 private void sendReportArcInitiated() { 66 HdmiCecMessage command = 67 HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress); 68 sendCommand(command, new HdmiControlService.SendMessageCallback() { 69 @Override 70 public void onSendCompleted(int error) { 71 if (error == HdmiConstants.SEND_RESULT_SUCCESS) { 72 // Enable ARC status immediately after sending <Report Arc Initiated>. 73 // If AVR responds with <Feature Abort>, disable ARC status again. 74 // This is different from spec that says that turns ARC status to 75 // "Enabled" if <Report ARC Initiated> is acknowledged and no 76 // <Feature Abort> is received. 77 // But implemented this way to save the time having to wait for 78 // <Feature Abort>. 79 setArcStatus(true); 80 // If succeeds to send <Report ARC Initiated>, wait general timeout 81 // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 82 mState = STATE_WAITING_TIMEOUT; 83 addTimer(mState, TIMEOUT_MS); 84 } else { 85 // If fails to send <Report ARC Initiated>, disable ARC and 86 // send <Report ARC Terminated> directly. 87 setArcStatus(false); 88 finish(); 89 } 90 } 91 }); 92 } 93 94 private void setArcStatus(boolean enabled) { 95 boolean wasEnabled = tv().setArcStatus(enabled); 96 Slog.i(TAG, "Change arc status [old:" + wasEnabled + " ,new:" + enabled); 97 98 // If enabled before and set to "disabled" and send <Report Arc Terminated> to 99 // av reciever. 100 if (!enabled && wasEnabled) { 101 sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(), 102 mAvrAddress)); 103 } 104 } 105 106 @Override 107 boolean processCommand(HdmiCecMessage cmd) { 108 if (mState != STATE_WAITING_TIMEOUT) { 109 return false; 110 } 111 112 int opcode = cmd.getOpcode(); 113 if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) { 114 setArcStatus(false); 115 } 116 finish(); 117 return true; 118 } 119 120 @Override 121 void handleTimerEvent(int state) { 122 if (mState != state || mState != STATE_WAITING_TIMEOUT) { 123 return; 124 } 125 // Expire timeout for <Feature Abort>. 126 finish(); 127 } 128} 129