SetArcTransmissionStateAction.java revision 67ea521d14f366fe5aac09e512865d31bfa0ee53
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 verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV); 50 verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM); 51 mAvrAddress = avrAddress; 52 mEnabled = enabled; 53 } 54 55 // TODO: extract it as separate utility class. 56 private static void verifyAddressType(int logicalAddress, int deviceType) { 57 int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress); 58 if (actualDeviceType != deviceType) { 59 throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType 60 + ", Actual:" + actualDeviceType); 61 } 62 } 63 64 @Override 65 boolean start() { 66 if (mEnabled) { 67 if (sendCommand( 68 HdmiCecMessageBuilder.buildReportArcInitiated(mSourceAddress, mAvrAddress))) { 69 // Enable ARC status immediately after sending <Report Arc Initiated>. 70 // If AVR responds with <Feature Abort>, disable ARC status again. 71 // This is different from spec that says that turns ARC status to "Enabled" 72 // if <Report ARC Initiated> is acknowledged and no <Feature Abort> is received. 73 // But implemented this way to save the time having to wait for <Feature Abort>. 74 setArcStatus(true); 75 // If succeeds to send <Report ARC Initiated>, wait general timeout 76 // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 77 mState = STATE_WAITING_TIMEOUT; 78 addTimer(mState, TIMEOUT_MS); 79 } else { 80 // If fails to send <Report ARC Initiated>, disable ARC and 81 // send <Report ARC Terminated> directly. 82 Slog.w(TAG, "Failed to send <Report ARC Initiated>:[source:" + mSourceAddress 83 + ", avr Address:" + mAvrAddress + "]"); 84 setArcStatus(false); 85 finish(); 86 } 87 } else { 88 setArcStatus(false); 89 finish(); 90 } 91 return true; 92 } 93 94 private void setArcStatus(boolean enabled) { 95 boolean wasEnabled = mService.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( 102 HdmiCecMessageBuilder.buildReportArcTerminated(mSourceAddress, 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